196 lines
5.5 KiB
C
196 lines
5.5 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; coding: utf-8 -*-
|
|
* moofilesystem-private.h
|
|
*
|
|
* Copyright (C) 2004-2006 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* See COPYING file that comes with this distribution.
|
|
*/
|
|
|
|
|
|
#include <string.h>
|
|
#include <glib.h>
|
|
|
|
#define COLUMN_FILE MOO_FOLDER_MODEL_COLUMN_FILE
|
|
|
|
|
|
/* TODO: strncmp should accept char len, not byte len? */
|
|
typedef struct {
|
|
int (*strcmp_func) (const char *str,
|
|
MooFile *file);
|
|
int (*strncmp_func) (const char *str,
|
|
MooFile *file,
|
|
guint len);
|
|
char* (*normalize_func) (const char *str,
|
|
gssize len);
|
|
} TextFuncs;
|
|
|
|
|
|
static int strcmp_func (const char *str,
|
|
MooFile *file)
|
|
{
|
|
return strcmp (str, moo_file_display_name (file));
|
|
}
|
|
|
|
static int strncmp_func (const char *str,
|
|
MooFile *file,
|
|
guint len)
|
|
{
|
|
return strncmp (str, moo_file_display_name (file), len);
|
|
}
|
|
|
|
static char *normalize_func (const char *str,
|
|
gssize len)
|
|
{
|
|
return g_utf8_normalize (str, len, G_NORMALIZE_ALL);
|
|
}
|
|
|
|
|
|
static int case_strcmp_func (const char *str,
|
|
MooFile *file)
|
|
{
|
|
return strcmp (str, moo_file_case_display_name (file));
|
|
}
|
|
|
|
static int case_strncmp_func (const char *str,
|
|
MooFile *file,
|
|
guint len)
|
|
{
|
|
return strncmp (str, moo_file_case_display_name (file), len);
|
|
}
|
|
|
|
static char *case_normalize_func (const char *str,
|
|
gssize len)
|
|
{
|
|
char *norm = g_utf8_normalize (str, len, G_NORMALIZE_ALL);
|
|
char *res = g_utf8_casefold (norm, -1);
|
|
g_free (norm);
|
|
return res;
|
|
}
|
|
|
|
|
|
static gboolean model_find_next_match (GtkTreeModel *model,
|
|
GtkTreeIter *iter,
|
|
const char *text,
|
|
gssize len,
|
|
TextFuncs *funcs,
|
|
gboolean exact_match)
|
|
{
|
|
char *normalized_text;
|
|
guint normalized_text_len;
|
|
|
|
g_return_val_if_fail (text != NULL, FALSE);
|
|
|
|
normalized_text = funcs->normalize_func (text, len);
|
|
normalized_text_len = strlen (normalized_text);
|
|
|
|
while (TRUE)
|
|
{
|
|
MooFile *file = NULL;
|
|
gboolean match;
|
|
|
|
gtk_tree_model_get (model, iter, COLUMN_FILE, &file, -1);
|
|
|
|
if (file)
|
|
{
|
|
if (exact_match)
|
|
match = !funcs->strcmp_func (normalized_text, file);
|
|
else
|
|
match = !funcs->strncmp_func (normalized_text, file,
|
|
normalized_text_len);
|
|
|
|
moo_file_unref (file);
|
|
|
|
if (match)
|
|
{
|
|
g_free (normalized_text);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (!gtk_tree_model_iter_next (model, iter))
|
|
{
|
|
g_free (normalized_text);
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static GString *model_find_max_prefix (GtkTreeModel *model,
|
|
const char *text,
|
|
TextFuncs *funcs,
|
|
gboolean *unique_p,
|
|
GtkTreeIter *unique_iter_p)
|
|
{
|
|
GtkTreeIter iter, unique_iter;
|
|
guint text_len;
|
|
GString *prefix = NULL;
|
|
gboolean unique = FALSE;
|
|
|
|
g_assert (text && text[0]);
|
|
|
|
text_len = strlen (text);
|
|
|
|
if (!gtk_tree_model_get_iter_first (model, &iter))
|
|
goto out;
|
|
|
|
while (TRUE)
|
|
{
|
|
MooFile *file = NULL;
|
|
const char *name;
|
|
guint i;
|
|
|
|
if (!model_find_next_match (model, &iter, text, text_len, funcs, FALSE))
|
|
goto out;
|
|
|
|
gtk_tree_model_get (model, &iter,
|
|
COLUMN_FILE, &file, -1);
|
|
g_assert (file != NULL);
|
|
|
|
name = moo_file_display_name (file);
|
|
|
|
if (!prefix)
|
|
{
|
|
prefix = g_string_new (moo_file_display_name (file));
|
|
unique_iter = iter;
|
|
unique = TRUE;
|
|
|
|
/* nothing to look for, just check if it's really unique */
|
|
if (prefix->len == text_len)
|
|
{
|
|
if (gtk_tree_model_iter_next (model, &iter) &&
|
|
model_find_next_match (model, &iter, text, text_len, funcs, FALSE))
|
|
unique = FALSE;
|
|
|
|
goto out;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = text_len; i < prefix->len && name[i] == prefix->str[i]; ++i) ;
|
|
|
|
prefix->str[i] = 0;
|
|
prefix->len = i;
|
|
unique = FALSE;
|
|
|
|
if (prefix->len == text_len)
|
|
goto out;
|
|
}
|
|
|
|
if (!gtk_tree_model_iter_next (model, &iter))
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
if (unique_p)
|
|
*unique_p = unique;
|
|
if (unique_iter_p)
|
|
*unique_iter_p = unique_iter;
|
|
return prefix;
|
|
}
|