1
1

patches by Rostislav Beneš: mc-20-dir

changes in sorting strings (name, extension), for comparing are created keys
from strings and than their are compared instead of primary strings. (in
reality, keys are created only for case insensitive comparing, case
sensitive compare original strings). In utf-8 shall by keys faster than
compare strings directly. But this need ediding declaration of all sorts
functions.
Этот коммит содержится в:
Slava Zanko 2008-12-29 01:07:48 +02:00
родитель e57e297ffe
Коммит 26f6eeed8b
4 изменённых файлов: 72 добавлений и 68 удалений

113
src/dir.c
Просмотреть файл

@ -30,6 +30,7 @@
#include "dir.h"
#include "wtools.h"
#include "treestore.h"
#include "strutil.h"
/* If true show files starting with a dot */
int show_dot_files = 1;
@ -59,50 +60,9 @@ sort_orders_t sort_orders [SORT_TYPES_TOTAL] = {
{ N_("&Inode"), sort_inode },
};
#ifdef HAVE_STRCOLL
/*
* g_strcasecmp() doesn't work well in some locales because it relies on
* the locale-specific toupper(). On the other hand, strcoll() is case
* sensitive in the "C" and "POSIX" locales, unlike other locales.
* Solution: always use strcmp() for case sensitive sort. For case
* insensitive sort use strcoll() if it's case insensitive for ASCII and
* g_strcasecmp() otherwise.
*/
typedef enum {
STRCOLL_NO,
STRCOLL_YES,
STRCOLL_TEST
} strcoll_status;
static int string_sortcomp (const char *str1, const char *str2)
{
static strcoll_status use_strcoll = STRCOLL_TEST;
if (case_sensitive) {
return strcmp (str1, str2);
}
/* Initialize use_strcoll once. */
if (use_strcoll == STRCOLL_TEST) {
/* Only use strcoll() if it considers "B" between "a" and "c". */
if (strcoll ("a", "B") * strcoll ("B", "c") > 0) {
use_strcoll = STRCOLL_YES;
} else {
use_strcoll = STRCOLL_NO;
}
}
if (use_strcoll == STRCOLL_NO)
return g_strcasecmp (str1, str2);
else
return strcoll (str1, str2);
}
#else
#define string_sortcomp(a,b) (case_sensitive ? strcmp (a,b) : g_strcasecmp (a,b))
#endif
int
unsorted (const file_entry *a, const file_entry *b)
unsorted (file_entry *a, file_entry *b)
{
(void) a;
(void) b;
@ -110,28 +70,38 @@ unsorted (const file_entry *a, const file_entry *b)
}
int
sort_name (const file_entry *a, const file_entry *b)
sort_name (file_entry *a, file_entry *b)
{
int ad = MY_ISDIR (a);
int bd = MY_ISDIR (b);
if (ad == bd || mix_all_files)
return string_sortcomp (a->fname, b->fname) * reverse;
return bd-ad;
if (ad == bd || mix_all_files) {
/* create key if does not exist, key will be freed after sorting */
if (a->sort_key == NULL)
a->sort_key = str_create_key_for_filename (a->fname, case_sensitive);
if (b->sort_key == NULL)
b->sort_key = str_create_key_for_filename (b->fname, case_sensitive);
return str_key_collate (a->sort_key, b->sort_key, case_sensitive)
* reverse;
}
return bd - ad;
}
int
sort_ext (const file_entry *a, const file_entry *b)
sort_ext (file_entry *a, file_entry *b)
{
const char *exta, *extb;
int r;
int ad = MY_ISDIR (a);
int bd = MY_ISDIR (b);
if (ad == bd || mix_all_files){
exta = extension (a->fname);
extb = extension (b->fname);
r = string_sortcomp (exta, extb);
if (a->second_sort_key == NULL)
a->second_sort_key = str_create_key (extension (a->fname), case_sensitive);
if (b->second_sort_key == NULL)
b->second_sort_key = str_create_key (extension (b->fname), case_sensitive);
r = str_key_collate (a->second_sort_key, b->second_sort_key, case_sensitive);
if (r)
return r * reverse;
else
@ -141,7 +111,7 @@ sort_ext (const file_entry *a, const file_entry *b)
}
int
sort_time (const file_entry *a, const file_entry *b)
sort_time (file_entry *a, file_entry *b)
{
int ad = MY_ISDIR (a);
int bd = MY_ISDIR (b);
@ -159,7 +129,7 @@ sort_time (const file_entry *a, const file_entry *b)
}
int
sort_ctime (const file_entry *a, const file_entry *b)
sort_ctime (file_entry *a, file_entry *b)
{
int ad = MY_ISDIR (a);
int bd = MY_ISDIR (b);
@ -177,7 +147,7 @@ sort_ctime (const file_entry *a, const file_entry *b)
}
int
sort_atime (const file_entry *a, const file_entry *b)
sort_atime (file_entry *a, file_entry *b)
{
int ad = MY_ISDIR (a);
int bd = MY_ISDIR (b);
@ -195,7 +165,7 @@ sort_atime (const file_entry *a, const file_entry *b)
}
int
sort_inode (const file_entry *a, const file_entry *b)
sort_inode (file_entry *a, file_entry *b)
{
int ad = MY_ISDIR (a);
int bd = MY_ISDIR (b);
@ -207,7 +177,7 @@ sort_inode (const file_entry *a, const file_entry *b)
}
int
sort_size (const file_entry *a, const file_entry *b)
sort_size (file_entry *a, file_entry *b)
{
int ad = MY_ISDIR (a);
int bd = MY_ISDIR (b);
@ -224,6 +194,20 @@ sort_size (const file_entry *a, const file_entry *b)
return sort_name (a, b);
}
/* clear keys, should be call after sorting is finished */
static void
clean_sort_keys (dir_list *list, int start, int count)
{
int i;
for (i = 0; i < count; i++){
str_release_key (list->list [i + start].sort_key, case_sensitive);
list->list [i + start].sort_key = NULL;
str_release_key (list->list [i + start].second_sort_key, case_sensitive);
list->list [i + start].second_sort_key = NULL;
}
}
void
do_sort (dir_list *list, sortfn *sort, int top, int reverse_f, int case_sensitive_f)
@ -242,6 +226,8 @@ do_sort (dir_list *list, sortfn *sort, int top, int reverse_f, int case_sensitiv
case_sensitive = case_sensitive_f;
qsort (&(list->list) [dot_dot_found],
top + 1 - dot_dot_found, sizeof (file_entry), sort);
clean_sort_keys (list, dot_dot_found, top + 1 - dot_dot_found);
}
void
@ -251,7 +237,7 @@ clean_dir (dir_list *list, int count)
for (i = 0; i < count; i++){
g_free (list->list [i].fname);
list->list [i].fname = 0;
list->list [i].fname = NULL;
}
}
@ -422,6 +408,8 @@ do_load_dir (const char *path, dir_list *list, sortfn *sort, int reverse,
list->list[next_free].f.stale_link = stale_link;
list->list[next_free].f.dir_size_computed = 0;
list->list[next_free].st = st;
list->list[next_free].sort_key = NULL;
list->list[next_free].second_sort_key = NULL;
next_free++;
if (!(next_free % 32))
rotate_dash ();
@ -474,8 +462,11 @@ alloc_dir_copy (int size)
}
dir_copy.list = g_new (file_entry, size);
for (i = 0; i < size; i++)
dir_copy.list [i].fname = 0;
for (i = 0; i < size; i++) {
dir_copy.list [i].fname = NULL;
dir_copy.list [i].sort_key = NULL;
dir_copy.list [i].second_sort_key = NULL;
}
dir_copy.size = size;
}
@ -512,6 +503,8 @@ do_reload_dir (const char *path, dir_list *list, sortfn *sort, int count,
list->list[i].f.dir_size_computed;
dir_copy.list[i].f.link_to_dir = list->list[i].f.link_to_dir;
dir_copy.list[i].f.stale_link = list->list[i].f.stale_link;
dir_copy.list[i].sort_key = NULL;
dir_copy.list[i].second_sort_key = NULL;
if (list->list[i].f.marked) {
g_hash_table_insert (marked_files, dir_copy.list[i].fname,
&dir_copy.list[i]);
@ -573,6 +566,8 @@ do_reload_dir (const char *path, dir_list *list, sortfn *sort, int count,
list->list[next_free].f.stale_link = stale_link;
list->list[next_free].f.dir_size_computed = 0;
list->list[next_free].st = st;
list->list[next_free].sort_key = NULL;
list->list[next_free].second_sort_key = NULL;
next_free++;
if (!(next_free % 16))
rotate_dash ();

Просмотреть файл

@ -6,6 +6,7 @@
#include <sys/stat.h>
/* keys are set only during sorting */
typedef struct {
/* File attributes */
@ -13,6 +14,10 @@ typedef struct {
int fnamelen;
char *fname;
struct stat st;
/* key used for comparing names */
char *sort_key;
/* key used for comparing extensions */
char *second_sort_key;
/* Flags */
struct {
@ -42,14 +47,14 @@ int handle_path (dir_list *list, const char *path, struct stat *buf1,
int next_free, int *link_to_dir, int *stale_link);
/* Sorting functions */
int unsorted (const file_entry *a, const file_entry *b);
int sort_name (const file_entry *a, const file_entry *b);
int sort_ext (const file_entry *a, const file_entry *b);
int sort_time (const file_entry *a, const file_entry *b);
int sort_atime (const file_entry *a, const file_entry *b);
int sort_ctime (const file_entry *a, const file_entry *b);
int sort_size (const file_entry *a, const file_entry *b);
int sort_inode (const file_entry *a, const file_entry *b);
int unsorted (file_entry *a, file_entry *b);
int sort_name (file_entry *a, file_entry *b);
int sort_ext (file_entry *a, file_entry *b);
int sort_time (file_entry *a, file_entry *b);
int sort_atime (file_entry *a, file_entry *b);
int sort_ctime (file_entry *a, file_entry *b);
int sort_size (file_entry *a, file_entry *b);
int sort_inode (file_entry *a, file_entry *b);
/* SORT_TYPES is used to build the nice dialog box entries */
#define SORT_TYPES 8
@ -62,7 +67,7 @@ int sort_inode (const file_entry *a, const file_entry *b);
typedef struct {
const char *sort_name;
int (*sort_fn)(const file_entry *, const file_entry *);
int (*sort_fn)(file_entry *, file_entry *);
} sort_orders_t;
extern sort_orders_t sort_orders [SORT_TYPES_TOTAL];

Просмотреть файл

@ -1045,6 +1045,8 @@ find_file (char *start_dir, char *pattern, char *content, char **dirname,
list->list[next_free].f.stale_link = stale_link;
list->list[next_free].f.dir_size_computed = 0;
list->list[next_free].st = st;
list->list[next_free].sort_key = NULL;
list->list[next_free].second_sort_key = NULL;
next_free++;
if (!(next_free & 15))
rotate_dash ();

Просмотреть файл

@ -404,6 +404,8 @@ static void do_external_panelize (char *command)
list->list [next_free].f.stale_link = stale_link;
list->list [next_free].f.dir_size_computed = 0;
list->list [next_free].st = st;
list->list[next_free].sort_key = NULL;
list->list[next_free].second_sort_key = NULL;
next_free++;
if (!(next_free & 32))
rotate_dash ();