diff --git a/thunar/thunar-dialogs.c b/thunar/thunar-dialogs.c index 953d4f5..9c07f4b 100644 --- a/thunar/thunar-dialogs.c +++ b/thunar/thunar-dialogs.c @@ -138,7 +138,7 @@ thunar_dialogs_show_rename_file (gpointer parent, if (!thunar_file_is_directory (file)) { /* check if the filename contains a dot */ - text = g_utf8_strrchr (filename, -1, '.'); + text = thunar_util_strrchr_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-renamer-model.c b/thunar/thunar-renamer-model.c index 853b797..a021716 100644 --- a/thunar/thunar-renamer-model.c +++ b/thunar/thunar-renamer-model.c @@ -33,6 +33,7 @@ #include #include #include +#include @@ -820,9 +821,7 @@ thunar_renamer_model_process_item (ThunarRenamerModel *renamer_model, 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; + dot = thunar_util_strrchr_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-util.c b/thunar/thunar-util.c index 7b8665f..8ac1fd0 100644 --- a/thunar/thunar-util.c +++ b/thunar/thunar-util.c @@ -62,6 +62,92 @@ +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_strrchr_extension + * @filename : a filename + * + * Returns a pointer to the extension in @filename + * This works for compound extensions like ".tar.gz" +**/ +gchar * +thunar_util_strrchr_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..d08675f 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_strrchr_extension (const gchar *name) G_GNUC_WARN_UNUSED_RESULT; + void thunar_util_load_bookmarks (GFile *bookmarks_file, ThunarBookmarksFunc foreach_func, gpointer user_data);