tries.c revision 50276
150276Speter/****************************************************************************
250276Speter * Copyright (c) 1998 Free Software Foundation, Inc.                        *
350276Speter *                                                                          *
450276Speter * Permission is hereby granted, free of charge, to any person obtaining a  *
550276Speter * copy of this software and associated documentation files (the            *
650276Speter * "Software"), to deal in the Software without restriction, including      *
750276Speter * without limitation the rights to use, copy, modify, merge, publish,      *
850276Speter * distribute, distribute with modifications, sublicense, and/or sell       *
950276Speter * copies of the Software, and to permit persons to whom the Software is    *
1050276Speter * furnished to do so, subject to the following conditions:                 *
1150276Speter *                                                                          *
1250276Speter * The above copyright notice and this permission notice shall be included  *
1350276Speter * in all copies or substantial portions of the Software.                   *
1450276Speter *                                                                          *
1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
2250276Speter *                                                                          *
2350276Speter * Except as contained in this notice, the name(s) of the above copyright   *
2450276Speter * holders shall not be used in advertising or otherwise to promote the     *
2550276Speter * sale, use or other dealings in this Software without prior written       *
2650276Speter * authorization.                                                           *
2750276Speter ****************************************************************************/
2850276Speter
2950276Speter/****************************************************************************
3050276Speter *  Author: Thomas E. Dickey <dickey@clark.net> 1997                        *
3150276Speter ****************************************************************************/
3250276Speter
3350276Speter/*
3450276Speter**	tries.c
3550276Speter**
3650276Speter**	Functions to manage the tree of partial-completions for keycodes.
3750276Speter**
3850276Speter*/
3950276Speter
4050276Speter#include <curses.priv.h>
4150276Speter
4250276SpeterMODULE_ID("$Id: tries.c,v 1.12 1999/03/01 23:23:59 tom Exp $")
4350276Speter
4450276Speter/*
4550276Speter * Expand a keycode into the string that it corresponds to, returning null if
4650276Speter * no match was found, otherwise allocating a string of the result.
4750276Speter */
4850276Speterchar *_nc_expand_try(struct tries *tree, unsigned short code, int *count, size_t len)
4950276Speter{
5050276Speter	struct tries *ptr = tree;
5150276Speter	char *result = 0;
5250276Speter
5350276Speter	if (code != 0) {
5450276Speter		while (ptr != 0) {
5550276Speter			if ((result = _nc_expand_try(ptr->child, code, count, len + 1)) != 0) {
5650276Speter				break;
5750276Speter			}
5850276Speter			if (ptr->value == code) {
5950276Speter				*count -= 1;
6050276Speter				if (*count == -1) {
6150276Speter					result = typeCalloc(char, len+2);
6250276Speter					break;
6350276Speter				}
6450276Speter			}
6550276Speter			ptr = ptr->sibling;
6650276Speter		}
6750276Speter	}
6850276Speter	if (result != 0) {
6950276Speter		if ((result[len] = ptr->ch) == 0)
7050276Speter			*((unsigned char *)(result+len)) = 128;
7150276Speter#ifdef TRACE
7250276Speter		if (len == 0)
7350276Speter			_tracef("expand_key %s %s", _trace_key(code), _nc_visbuf(result));
7450276Speter#endif
7550276Speter	}
7650276Speter	return result;
7750276Speter}
7850276Speter
7950276Speter/*
8050276Speter * Remove a code from the specified tree, freeing the unused nodes.  Returns
8150276Speter * true if the code was found/removed.
8250276Speter */
8350276Speterint _nc_remove_key(struct tries **tree, unsigned short code)
8450276Speter{
8550276Speter	T((T_CALLED("_nc_remove_key(%p,%d)"), tree, code));
8650276Speter
8750276Speter	if (code == 0)
8850276Speter		returnCode(FALSE);
8950276Speter
9050276Speter	while (*tree != 0) {
9150276Speter		if (_nc_remove_key(&(*tree)->child, code)) {
9250276Speter			returnCode(TRUE);
9350276Speter		}
9450276Speter		if ((*tree)->value == code) {
9550276Speter			if((*tree)->child) {
9650276Speter				/* don't cut the whole sub-tree */
9750276Speter				(*tree)->value = 0;
9850276Speter			} else {
9950276Speter				struct tries *to_free = *tree;
10050276Speter				*tree = (*tree)->sibling;
10150276Speter				free(to_free);
10250276Speter			}
10350276Speter			returnCode(TRUE);
10450276Speter		}
10550276Speter		tree = &(*tree)->sibling;
10650276Speter	}
10750276Speter	returnCode(FALSE);
10850276Speter}
10950276Speter
11050276Speter/*
11150276Speter * Remove a string from the specified tree, freeing the unused nodes.  Returns
11250276Speter * true if the string was found/removed.
11350276Speter */
11450276Speterint _nc_remove_string(struct tries **tree, char *string)
11550276Speter{
11650276Speter	T((T_CALLED("_nc_remove_string(%p,%s)"), tree, _nc_visbuf(string)));
11750276Speter
11850276Speter	if (string == 0 || *string == 0)
11950276Speter		returnCode(FALSE);
12050276Speter
12150276Speter	while (*tree != 0) {
12250276Speter		if ((unsigned char)(*tree)->ch == (unsigned char)*string) {
12350276Speter			if (string[1] != 0)
12450276Speter				returnCode(_nc_remove_string(&(*tree)->child, string+1));
12550276Speter			if((*tree)->child) {
12650276Speter				/* don't cut the whole sub-tree */
12750276Speter				(*tree)->value = 0;
12850276Speter			} else {
12950276Speter				struct tries *to_free = *tree;
13050276Speter				*tree = (*tree)->sibling;
13150276Speter				free(to_free);
13250276Speter			}
13350276Speter			returnCode(TRUE);
13450276Speter		}
13550276Speter		tree = &(*tree)->sibling;
13650276Speter	}
13750276Speter	returnCode(FALSE);
13850276Speter}
139