glib/glib/deprecated/gcompletion.c
Philip Withnall f14cd8de14 gcompletion: Make argument names match up
This fixes some warnings from g-ir-scanner.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: #3037
2023-11-29 12:00:14 +00:00

503 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
/*
* MT safe
*/
#include "config.h"
/* we know we are deprecated here, no need for warnings */
#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#endif
#include "gcompletion.h"
#include <glib/gstrfuncs.h>
#include <glib/gmessages.h>
#include <glib/gunicode.h>
#include <string.h>
/**
* GCompletion:
* @items: list of target items (strings or data structures).
* @func: function which is called to get the string associated with a
* target item. It is %NULL if the target items are strings.
* @prefix: the last prefix passed to g_completion_complete() or
* g_completion_complete_utf8().
* @cache: the list of items which begin with @prefix.
* @strncmp_func: The function to use when comparing strings. Use
* g_completion_set_compare() to modify this function.
*
* `GCompletion` provides support for automatic completion of a string
* using any group of target strings. It is typically used for file
* name completion as is common in many UNIX shells.
*
* A `GCompletion` is created using [func@GLib.Completion.new]. Target items are
* added and removed with [method@GLib.Completion.add_items],
* [method@GLib.Completion.remove_items] and
* [method@GLib.Completion.clear_items]. A completion attempt is requested with
* [method@GLib.Completion.complete] or [method@GLib.Completion.complete_utf8].
* When no longer needed, the `GCompletion` is freed with
* [method@GLib.Completion.free].
*
* Items in the completion can be simple strings (e.g. filenames), or
* pointers to arbitrary data structures. If data structures are used
* you must provide a [type@GLib.CompletionFunc] in [func@GLib.Completion.new],
* which retrieves the items string from the data structure. You can change
* the way in which strings are compared by setting a different
* [type@GLib.CompletionStrncmpFunc] in [method@GLib.Completion.set_compare].
*
* `GCompletion` has been marked as deprecated, since this API is rarely
* used and not very actively maintained.
*
* Deprecated: 2.26: Rarely used API
**/
/**
* GCompletionFunc:
* @item: the completion item.
*
* Specifies the type of the function passed to g_completion_new(). It
* should return the string corresponding to the given target item.
* This is used when you use data structures as #GCompletion items.
*
* Returns: the string corresponding to the item.
* Deprecated: 2.26: Rarely used API
**/
/**
* GCompletionStrncmpFunc:
* @s1: string to compare with @s2.
* @s2: string to compare with @s1.
* @n: maximal number of bytes to compare.
*
* Specifies the type of the function passed to
* g_completion_set_compare(). This is used when you use strings as
* #GCompletion items.
*
* Returns: an integer less than, equal to, or greater than zero if
* the first @n bytes of @s1 is found, respectively, to be
* less than, to match, or to be greater than the first @n
* bytes of @s2.
* Deprecated: 2.26: Rarely used API
**/
static void completion_check_cache (GCompletion* cmp,
gchar** new_prefix);
/**
* g_completion_new:
* @func: the function to be called to return the string representing
* an item in the #GCompletion, or %NULL if strings are going to
* be used as the #GCompletion items.
*
* Creates a new #GCompletion.
*
* Returns: the new #GCompletion.
* Deprecated: 2.26: Rarely used API
**/
GCompletion*
g_completion_new (GCompletionFunc func)
{
GCompletion* gcomp;
gcomp = g_new (GCompletion, 1);
gcomp->items = NULL;
gcomp->cache = NULL;
gcomp->prefix = NULL;
gcomp->func = func;
gcomp->strncmp_func = strncmp;
return gcomp;
}
/**
* g_completion_add_items:
* @cmp: the #GCompletion.
* @items: (transfer none): the list of items to add.
*
* Adds items to the #GCompletion.
*
* Deprecated: 2.26: Rarely used API
**/
void
g_completion_add_items (GCompletion* cmp,
GList* items)
{
GList* it;
g_return_if_fail (cmp != NULL);
/* optimize adding to cache? */
if (cmp->cache)
{
g_list_free (cmp->cache);
cmp->cache = NULL;
}
if (cmp->prefix)
{
g_free (cmp->prefix);
cmp->prefix = NULL;
}
it = items;
while (it)
{
cmp->items = g_list_prepend (cmp->items, it->data);
it = it->next;
}
}
/**
* g_completion_remove_items:
* @cmp: the #GCompletion.
* @items: (transfer none): the items to remove.
*
* Removes items from a #GCompletion. The items are not freed, so if the memory
* was dynamically allocated, free @items with g_list_free_full() after calling
* this function.
*
* Deprecated: 2.26: Rarely used API
**/
void
g_completion_remove_items (GCompletion* cmp,
GList* items)
{
GList* it;
g_return_if_fail (cmp != NULL);
it = items;
while (cmp->items && it)
{
cmp->items = g_list_remove (cmp->items, it->data);
it = it->next;
}
it = items;
while (cmp->cache && it)
{
cmp->cache = g_list_remove(cmp->cache, it->data);
it = it->next;
}
}
/**
* g_completion_clear_items:
* @cmp: the #GCompletion.
*
* Removes all items from the #GCompletion. The items are not freed, so if the
* memory was dynamically allocated, it should be freed after calling this
* function.
*
* Deprecated: 2.26: Rarely used API
**/
void
g_completion_clear_items (GCompletion* cmp)
{
g_return_if_fail (cmp != NULL);
g_list_free (cmp->items);
cmp->items = NULL;
g_list_free (cmp->cache);
cmp->cache = NULL;
g_free (cmp->prefix);
cmp->prefix = NULL;
}
static void
completion_check_cache (GCompletion* cmp,
gchar** new_prefix)
{
GList* list;
gsize len;
gsize i;
gsize plen;
gchar* postfix;
gchar* s;
if (!new_prefix)
return;
if (!cmp->cache)
{
*new_prefix = NULL;
return;
}
len = strlen(cmp->prefix);
list = cmp->cache;
s = cmp->func ? cmp->func (list->data) : (gchar*) list->data;
postfix = s + len;
plen = strlen (postfix);
list = list->next;
while (list && plen)
{
s = cmp->func ? cmp->func (list->data) : (gchar*) list->data;
s += len;
for (i = 0; i < plen; ++i)
{
if (postfix[i] != s[i])
break;
}
plen = i;
list = list->next;
}
*new_prefix = g_new0 (gchar, len + plen + 1);
strncpy (*new_prefix, cmp->prefix, len);
strncpy (*new_prefix + len, postfix, plen);
}
/**
* g_completion_complete_utf8:
* @cmp: the #GCompletion
* @prefix: the prefix string, typically used by the user, which is compared
* with each of the items
* @new_prefix: if non-%NULL, returns the longest prefix which is common to all
* items that matched @prefix, or %NULL if no items matched @prefix.
* This string should be freed when no longer needed.
*
* Attempts to complete the string @prefix using the #GCompletion target items.
* In contrast to g_completion_complete(), this function returns the largest common
* prefix that is a valid UTF-8 string, omitting a possible common partial
* character.
*
* You should use this function instead of g_completion_complete() if your
* items are UTF-8 strings.
*
* Returns: (element-type utf8) (transfer none): the list of items whose strings begin with @prefix. This should
* not be changed.
*
* Since: 2.4
*
* Deprecated: 2.26: Rarely used API
**/
GList*
g_completion_complete_utf8 (GCompletion *cmp,
const gchar *prefix,
gchar **new_prefix)
{
GList *list;
gchar *p, *q;
list = g_completion_complete (cmp, prefix, new_prefix);
if (new_prefix && *new_prefix)
{
p = *new_prefix + strlen (*new_prefix);
q = g_utf8_find_prev_char (*new_prefix, p);
switch (g_utf8_get_char_validated (q, p - q))
{
case (gunichar)-2:
case (gunichar)-1:
*q = 0;
break;
default: ;
}
}
return list;
}
/**
* g_completion_complete:
* @cmp: the #GCompletion.
* @prefix: the prefix string, typically typed by the user, which is
* compared with each of the items.
* @new_prefix: if non-%NULL, returns the longest prefix which is
* common to all items that matched @prefix, or %NULL if
* no items matched @prefix. This string should be freed
* when no longer needed.
*
* Attempts to complete the string @prefix using the #GCompletion
* target items.
*
* Returns: (transfer none): the list of items whose strings begin with
* @prefix. This should not be changed.
*
* Deprecated: 2.26: Rarely used API
**/
GList*
g_completion_complete (GCompletion* cmp,
const gchar* prefix,
gchar** new_prefix)
{
gsize plen, len;
gboolean done = FALSE;
GList* list;
g_return_val_if_fail (cmp != NULL, NULL);
g_return_val_if_fail (prefix != NULL, NULL);
len = strlen (prefix);
if (cmp->prefix && cmp->cache)
{
plen = strlen (cmp->prefix);
if (plen <= len && ! cmp->strncmp_func (prefix, cmp->prefix, plen))
{
/* use the cache */
list = cmp->cache;
while (list)
{
GList *next = list->next;
if (cmp->strncmp_func (prefix,
cmp->func ? cmp->func (list->data) : (gchar*) list->data,
len))
cmp->cache = g_list_delete_link (cmp->cache, list);
list = next;
}
done = TRUE;
}
}
if (!done)
{
/* normal code */
g_list_free (cmp->cache);
cmp->cache = NULL;
list = cmp->items;
while (*prefix && list)
{
if (!cmp->strncmp_func (prefix,
cmp->func ? cmp->func (list->data) : (gchar*) list->data,
len))
cmp->cache = g_list_prepend (cmp->cache, list->data);
list = list->next;
}
}
if (cmp->prefix)
{
g_free (cmp->prefix);
cmp->prefix = NULL;
}
if (cmp->cache)
cmp->prefix = g_strdup (prefix);
completion_check_cache (cmp, new_prefix);
return *prefix ? cmp->cache : cmp->items;
}
/**
* g_completion_free:
* @cmp: the #GCompletion.
*
* Frees all memory used by the #GCompletion. The items are not freed, so if
* the memory was dynamically allocated, it should be freed after calling this
* function.
*
* Deprecated: 2.26: Rarely used API
**/
void
g_completion_free (GCompletion* cmp)
{
g_return_if_fail (cmp != NULL);
g_completion_clear_items (cmp);
g_free (cmp);
}
/**
* g_completion_set_compare:
* @cmp: a #GCompletion.
* @strncmp_func: the string comparison function.
*
* Sets the function to use for string comparisons. The default string
* comparison function is strncmp().
*
* Deprecated: 2.26: Rarely used API
**/
void
g_completion_set_compare(GCompletion *cmp,
GCompletionStrncmpFunc strncmp_func)
{
cmp->strncmp_func = strncmp_func;
}
#ifdef TEST_COMPLETION
#include <stdio.h>
int
main (int argc,
char* argv[])
{
FILE *file;
gchar buf[1024];
GList *list;
GList *result;
GList *tmp;
GCompletion *cmp;
gint i;
gchar *longp = NULL;
if (argc < 3)
{
g_warning ("Usage: %s filename prefix1 [prefix2 ...]",
(argc > 0) ? argv[0] : "gcompletion");
return 1;
}
file = fopen (argv[1], "r");
if (!file)
{
g_warning ("Cannot open %s", argv[1]);
return 1;
}
cmp = g_completion_new (NULL);
list = g_list_alloc ();
while (fgets (buf, 1024, file))
{
list->data = g_strdup (buf);
g_completion_add_items (cmp, list);
}
fclose (file);
for (i = 2; i < argc; ++i)
{
printf ("COMPLETING: %s\n", argv[i]);
result = g_completion_complete (cmp, argv[i], &longp);
g_list_foreach (result, (GFunc) printf, NULL);
printf ("LONG MATCH: %s\n", longp);
g_free (longp);
longp = NULL;
}
g_list_foreach (cmp->items, (GFunc) g_free, NULL);
g_completion_free (cmp);
g_list_free (list);
return 0;
}
#endif