mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-09-19 07:41:26 +00:00
114bc35edc
* libnautilus-extensions/nautilus-search-uri.c: (nautilus_self_check_search_uri): Updated self-check expected results to match recent wording changes. This should fix the Tinderbox build.
850 lines
33 KiB
C
850 lines
33 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
|
|
/* Code to generate human-readable strings from search uris.
|
|
|
|
Copyright (C) 2000 Eazel, Inc.
|
|
|
|
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.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public
|
|
License along with this program; see the file COPYING. If not,
|
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
Boston, MA 02111-1307, USA.
|
|
|
|
Author: Mathieu Lacage <mathieu@eazel.com>
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include "nautilus-search-uri.h"
|
|
|
|
/* Must be included before other libgnome headers. */
|
|
#include <libgnome/gnome-defs.h>
|
|
|
|
#include "nautilus-lib-self-check-functions.h"
|
|
#include "nautilus-string.h"
|
|
#include <libgnome/gnome-i18n.h>
|
|
#include <libgnomevfs/gnome-vfs-utils.h>
|
|
|
|
static const char * strip_uri_beginning (const char *location_uri);
|
|
static GSList * tokenize_uri (const char *string);
|
|
static char * get_translated_criterion (const GSList *criterion);
|
|
static char * get_first_criterion_prefix (GSList *criterion);
|
|
static char * get_nth_criterion_prefix (GSList *criterion);
|
|
static char * parse_uri (const char *search_uri);
|
|
static void free_tokenized_uri (GSList *list);
|
|
|
|
/**
|
|
* strip_uri_beginning:
|
|
* @location_uri: search uri.
|
|
*
|
|
* strips the search:[file:///...] part of the input uri.
|
|
*
|
|
*/
|
|
static const char *
|
|
strip_uri_beginning (const char *location_uri)
|
|
{
|
|
char **first_token;
|
|
char *ptr;
|
|
const char *ret_val;
|
|
|
|
first_token = g_strsplit (location_uri, " ", 1);
|
|
if (first_token[0] == NULL) {
|
|
g_strfreev (first_token);
|
|
return NULL;
|
|
}
|
|
|
|
/* parse the first token from the end to the beginning.
|
|
to extract the search:[] part.
|
|
*/
|
|
for (ptr = first_token[0]+strlen(first_token[0]);
|
|
ptr != first_token[0] && *ptr != ']';
|
|
ptr--) {}
|
|
|
|
ret_val = location_uri + (ptr - first_token[0]) + 1;
|
|
|
|
g_strfreev (first_token);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
/**
|
|
* free_tokenized_uri:
|
|
* @list: tokenized uri to free
|
|
*
|
|
*/
|
|
static void
|
|
free_tokenized_uri (GSList *list)
|
|
{
|
|
GSList *temp_list;
|
|
|
|
for (temp_list = list; temp_list != NULL; temp_list = temp_list->next) {
|
|
GSList *inner_list, *temp_inner_list;
|
|
|
|
inner_list = (GSList *)temp_list->data;
|
|
for (temp_inner_list = inner_list; temp_inner_list != NULL;
|
|
temp_inner_list = temp_inner_list->next) {
|
|
g_free ((char *)temp_inner_list->data);
|
|
}
|
|
|
|
g_slist_free (inner_list);
|
|
}
|
|
g_slist_free (list);
|
|
}
|
|
|
|
|
|
/**
|
|
* tokenize_uri
|
|
* @string: string to parse
|
|
*
|
|
* This function tokenizes a subset of the grand medusa uri specification.
|
|
* If it cannot, it returns NULL. CHECK FOR NULL upon return.
|
|
*
|
|
* Return value: a Singly linked list of singly linked lists.
|
|
* each of the element of the root linked list is a complete criterion.
|
|
* each criterin sinlgly linked list is made of the different tokens
|
|
* of the criterion.
|
|
*/
|
|
static GSList *
|
|
tokenize_uri (const char *string)
|
|
{
|
|
const char *temp_string;
|
|
char **criteria;
|
|
GSList *criterion_list;
|
|
int i, j;
|
|
|
|
if (string == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
criterion_list = NULL;
|
|
|
|
string = strip_uri_beginning (string);
|
|
if (string == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/* make sure we can handle this uri */
|
|
if ( strchr (string , '(') != NULL
|
|
|| strchr (string, ')') != NULL
|
|
|| strchr (string, '|') != NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/* split the uri in different criteria */
|
|
criteria = g_strsplit (string, " & ", 0);
|
|
for (i = 0, temp_string = criteria[0];
|
|
temp_string != NULL;
|
|
i++, temp_string = criteria[i]) {
|
|
char **tokens;
|
|
char *token;
|
|
GSList *token_list;
|
|
|
|
/* split a criterion in different tokens */
|
|
token_list = NULL;
|
|
tokens = g_strsplit (temp_string, " ", 2);
|
|
for (j = 0, token = tokens[0]; token != NULL; j++, token = tokens[j]) {
|
|
/* g_strstrip does not return a newly allocated string. */
|
|
token_list = g_slist_append (token_list, g_strdup(g_strstrip (token)));
|
|
}
|
|
criterion_list = g_slist_append (criterion_list, token_list);
|
|
g_strfreev (tokens);
|
|
}
|
|
g_strfreev (criteria);
|
|
|
|
return criterion_list;
|
|
}
|
|
|
|
typedef struct _value_criterion_item value_criterion_item;
|
|
typedef value_criterion_item *value_criterion_table;
|
|
|
|
typedef struct _operand_criterion_item operand_criterion_item;
|
|
typedef operand_criterion_item *operand_criterion_table;
|
|
|
|
typedef struct _field_criterion_item field_criterion_item;
|
|
typedef field_criterion_item *field_criterion_table;
|
|
|
|
/* toplevel structure each entry points to a level 2 structure */
|
|
struct _field_criterion_item {
|
|
char *id;
|
|
char *prefix;
|
|
operand_criterion_table items;
|
|
};
|
|
/* second level structure. if items is NULL, the entry is a leaf
|
|
of our hierarchy. If it is not, it points to a level 3 leaf
|
|
*/
|
|
struct _operand_criterion_item {
|
|
char *id;
|
|
char *translation;
|
|
value_criterion_table items;
|
|
};
|
|
/* third level structure. leaf */
|
|
struct _value_criterion_item {
|
|
char *id;
|
|
char *translation;
|
|
/* this field is there only to make the 3 structures similar enough
|
|
so that you can safely cast between them it is a kind of evil hack
|
|
but i like it. It is guaranteed to be always NULL. */
|
|
value_criterion_table items;
|
|
};
|
|
|
|
|
|
/* -------------------------------------------------------
|
|
- file name -
|
|
-------------------------------------------------------
|
|
*/
|
|
|
|
static operand_criterion_item file_name2_table [] = {
|
|
{"contains",
|
|
/* Part of a window title for search results: a
|
|
description of the set of files that contains a string */
|
|
N_("containing \"%s\" in their names"),
|
|
NULL},
|
|
{"starts_with",
|
|
/* Part of a window title for search results: a
|
|
description of the set of files that start with a string */
|
|
N_("starting with \"%s\""),
|
|
NULL},
|
|
{"ends_with",
|
|
/* Part of a window title for search results: a
|
|
description of the set of files that end with a string */
|
|
N_("ending with %s"),
|
|
NULL},
|
|
{"does_not_contain",
|
|
/* Part of a window title for search results: a
|
|
description of the set of files that end with a string */
|
|
N_("containing \"%s\" in their names"),
|
|
NULL},
|
|
{"regexp_matches",
|
|
/* Part of a window title for search results: a
|
|
description of the set of files that match a regular
|
|
expression */
|
|
N_("matching the regular expression \"%s\""),
|
|
NULL},
|
|
{"matches",
|
|
/* Part of a window title for search results: a
|
|
description of the set of files that match a glob pattern */
|
|
N_("matching the file pattern \"%s\""),
|
|
NULL},
|
|
{NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
/* -------------------------------------------------------
|
|
- file type -
|
|
-------------------------------------------------------
|
|
*/
|
|
static value_criterion_item file_type_options3_table [] = {
|
|
{"file",
|
|
/* Part of a window title for search results: a
|
|
description of the set of files that are not directories,
|
|
sockets, etc. */
|
|
N_("regular files"),
|
|
NULL},
|
|
{"text_file",
|
|
/* Part of a window title for search results: a
|
|
description of the set of files that are stored as plain
|
|
text */
|
|
N_("text files"),
|
|
NULL},
|
|
{"application",
|
|
/* Part of a window title for search results: a
|
|
description of the set of files that are binary files or
|
|
applications you can run */
|
|
N_("applications"),
|
|
NULL},
|
|
{"directory",
|
|
/* Part of a window title for search results: a
|
|
description of the set of items that are folders
|
|
(directories) */
|
|
N_("folders"),
|
|
NULL},
|
|
{"music",
|
|
/* Part of a window title for search results: a
|
|
description of the set of items that are music files
|
|
(mp3s, wavs) */
|
|
N_("music"),
|
|
NULL},
|
|
{NULL, NULL, NULL}
|
|
};
|
|
static operand_criterion_item file_type2_table [] = {
|
|
{"is_not",
|
|
/* Part of a window title for search results: way of
|
|
describing the fact that files are not of a certain type
|
|
(folder, music, etc). Context is "files that are [folder,
|
|
music]" */
|
|
N_("that are %s"),
|
|
file_type_options3_table},
|
|
{"is",
|
|
/* Part of a window title for search results: way of
|
|
describing the fact that files are of a certain type
|
|
(folder, music, etc). Context is "files that are not
|
|
[folder, music]" */
|
|
N_("that are %s"),
|
|
file_type_options3_table},
|
|
};
|
|
|
|
|
|
/* -------------------------------------------------------
|
|
- owner -
|
|
-------------------------------------------------------
|
|
*/
|
|
static operand_criterion_item owner2_table [] = {
|
|
{"is_not",
|
|
/* Part of a window title for search results: way of
|
|
describing the fact that files are not owned by someone,
|
|
Context is files not ownd by xxx */
|
|
N_("not owned by \"%s\""),
|
|
NULL},
|
|
{"is",
|
|
/* Part of a window title for search results: way of
|
|
describing the fact that files are owned by someone.
|
|
Context is files owned by root */
|
|
N_("owned by \"%s\""),
|
|
NULL},
|
|
{"has_uid",
|
|
/* Part of a window title for search results: way of
|
|
describing the fact that files have a specific owner uid.
|
|
Context is "files with owner UID xx" */
|
|
N_("with owner UID \"%s\""),
|
|
NULL},
|
|
{"does_not_have_uid",
|
|
/* Part of a window title for search results: way of
|
|
describing the fact that files have a specific owner uid
|
|
other than this one. Context is "files with owner uid
|
|
other than xx" */
|
|
N_("with owner UID other than \"%s\""),
|
|
NULL},
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
/* -------------------------------------------------------
|
|
- size -
|
|
-------------------------------------------------------
|
|
*/
|
|
static operand_criterion_item size2_table [] = {
|
|
{"larger_than",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files are larger than a certain size.
|
|
Context is "files larger than %s bytes" */
|
|
N_("larger than %s bytes"),
|
|
NULL},
|
|
{"smaller_than",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files are larger than a certain size.
|
|
Context is "files smaller than %s bytes" */
|
|
N_("smaller than %s bytes"),
|
|
NULL},
|
|
{"is",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files are larger than a certain size.
|
|
Context is "files of %s bytes" */
|
|
N_("of %s bytes"),
|
|
NULL},
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
/* -------------------------------------------------------
|
|
- modified time -
|
|
-------------------------------------------------------
|
|
*/
|
|
static operand_criterion_item mod_time2_table [] = {
|
|
{"is today",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files were modified since midnight of
|
|
the current day. Context is "files modified today" */
|
|
N_("modified today"),
|
|
NULL},
|
|
{"is yesterday",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files were modified since midnight of
|
|
the previous day. Context is "files modified yesterday" */
|
|
N_("modified yesterday"),
|
|
NULL},
|
|
{"is",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files were modified since midnight of
|
|
the date that will replace the %s. Context is "files
|
|
modified on 11/20/00" */
|
|
N_("modified on %s"),
|
|
NULL},
|
|
{"is_not",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files were not modified since midnight
|
|
of the date that will replace the %s. Context is "files
|
|
not modified on 11/20/00" */
|
|
N_("not modified on %s"),
|
|
NULL},
|
|
{"is_before",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files were not modified since midnight
|
|
of the date that will replace the %s. Context is "files
|
|
modified before 11/20/00" */
|
|
N_("modified before %s"),
|
|
NULL},
|
|
{"is_after",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files were modified after midnight of
|
|
the date field that will replace the %s. Context is
|
|
"files modified after 11/20/00" */
|
|
N_("modified after %s"),
|
|
NULL},
|
|
{"is_within_a_week_of",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files were modified within a week of
|
|
the date field that will replace the %s. Context is
|
|
"files within a week of 11/20/00" */
|
|
N_("modified within a week of %s"),
|
|
NULL},
|
|
{"is_within_a_month_of",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files were modified within a week of
|
|
the date field that will replace the %s. Context is
|
|
"files within a month of 11/20/00" */
|
|
N_("modified within a month of %s"),
|
|
NULL},
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
/* -------------------------------------------------------
|
|
- emblems -
|
|
-------------------------------------------------------
|
|
*/
|
|
|
|
static operand_criterion_item emblem2_table [] = {
|
|
{ "include",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files have emblems attached that include
|
|
the one that will replace the %s. Context is "files
|
|
marked with Important" */
|
|
N_("marked with \"%s\""),
|
|
NULL},
|
|
{ "do_not_include",
|
|
/* Part of a window title for search results: way of
|
|
describing that the files have emblems attached that don't
|
|
include the one that will replace the %s. Context is
|
|
"files not marked with Important" */
|
|
N_("not marked with \"%s\""),
|
|
NULL},
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
|
|
/* -------------------------------------------------------
|
|
- contains -
|
|
-------------------------------------------------------
|
|
*/
|
|
|
|
|
|
static operand_criterion_item contains2_table [] = {
|
|
{"includes_all_of",
|
|
/* Part of a window title for search results: way of
|
|
describing that the (text) files searched for contain the
|
|
word or words that will replace the %s. Context is "files
|
|
with all the word "bob frank" */
|
|
N_("with all the words \"%s\""),
|
|
NULL},
|
|
{"includes_any_of",
|
|
/* Part of a window title for search results: way of
|
|
describing that the (text) files searched for contain the
|
|
word or one or more of the words that will replace the %s.
|
|
Context is "files containing one of the words "bob frank" */
|
|
N_("containing one of the words \"%s\""),
|
|
NULL},
|
|
{"does_not_include_all_of",
|
|
/* Part of a window title for search results: way of
|
|
describing that the (text) files searched for don't
|
|
contain the word or all of the words that will replace the
|
|
%s. Context is "files without all the word "bob frank" */
|
|
N_("without all the words \"%s\""),
|
|
NULL},
|
|
{"does_not_include_any_of",
|
|
/* Part of a window title for search results: way of
|
|
describing that the (text) files searched for contain none of
|
|
the word or words that will replace the %s. Context is "files
|
|
with none of the words "bob frank" */
|
|
N_("without any of the words \"%s\""),
|
|
NULL},
|
|
{NULL, NULL, NULL},
|
|
};
|
|
|
|
|
|
|
|
/* -------------------------------------------------------
|
|
- main table -
|
|
------------------------------------------------------- */
|
|
|
|
static field_criterion_item main_table[] = {
|
|
{"file_name",
|
|
/* Part of a window title for search results: Optional
|
|
preposition that precedes the clause describing the file
|
|
name attribute matched. Context is after "files" and
|
|
before the translation for "containing xx in the name" */
|
|
N_(""),
|
|
file_name2_table},
|
|
{"file_type",
|
|
/* Part of a window title for search results: Optional
|
|
preposition that precedes the clause describing the file
|
|
type attribute matched. Context is after "files" and
|
|
before the translation for "that are music" */
|
|
N_(""),
|
|
file_type2_table},
|
|
{"owner",
|
|
/* Part of a window title for search results: Optional
|
|
preposition that precedes the clause describing the
|
|
properties of the file's owner that the search matched.
|
|
Context is after "files" and before the translation for
|
|
"owned by xx" */
|
|
N_(""),
|
|
owner2_table},
|
|
{"size",
|
|
/* Part of a window title for search results: Optional
|
|
preposition that precedes the clause describing the
|
|
properties of the file's size that the search matched.
|
|
Context is after "files" and before the translation for
|
|
"larger than 500 bytes" */
|
|
N_(""),
|
|
size2_table},
|
|
{"content",
|
|
/* Part of a window title for search results: Optional
|
|
preposition that precedes the clause describing the
|
|
properties of the file's content that the search matched.
|
|
Context is after "files" and before the translation for
|
|
"containing all the words" */
|
|
N_(""),
|
|
contains2_table},
|
|
{"modified",
|
|
/* Part of a window title for search results: Optional
|
|
preposition that precedes the clause describing the
|
|
properties of the file's modification date that the search
|
|
matched. Context is after "files" and before the
|
|
translation for "modified today" */
|
|
N_(""),
|
|
mod_time2_table},
|
|
{"keywords",
|
|
/* Part of a window title for search results: Optional
|
|
preposition that precedes the clause describing the
|
|
properties of the file's attached emblems that the search
|
|
matched. Context is after "files" and before the
|
|
translation for "marked with Important" */
|
|
N_(""),
|
|
emblem2_table},
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* get_item_number:
|
|
* @current_table: the table to parse.
|
|
* @item: the string to search into the table.
|
|
*
|
|
* Small helper function which allows whoich serches for @item
|
|
* into the @current_table.
|
|
* it returns -1 if it could not find it.
|
|
* Yes, I know it is wrong to use the normal function return value
|
|
* to pass error status. */
|
|
static int
|
|
get_item_number (field_criterion_item *current_table, char *item)
|
|
{
|
|
int i;
|
|
|
|
i = 0;
|
|
while (strcmp (current_table[i].id,
|
|
item) != 0) {
|
|
i++;
|
|
if (current_table[i].id == NULL) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
/**
|
|
* get_translated_criterion:
|
|
* @criterion: criterion uri to parse
|
|
*
|
|
* Returns a translated string for a given criterion uri.
|
|
*/
|
|
static char *
|
|
get_translated_criterion (const GSList *criterion)
|
|
{
|
|
|
|
int item_number, value_item_number;
|
|
operand_criterion_item *operand_table;
|
|
value_criterion_item *value_table;
|
|
char *ret_val;
|
|
|
|
/* make sure we got a valid criterion */
|
|
if (g_slist_length ((GSList *) criterion) != 3) {
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/* get through begening of criterion structure */
|
|
item_number = get_item_number (main_table, (char *)criterion->data);
|
|
if (item_number == -1) {
|
|
return NULL;
|
|
}
|
|
operand_table = main_table[item_number].items;
|
|
criterion = criterion->next;
|
|
|
|
/* get through operanddle criterion structure */
|
|
item_number = get_item_number ((field_criterion_item *)operand_table,
|
|
(char *)criterion->data);
|
|
if (item_number == -1) {
|
|
return NULL;
|
|
}
|
|
value_table = operand_table[item_number].items;
|
|
criterion = criterion->next;
|
|
|
|
/* get through value criterion structure.
|
|
The fun begins NOW. */
|
|
|
|
if (value_table == NULL && operand_table[item_number].translation != NULL) {
|
|
/* simplest case: if the pointer to the value criterion
|
|
structure is NULL and we have a translation,
|
|
we output a concat of the translation and the
|
|
last part of the uri.
|
|
*/
|
|
ret_val = g_strdup_printf (_(operand_table[item_number].translation),
|
|
(char *) criterion->data);
|
|
return ret_val;
|
|
} else if (value_table != NULL) {
|
|
/* get through level 3 structure */
|
|
|
|
value_item_number = get_item_number ((field_criterion_item *) value_table,
|
|
(char *) criterion->data);
|
|
if (value_item_number == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
if (operand_table[item_number].translation == NULL) {
|
|
/* if we had no translation in operand criterion table */
|
|
ret_val = g_strdup (_(value_table[value_item_number].translation));
|
|
} else {
|
|
/* if we have both some translation in level 2 and level 3 */
|
|
ret_val = g_strdup_printf (_(operand_table[item_number].translation),
|
|
_(value_table[value_item_number].translation));
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
return g_strdup (_("are folders"));
|
|
}
|
|
|
|
/**
|
|
* get_first_criterion_prefix:
|
|
* @criterion: The GSList whose data field points to the criterion GSList.
|
|
*
|
|
* calculates the prefix for a given criterion */
|
|
static char *
|
|
get_first_criterion_prefix (GSList *criterion)
|
|
{
|
|
GSList *criterion_list;
|
|
char *criterion_type;
|
|
int item_number;
|
|
|
|
criterion_list = (GSList *) criterion->data;
|
|
criterion_type = (char *) criterion_list->data;
|
|
|
|
|
|
item_number = get_item_number (main_table, criterion_type);
|
|
|
|
return g_strdup (_(main_table[item_number].prefix));
|
|
}
|
|
|
|
/**
|
|
* get_nth_criterion_prefix:
|
|
* @criterion: The GSList whose data field points to the criterion GSList.
|
|
*
|
|
* calculates the "," or "and" prefix for any criterion.
|
|
*
|
|
* return value: the translated prefix.
|
|
*/
|
|
static char *
|
|
get_nth_criterion_prefix (GSList *criterion)
|
|
{
|
|
/* if we are the last criterion, put it here. */
|
|
|
|
if (criterion->next == NULL) {
|
|
return g_strdup (_(" and "));
|
|
}
|
|
return g_strdup (", ");
|
|
}
|
|
|
|
/**
|
|
* parse_uri:
|
|
* @search_uri: uri to translate.
|
|
*
|
|
* returns the translated version of the uri.
|
|
*/
|
|
static char *
|
|
parse_uri (const char *search_uri)
|
|
{
|
|
GSList *criteria, *criterion;
|
|
char *translated_criterion, *translated_prefix;
|
|
char *ret_val, *temp;
|
|
|
|
criteria = tokenize_uri (search_uri);
|
|
if (criteria == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/* processes the first criterion and add the necessary "whose" prefix */
|
|
translated_criterion = get_translated_criterion ((GSList *)criteria->data);
|
|
if (translated_criterion == NULL) {
|
|
free_tokenized_uri (criteria);
|
|
return NULL;
|
|
}
|
|
translated_prefix = get_first_criterion_prefix (criteria);
|
|
if (strcmp (translated_prefix, "") == 0) {
|
|
ret_val = g_strdup_printf (_("Items %s"),
|
|
translated_criterion);
|
|
} else {
|
|
ret_val = g_strdup_printf (_("Items %s %s"),
|
|
translated_prefix, translated_criterion);
|
|
}
|
|
g_free (translated_criterion);
|
|
g_free (translated_prefix);
|
|
|
|
/* processes the other criteria and add the necessary "and" prefixes */
|
|
for (criterion = criteria->next; criterion != NULL; criterion = criterion->next) {
|
|
translated_criterion = get_translated_criterion ((const GSList *)criterion->data);
|
|
if (translated_criterion == NULL) {
|
|
g_free (ret_val);
|
|
free_tokenized_uri (criteria);
|
|
return NULL;
|
|
}
|
|
translated_prefix = get_nth_criterion_prefix (criterion);
|
|
temp = g_strconcat (ret_val, translated_prefix,
|
|
translated_criterion, NULL);
|
|
g_free (ret_val);
|
|
ret_val = temp;
|
|
g_free (translated_criterion);
|
|
g_free (translated_prefix);
|
|
}
|
|
|
|
free_tokenized_uri (criteria);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
/**
|
|
* nautilus_search_uri_to_human:
|
|
* @search_uri: search uri to translate to human langage.
|
|
*
|
|
* The returned string is already localized.
|
|
*/
|
|
char *
|
|
nautilus_search_uri_to_human (const char *search_uri)
|
|
{
|
|
char *uri, *human;
|
|
|
|
g_return_val_if_fail (search_uri != NULL, NULL);
|
|
|
|
uri = gnome_vfs_unescape_string_for_display (search_uri);
|
|
human = parse_uri (uri);
|
|
if (human == NULL) {
|
|
return uri;
|
|
}
|
|
|
|
g_free (uri);
|
|
|
|
return human;
|
|
}
|
|
|
|
char *
|
|
nautilus_get_target_uri_from_search_result_name (const char *search_result_name)
|
|
{
|
|
return gnome_vfs_unescape_string (search_result_name, NULL);
|
|
}
|
|
|
|
gboolean
|
|
nautilus_is_search_uri (const char *uri)
|
|
{
|
|
g_return_val_if_fail (uri != NULL, FALSE);
|
|
|
|
return nautilus_istr_has_prefix (uri, "search:")
|
|
|| nautilus_istr_has_prefix (uri, "gnome-search:");
|
|
}
|
|
|
|
#if !defined (NAUTILUS_OMIT_SELF_CHECK)
|
|
|
|
void
|
|
nautilus_self_check_search_uri (void)
|
|
{
|
|
/* search_uri_to_human */
|
|
|
|
/* make sure that it does not accept non-supported uris.*/
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human (""), "");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("s"), "s");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human (" "), " ");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human (" "), " ");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human (" s"), " s");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human (" s "), " s ");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("xxx:yyy"), "xxx:yyy");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]"), "search:[][]");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]fi"), "search:[][]fi");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name"),
|
|
"search:[][]file_name");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name cont"),
|
|
"search:[][]file_name cont");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains"),
|
|
"search:[][]file_name contains");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name c stuff"),
|
|
"search:[][]file_name c stuff");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]&"),
|
|
"search:[][]&");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]f & s"),
|
|
"search:[][]f & s");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff & f"),
|
|
"search:[][]file_name contains stuff & f");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff & file_type i"),
|
|
"search:[][]file_name contains stuff & file_type i");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff & file_type is f"),
|
|
"search:[][]file_name contains stuff & file_type is f");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stu)ff & file_type is file"),
|
|
"search:[][]file_name contains stu)ff & file_type is file");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stu(ff & file_type is file"),
|
|
"search:[][]file_name contains stu(ff & file_type is file");
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stu|ff & file_type is file"),
|
|
"search:[][]file_name contains stu|ff & file_type is file");
|
|
|
|
/* make sure all the code paths work */
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff"),
|
|
_("Items containing \"stuff\" in their names"));
|
|
/* FIXME bugzilla.eazel.com 5088: This may be what the function calls "human", but it's bad grammar. */
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff & file_type is file"),
|
|
_("Items containing \"stuff\" in their names and that are regular files"));
|
|
/* FIXME bugzilla.eazel.com 5088: This may be what the function calls "human", but it's bad grammar. */
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains stuff & file_type is file"
|
|
" & size smaller_than 2000"),
|
|
_("Items containing \"stuff\" in their names, that are regular files and "
|
|
"smaller than 2000 bytes"));
|
|
/* FIXME bugzilla.eazel.com 5088: This may be what the function calls "human", but it's bad grammar. */
|
|
NAUTILUS_CHECK_STRING_RESULT (nautilus_search_uri_to_human ("search:[][]file_name contains medusa & file_type is directory"),
|
|
_("Items containing \"medusa\" in their names and that are "
|
|
"folders"));
|
|
|
|
/* is_search_uri */
|
|
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri (""), FALSE);
|
|
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("search:"), TRUE);
|
|
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("gnome-search:"), TRUE);
|
|
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("xxx-search:"), FALSE);
|
|
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("search:xxx"), TRUE);
|
|
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("gnome-search:xxx"), TRUE);
|
|
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_is_search_uri ("xxx-search:xxx"), FALSE);
|
|
}
|
|
|
|
#endif /* !NAUTILUS_OMIT_SELF_CHECK */
|