[Xfce4-commits] <thunar:master> Smarter file extension selecting (bug #10268).

Nick Schermer noreply at xfce.org
Sun Jul 28 12:30:01 CEST 2013


Updating branch refs/heads/master
         to 5e25c200fa3071e4c0a47d2f621e45819f42706f (commit)
       from 82701c297ac6788db64a251e10d77f96f04486ce (commit)

commit 5e25c200fa3071e4c0a47d2f621e45819f42706f
Author: Jeff Shipley <jshipley at fastmail.fm>
Date:   Sun Jul 28 12:25:34 2013 +0200

    Smarter file extension selecting (bug #10268).
    
    Instead of simply looking for the last '.' in the filename,
    do a better job at selecting compound filenames like
    .tar.gz and development files like .desktop.in.in.

 thunar/thunar-create-dialog.c     |    2 +-
 thunar/thunar-dialogs.c           |    4 +-
 thunar/thunar-properties-dialog.c |    6 +--
 thunar/thunar-renamer-model.c     |    7 ++-
 thunar/thunar-text-renderer.c     |    3 +-
 thunar/thunar-util.c              |  107 +++++++++++++++++++++++++++++++++++++
 thunar/thunar-util.h              |    2 +
 7 files changed, 119 insertions(+), 12 deletions(-)

diff --git a/thunar/thunar-create-dialog.c b/thunar/thunar-create-dialog.c
index 781b060..f31f337 100644
--- a/thunar/thunar-create-dialog.c
+++ b/thunar/thunar-create-dialog.c
@@ -329,7 +329,7 @@ thunar_create_dialog_set_filename (ThunarCreateDialog *dialog,
   gtk_entry_set_text (GTK_ENTRY (dialog->entry), filename);
 
   /* check if filename contains a dot */
-  dot = g_utf8_strrchr (filename, -1, '.');
+  dot = thunar_util_str_get_extension (filename);
   if (G_LIKELY (dot != NULL))
     {
       /* grab focus to the entry first, else
diff --git a/thunar/thunar-dialogs.c b/thunar/thunar-dialogs.c
index 953d4f5..99b9e54 100644
--- a/thunar/thunar-dialogs.c
+++ b/thunar/thunar-dialogs.c
@@ -137,8 +137,8 @@ thunar_dialogs_show_rename_file (gpointer    parent,
   /* check if we don't have a directory here */
   if (!thunar_file_is_directory (file))
     {
-      /* check if the filename contains a dot */
-      text = g_utf8_strrchr (filename, -1, '.');
+      /* check if the filename contains an extension */
+      text = thunar_util_str_get_extension (filename);
       if (G_LIKELY (text != NULL))
         {
           /* grab focus to the entry first, else the selection will be altered later */
diff --git a/thunar/thunar-properties-dialog.c b/thunar/thunar-properties-dialog.c
index f5e5483..6e6fa8d 100644
--- a/thunar/thunar-properties-dialog.c
+++ b/thunar/thunar-properties-dialog.c
@@ -56,6 +56,7 @@
 #include <thunar/thunar-properties-dialog.h>
 #include <thunar/thunar-size-label.h>
 #include <thunar/thunar-thumbnailer.h>
+#include <thunar/thunar-util.h>
 
 
 
@@ -913,7 +914,7 @@ thunar_properties_dialog_update_single (ThunarPropertiesDialog *dialog)
       gtk_widget_grab_focus (dialog->name_entry);
 
       /* select the pre-dot part of the name */
-      str = strrchr (name, '.');
+      str = thunar_util_str_get_extension (name);
       if (G_LIKELY (str != NULL))
         {
           /* calculate the offset */
@@ -1260,9 +1261,6 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
 
       /* update the properties for a dialog showing 1 file */
       thunar_properties_dialog_update_single (dialog);
-
-      /* place the initial focus on the name entry widget */
-      gtk_widget_grab_focus (dialog->name_entry);
     }
   else
     {
diff --git a/thunar/thunar-renamer-model.c b/thunar/thunar-renamer-model.c
index 853b797..3d8c209 100644
--- a/thunar/thunar-renamer-model.c
+++ b/thunar/thunar-renamer-model.c
@@ -33,6 +33,7 @@
 #include <thunar/thunar-gobject-extensions.h>
 #include <thunar/thunar-private.h>
 #include <thunar/thunar-renamer-model.h>
+#include <thunar/thunar-util.h>
 
 
 
@@ -819,10 +820,8 @@ thunar_renamer_model_process_item (ThunarRenamerModel     *renamer_model,
   /* determine the current display name of the file */
   display_name = thunar_file_get_display_name (item->file);
 
-  /* determine the last dot in the filename */
-  dot = strrchr (display_name, '.');
-  if (G_UNLIKELY (dot == display_name || (dot != NULL && dot[1] == '\0')))
-    dot = NULL;
+  /* determine the extension in the filename */
+  dot = thunar_util_str_get_extension (display_name);
 
   /* if we don't have a dot, then no "Suffix only" rename can take place */
   if (G_LIKELY (dot != NULL || renamer_model->mode != THUNAR_RENAMER_MODE_SUFFIX))
diff --git a/thunar/thunar-text-renderer.c b/thunar/thunar-text-renderer.c
index 8b111cc..d85f65a 100644
--- a/thunar/thunar-text-renderer.c
+++ b/thunar/thunar-text-renderer.c
@@ -34,6 +34,7 @@
 #include <thunar/thunar-marshal.h>
 #include <thunar/thunar-pango-extensions.h>
 #include <thunar/thunar-text-renderer.h>
+#include <thunar/thunar-util.h>
 
 
 
@@ -756,7 +757,7 @@ thunar_text_renderer_grab_focus (GtkWidget          *entry,
   text = gtk_entry_get_text (GTK_ENTRY (entry));
 
   /* lookup the last dot in the text */
-  dot = strrchr (text, '.');
+  dot = thunar_util_str_get_extension (text);
   if (G_LIKELY (dot != NULL))
     {
       /* determine the UTF-8 char offset */
diff --git a/thunar/thunar-util.c b/thunar/thunar-util.c
index 7b8665f..77a36f9 100644
--- a/thunar/thunar-util.c
+++ b/thunar/thunar-util.c
@@ -62,6 +62,113 @@
 
 
 
+/**
+ * thunar_util_strrchr_offset:
+ * @str:    haystack
+ * @offset: pointer offset in @str
+ * @c:      search needle
+ *
+ * Return the last occurrence of the character @c in
+ * the string @str starting at @offset.
+ *
+ * There are also Glib functions for this like g_strrstr_len
+ * and g_utf8_strrchr, but these work internally the same
+ * as this function (tho, less efficient).
+ *
+ * Return value: pointer in @str or NULL.
+ **/
+static inline gchar *
+thunar_util_strrchr_offset (const gchar *str,
+                            const gchar *offset,
+                            gchar        c)
+{
+  const gchar *p;
+
+  for (p = offset; p > str; p--)
+    if (*p == c)
+      return (gchar *) p;
+
+  return NULL;
+}
+
+
+
+/**
+ * thunar_util_str_get_extension
+ * @filename : an UTF-8 filename
+ *
+ * Returns a pointer to the extension in @filename.
+ *
+ * This is an improved version of g_utf8_strrchr with
+ * improvements to recognize compound extensions like
+ * ".tar.gz" and ".desktop.in.in".
+ *
+ * Return value: pointer to the extension in @filename
+ *               or NULL.
+**/
+gchar *
+thunar_util_str_get_extension (const gchar *filename)
+{
+  static const gchar *compressed[] = { "gz", "bz2", "lzma", "lrz", "rpm", "lzo", "xz", "z" };
+  gchar              *dot;
+  gchar              *ext;
+  guint               i;
+  gchar              *dot2;
+  gsize               len;
+  gboolean            is_in;
+
+  /* check if there is an possible extension part in the name */
+  dot = strrchr (filename, '.');
+  if (dot == NULL || dot[1] == '\0')
+    return NULL;
+
+  /* skip the . */
+  ext = dot + 1;
+
+  /* check if this looks like a compression mime-type */
+  for (i = 0; i < G_N_ELEMENTS (compressed); i++)
+    {
+      if (strcasecmp (ext, compressed[i]) == 0)
+        {
+          /* look for a possible container part (tar, psd, epsf) */
+          dot2 = thunar_util_strrchr_offset (filename, dot - 1, '.');
+          if (dot2 != NULL)
+            {
+              /* check the 2nd part range, keep it between 2 and 5 chars */
+              len = dot - dot2 - 1;
+              if (len >= 2 && len <= 5)
+                dot = dot2;
+            }
+
+          /* that's it for compression types */
+          return dot;
+        }
+    }
+
+  /* for coders, .in are quite common, so check for those too
+   * with a max of 3 rounds (2x .in and the possibly final extension) */
+  if (strcasecmp (ext, "in") == 0)
+    {
+      for (i = 0, is_in = TRUE; is_in && i < 3; i++)
+        {
+          dot2 = thunar_util_strrchr_offset (filename, dot - 1, '.');
+          /* the extension before .in could be long. check that it's at least 2 chars */
+          len = dot - dot2 - 1;
+          if (dot2 == NULL || len < 2)
+            break;
+
+          /* continue if another .in was found */
+          is_in = dot - dot2 == 3 && strncasecmp (dot2, ".in", 3) == 0;
+
+          dot = dot2;
+        }
+    }
+
+  return dot;
+}
+
+
+
 void
 thunar_util_load_bookmarks (GFile               *bookmarks_file,
                             ThunarBookmarksFunc  foreach_func,
diff --git a/thunar/thunar-util.h b/thunar/thunar-util.h
index 8170bdc..b80f070 100644
--- a/thunar/thunar-util.h
+++ b/thunar/thunar-util.h
@@ -31,6 +31,8 @@ typedef void (*ThunarBookmarksFunc) (GFile       *file,
                                      gint         row_num,
                                      gpointer     user_data);
 
+gchar     *thunar_util_str_get_extension        (const gchar *name) G_GNUC_WARN_UNUSED_RESULT;
+
 void       thunar_util_load_bookmarks           (GFile               *bookmarks_file,
                                                  ThunarBookmarksFunc  foreach_func,
                                                  gpointer             user_data);


More information about the Xfce4-commits mailing list