|
Packit |
116408 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
|
|
Packit |
116408 |
/*
|
|
Packit |
116408 |
* Copyright (C) 2018 Sébastien Wilmet <swilmet@gnome.org>
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* This program is free software; you can redistribute it and/or
|
|
Packit |
116408 |
* modify it under the terms of the GNU General Public License as
|
|
Packit |
116408 |
* published by the Free Software Foundation; either version 2 of the
|
|
Packit |
116408 |
* License, or (at your option) any later version.
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
116408 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
116408 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
116408 |
* General Public License for more details.
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
116408 |
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
|
|
Packit |
116408 |
#include "dh-search-context.h"
|
|
Packit |
116408 |
#include <string.h>
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* DhSearchContext is a helper class for a search instance, with the search
|
|
Packit |
116408 |
* string as data.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
|
|
Packit |
116408 |
struct _DhSearchContext {
|
|
Packit |
116408 |
/* The content of the search string: */
|
|
Packit |
116408 |
|
|
Packit |
116408 |
gchar *book_id;
|
|
Packit |
116408 |
gchar *page_id;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
// If non-NULL, contains at least one non-empty string.
|
|
Packit |
116408 |
GStrv keywords;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Derived data: */
|
|
Packit |
116408 |
|
|
Packit |
116408 |
// Element-type: KeywordData*.
|
|
Packit |
116408 |
GSList *keywords_data;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
gchar *joined_keywords;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
guint case_sensitive : 1;
|
|
Packit |
116408 |
};
|
|
Packit |
116408 |
|
|
Packit |
116408 |
typedef struct _KeywordData {
|
|
Packit |
116408 |
gchar *keyword;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Created only if has_glob and is_first. */
|
|
Packit |
116408 |
GPatternSpec *pattern_spec_prefix;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Created only if has_glob. */
|
|
Packit |
116408 |
GPatternSpec *pattern_spec_anywhere;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
guint is_first : 1;
|
|
Packit |
116408 |
guint has_glob : 1;
|
|
Packit |
116408 |
} KeywordData;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Process the input search string and extract:
|
|
Packit |
116408 |
* - If "book:" prefix given, a book_id;
|
|
Packit |
116408 |
* - If "page:" prefix given, a page_id;
|
|
Packit |
116408 |
* - All remaining keywords.
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* "book:" and "page:" must be before the other keywords.
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* Returns TRUE if the extraction is successfull, FALSE if the @search_string is
|
|
Packit |
116408 |
* invalid.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
static gboolean
|
|
Packit |
116408 |
process_search_string (DhSearchContext *search,
|
|
Packit |
116408 |
const gchar *search_string)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gchar *processed = NULL;
|
|
Packit |
116408 |
GStrv tokens = NULL;
|
|
Packit |
116408 |
gint token_num;
|
|
Packit |
116408 |
gint keyword_num;
|
|
Packit |
116408 |
gboolean ret = TRUE;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_assert (search->book_id == NULL);
|
|
Packit |
116408 |
g_assert (search->page_id == NULL);
|
|
Packit |
116408 |
g_assert (search->keywords == NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* First, remove all leading and trailing whitespaces in the search
|
|
Packit |
116408 |
* string.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
processed = g_strdup (search_string);
|
|
Packit |
116408 |
g_strstrip (processed);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Also avoid words being separated by more than one whitespace, or
|
|
Packit |
116408 |
* g_strsplit() will give us empty strings.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gchar *aux;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
aux = processed;
|
|
Packit |
116408 |
while ((aux = strchr (aux, ' ')) != NULL) {
|
|
Packit |
116408 |
g_strchug (++aux);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* If after all this we get an empty string, nothing else to do. */
|
|
Packit |
116408 |
if (processed[0] == '\0') {
|
|
Packit |
116408 |
ret = FALSE;
|
|
Packit |
116408 |
goto out;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Split the input string into tokens */
|
|
Packit |
116408 |
tokens = g_strsplit (processed, " ", 0);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Allocate output keywords */
|
|
Packit |
116408 |
search->keywords = g_new0 (gchar *, g_strv_length (tokens) + 1);
|
|
Packit |
116408 |
keyword_num = 0;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
for (token_num = 0; tokens[token_num] != NULL; token_num++) {
|
|
Packit |
116408 |
const gchar *cur_token = tokens[token_num];
|
|
Packit |
116408 |
const gchar *prefix;
|
|
Packit |
116408 |
gint prefix_len;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Book prefix? */
|
|
Packit |
116408 |
prefix = "book:";
|
|
Packit |
116408 |
if (g_str_has_prefix (cur_token, prefix)) {
|
|
Packit |
116408 |
/* Must be before normal keywords. */
|
|
Packit |
116408 |
if (keyword_num > 0) {
|
|
Packit |
116408 |
ret = FALSE;
|
|
Packit |
116408 |
goto out;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
prefix_len = strlen (prefix);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* If keyword given but no content, skip it. */
|
|
Packit |
116408 |
if (cur_token[prefix_len] == '\0') {
|
|
Packit |
116408 |
continue;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* We got a second request of book, don't allow this. */
|
|
Packit |
116408 |
if (search->book_id != NULL) {
|
|
Packit |
116408 |
ret = FALSE;
|
|
Packit |
116408 |
goto out;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
search->book_id = g_strdup (cur_token + prefix_len);
|
|
Packit |
116408 |
continue;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Page prefix? */
|
|
Packit |
116408 |
prefix = "page:";
|
|
Packit |
116408 |
if (g_str_has_prefix (cur_token, prefix)) {
|
|
Packit |
116408 |
/* Must be before normal keywords. */
|
|
Packit |
116408 |
if (keyword_num > 0) {
|
|
Packit |
116408 |
ret = FALSE;
|
|
Packit |
116408 |
goto out;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
prefix_len = strlen (prefix);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* If keyword given but no content, skip it. */
|
|
Packit |
116408 |
if (cur_token[prefix_len] == '\0') {
|
|
Packit |
116408 |
continue;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* We got a second request of page, don't allow this. */
|
|
Packit |
116408 |
if (search->page_id != NULL) {
|
|
Packit |
116408 |
ret = FALSE;
|
|
Packit |
116408 |
goto out;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
search->page_id = g_strdup (cur_token + prefix_len);
|
|
Packit |
116408 |
continue;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Then, a new keyword to look for. */
|
|
Packit |
116408 |
search->keywords[keyword_num] = g_strdup (cur_token);
|
|
Packit |
116408 |
keyword_num++;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (keyword_num == 0) {
|
|
Packit |
116408 |
g_free (search->keywords);
|
|
Packit |
116408 |
search->keywords = NULL;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
out:
|
|
Packit |
116408 |
g_free (processed);
|
|
Packit |
116408 |
g_strfreev (tokens);
|
|
Packit |
116408 |
return ret;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static gboolean
|
|
Packit |
116408 |
contains_uppercase_letter (const gchar *str)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
const gchar *p;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
for (p = str; *p != '\0'; p++) {
|
|
Packit |
116408 |
if (g_ascii_isupper (*p))
|
|
Packit |
116408 |
return TRUE;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return FALSE;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static void
|
|
Packit |
116408 |
set_case_sensitive (DhSearchContext *search)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gint i;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
search->case_sensitive = FALSE;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (search->keywords == NULL)
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Searches are case sensitive when any uppercase letter is used in the
|
|
Packit |
116408 |
* search terms, matching Vim smartcase behaviour.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
for (i = 0; search->keywords[i] != NULL; i++) {
|
|
Packit |
116408 |
const gchar *cur_keyword = search->keywords[i];
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (contains_uppercase_letter (cur_keyword)) {
|
|
Packit |
116408 |
search->case_sensitive = TRUE;
|
|
Packit |
116408 |
break;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static KeywordData *
|
|
Packit |
116408 |
keyword_data_new (const gchar *keyword,
|
|
Packit |
116408 |
gboolean is_first)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
KeywordData *data;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_assert (keyword != NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
data = g_new0 (KeywordData, 1);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
data->keyword = g_strdup (keyword);
|
|
Packit |
116408 |
data->is_first = is_first != FALSE;
|
|
Packit |
116408 |
data->has_glob = (strchr (keyword, '*') != NULL ||
|
|
Packit |
116408 |
strchr (keyword, '?') != NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (data->has_glob) {
|
|
Packit |
116408 |
gchar *pattern;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (is_first) {
|
|
Packit |
116408 |
pattern = g_strdup_printf ("%s*", keyword);
|
|
Packit |
116408 |
data->pattern_spec_prefix = g_pattern_spec_new (pattern);
|
|
Packit |
116408 |
g_free (pattern);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
pattern = g_strdup_printf ("*%s*", keyword);
|
|
Packit |
116408 |
data->pattern_spec_anywhere = g_pattern_spec_new (pattern);
|
|
Packit |
116408 |
g_free (pattern);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return data;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static void
|
|
Packit |
116408 |
keyword_data_free (gpointer _data)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
KeywordData *data = _data;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (data == NULL)
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_free (data->keyword);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (data->pattern_spec_prefix != NULL)
|
|
Packit |
116408 |
g_pattern_spec_free (data->pattern_spec_prefix);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (data->pattern_spec_anywhere != NULL)
|
|
Packit |
116408 |
g_pattern_spec_free (data->pattern_spec_anywhere);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_free (data);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static void
|
|
Packit |
116408 |
create_keywords_data (DhSearchContext *search)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gint keyword_num;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_assert (search->keywords_data == NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (search->keywords == NULL)
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
for (keyword_num = 0; search->keywords[keyword_num] != NULL; keyword_num++) {
|
|
Packit |
116408 |
const gchar *cur_keyword = search->keywords[keyword_num];
|
|
Packit |
116408 |
KeywordData *data;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
data = keyword_data_new (cur_keyword, keyword_num == 0);
|
|
Packit |
116408 |
search->keywords_data = g_slist_prepend (search->keywords_data, data);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
search->keywords_data = g_slist_reverse (search->keywords_data);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static void
|
|
Packit |
116408 |
join_keywords (DhSearchContext *search)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
g_assert (search->joined_keywords == NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (search->keywords == NULL)
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
search->joined_keywords = g_strjoinv (" ", search->keywords);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Returns: (transfer full) (nullable): a new #DhSearchContext, or %NULL if
|
|
Packit |
116408 |
* @search_string is invalid.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
DhSearchContext *
|
|
Packit |
116408 |
_dh_search_context_new (const gchar *search_string)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
DhSearchContext *search;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_val_if_fail (search_string != NULL, NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
search = g_new0 (DhSearchContext, 1);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (!process_search_string (search, search_string)) {
|
|
Packit |
116408 |
_dh_search_context_free (search);
|
|
Packit |
116408 |
return NULL;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
set_case_sensitive (search);
|
|
Packit |
116408 |
create_keywords_data (search);
|
|
Packit |
116408 |
join_keywords (search);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return search;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
_dh_search_context_free (DhSearchContext *search)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
if (search == NULL)
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_free (search->book_id);
|
|
Packit |
116408 |
g_free (search->page_id);
|
|
Packit |
116408 |
g_strfreev (search->keywords);
|
|
Packit |
116408 |
g_slist_free_full (search->keywords_data, keyword_data_free);
|
|
Packit |
116408 |
g_free (search->joined_keywords);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_free (search);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
const gchar *
|
|
Packit |
116408 |
_dh_search_context_get_book_id (DhSearchContext *search)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
g_return_val_if_fail (search != NULL, NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return search->book_id;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
const gchar *
|
|
Packit |
116408 |
_dh_search_context_get_page_id (DhSearchContext *search)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
g_return_val_if_fail (search != NULL, NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return search->page_id;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
GStrv
|
|
Packit |
116408 |
_dh_search_context_get_keywords (DhSearchContext *search)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
g_return_val_if_fail (search != NULL, NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return search->keywords;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
gboolean
|
|
Packit |
116408 |
_dh_search_context_get_case_sensitive (DhSearchContext *search)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
g_return_val_if_fail (search != NULL, FALSE);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return search->case_sensitive;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
gboolean
|
|
Packit |
116408 |
_dh_search_context_match_book (DhSearchContext *search,
|
|
Packit |
116408 |
DhBook *book)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
g_return_val_if_fail (search != NULL, FALSE);
|
|
Packit |
116408 |
g_return_val_if_fail (DH_IS_BOOK (book), FALSE);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (!dh_book_get_enabled (book))
|
|
Packit |
116408 |
return FALSE;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (search->book_id == NULL)
|
|
Packit |
116408 |
return TRUE;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return g_strcmp0 (search->book_id, dh_book_get_id (book)) == 0;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* This function assumes that _dh_search_context_match_book() returns TRUE for
|
|
Packit |
116408 |
* the DhBook containing @link (to avoid checking the book_id for each DhLink).
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
gboolean
|
|
Packit |
116408 |
_dh_search_context_match_link (DhSearchContext *search,
|
|
Packit |
116408 |
DhLink *link,
|
|
Packit |
116408 |
gboolean prefix)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gchar *str_to_free = NULL;
|
|
Packit |
116408 |
const gchar *link_name;
|
|
Packit |
116408 |
gboolean match = FALSE;
|
|
Packit |
116408 |
GSList *l;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_val_if_fail (search != NULL, FALSE);
|
|
Packit |
116408 |
g_return_val_if_fail (link != NULL, FALSE);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Filter by page? */
|
|
Packit |
116408 |
if (search->page_id != NULL) {
|
|
Packit |
116408 |
if (!dh_link_belongs_to_page (link, search->page_id))
|
|
Packit |
116408 |
return FALSE;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (search->keywords == NULL)
|
|
Packit |
116408 |
/* Show all in the page, but only if prefix=TRUE, to not
|
|
Packit |
116408 |
* match two times the same link.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
return prefix;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (search->keywords == NULL)
|
|
Packit |
116408 |
return FALSE;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (search->case_sensitive) {
|
|
Packit |
116408 |
link_name = dh_link_get_name (link);
|
|
Packit |
116408 |
} else {
|
|
Packit |
116408 |
str_to_free = g_ascii_strdown (dh_link_get_name (link), -1);
|
|
Packit |
116408 |
link_name = str_to_free;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_val_if_fail (link_name != NULL, FALSE);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Why isn't there only one GPatternSpec (or two variants:
|
|
Packit |
116408 |
* prefix/anywhere) for all the keywords? For example searching
|
|
Packit |
116408 |
* "dh_link_ book" (two keywords) would create the GPatternSpec
|
|
Packit |
116408 |
* "dh_link_*book*". Although the implementation would be simpler, doing
|
|
Packit |
116408 |
* so would be a regression in functionality. It is explained in details
|
|
Packit |
116408 |
* in the user documentation of the Devhelp app.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Why matching by prefix only for the first keyword and not the others?
|
|
Packit |
116408 |
* For several reasons:
|
|
Packit |
116408 |
* - When prefix=TRUE, if data->pattern_spec_prefix was used for all
|
|
Packit |
116408 |
* keywords, it would be impossible to match the DhLink name (except
|
|
Packit |
116408 |
* if all the keywords are equal for example, but it doesn't make
|
|
Packit |
116408 |
* sense to do such a search).
|
|
Packit |
116408 |
* - At least with the GTK+/GNOME APIs, normally all the symbols start
|
|
Packit |
116408 |
* with the namespace of the library. So when we search symbols, if we
|
|
Packit |
116408 |
* know in which library the symbol(s) is located, we can type the
|
|
Packit |
116408 |
* namespace as first keyword. With prefix=TRUE, this will match the
|
|
Packit |
116408 |
* namespace.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Use simple string functions when the keyword doesn't contain globs,
|
|
Packit |
116408 |
* to improve performances (this function can be called on *every*
|
|
Packit |
116408 |
* DhLink).
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
|
|
Packit |
116408 |
for (l = search->keywords_data; l != NULL; l = l->next) {
|
|
Packit |
116408 |
KeywordData *data = l->data;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (data->is_first) {
|
|
Packit |
116408 |
if (data->has_glob) {
|
|
Packit |
116408 |
if (prefix) {
|
|
Packit |
116408 |
match = g_pattern_match_string (data->pattern_spec_prefix, link_name);
|
|
Packit |
116408 |
} else {
|
|
Packit |
116408 |
match = (!g_pattern_match_string (data->pattern_spec_prefix, link_name) &&
|
|
Packit |
116408 |
g_pattern_match_string (data->pattern_spec_anywhere, link_name));
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
} else {
|
|
Packit |
116408 |
if (prefix) {
|
|
Packit |
116408 |
match = g_str_has_prefix (link_name, data->keyword);
|
|
Packit |
116408 |
} else {
|
|
Packit |
116408 |
match = (!g_str_has_prefix (link_name, data->keyword) &&
|
|
Packit |
116408 |
strstr (link_name, data->keyword) != NULL);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
} else {
|
|
Packit |
116408 |
if (data->has_glob) {
|
|
Packit |
116408 |
match = g_pattern_match_string (data->pattern_spec_anywhere, link_name);
|
|
Packit |
116408 |
} else {
|
|
Packit |
116408 |
match = strstr (link_name, data->keyword) != NULL;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (!match)
|
|
Packit |
116408 |
break;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_free (str_to_free);
|
|
Packit |
116408 |
return match;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* This function assumes:
|
|
Packit |
116408 |
* - That _dh_search_context_match_book() returns TRUE for the DhBook containing
|
|
Packit |
116408 |
* @link (to avoid checking the book_id for each DhLink).
|
|
Packit |
116408 |
* - That _dh_search_context_match_link(prefix=TRUE) returns TRUE for @link.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
gboolean
|
|
Packit |
116408 |
_dh_search_context_is_exact_link (DhSearchContext *search,
|
|
Packit |
116408 |
DhLink *link)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
const gchar *name;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_val_if_fail (search != NULL, FALSE);
|
|
Packit |
116408 |
g_return_val_if_fail (link != NULL, FALSE);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (search->page_id != NULL && search->keywords == NULL) {
|
|
Packit |
116408 |
DhLinkType link_type;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
link_type = dh_link_get_link_type (link);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Can be DH_LINK_TYPE_BOOK for page_id "index". */
|
|
Packit |
116408 |
return (link_type == DH_LINK_TYPE_BOOK ||
|
|
Packit |
116408 |
link_type == DH_LINK_TYPE_PAGE);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (search->keywords == NULL)
|
|
Packit |
116408 |
return FALSE;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
name = dh_link_get_name (link);
|
|
Packit |
116408 |
return g_strcmp0 (name, search->joined_keywords) == 0;
|
|
Packit |
116408 |
}
|