/* $Cambridge: hermes/src/prayer/session/dictionary.c,v 1.3 2008/09/16 09:59:58 dpc22 Exp $ */
/************************************************
 *    Prayer - a Webmail Interface              *
 ************************************************/

/* Copyright (c) University of Cambridge 2000 - 2008 */
/* See the file NOTICE for conditions of use and distribution. */

#include "prayer_session.h"

/* dictionary_create() ***************************************************
 *
 * Create a fresh dictionary structure, including own pool.
 ************************************************************************/

struct dictionary *dictionary_create()
{
    struct pool *pool = pool_create(DICTIONARY_POOL_SIZE);
    struct dictionary *d;

    d = pool_alloc(pool, sizeof(struct dictionary));
    d->pool = pool;
    d->list = list_create(pool, T);
    d->assoc = assoc_create(pool, 16, T);

    return (d);
}

/* dictionary_free() ******************************************************
 *
 * Free dictionary structure
 *************************************************************************/

void dictionary_free(struct dictionary *d)
{
    pool_free(d->pool);
}

/* ====================================================================== */

/* dictionary_print_options() *********************************************
 *
 * Convert dictionary to text form suitable for user preferences file.
 *   dictionary:
 *            b: Output buffer
 *************************************************************************/

void
dictionary_print_options(struct dictionary *dictionary, struct buffer *b)
{
    unsigned long offset = 0;
    struct list_item *li;

    for (li = dictionary->list->head; li; li = li->next) {
        if ((offset + strlen(li->name)) >= 76) {
            /* Add word to start of line */
            if (offset > 0)
                bputs(b, "" CRLF);
            bputs(b, li->name);
            offset = strlen(li->name);
        } else {
            /* Add word to end of existing (non-empty) line */
            if (offset > 0)
                bputc(b, ' ');
            bputs(b, li->name);
            offset += strlen(li->name);
        }
    }
    if (offset > 0)
        bputs(b, "" CRLF);
}

/* dictionary_parse_line() ***********************************************
 *
 * Parse a line from user preferences file.
 *  dictionary: dictionary to add to
 *        line: Line to parse
 *     session: For logging purposes only
 * 
 ************************************************************************/

void
dictionary_parse_line(struct dictionary *dictionary, char *line,
                      struct session *session)
{
    char *word;

    while ((word = string_get_token(&line))) {
        if (word[0])
            dictionary_add(dictionary, word);
    }
}

/* ====================================================================== */

/* dictionary_add() ******************************************************
 *
 * Add a word to the dictionary
 *      d: Dictionary
 *   word: Word to add (copied into dictionaries private pool)
 ************************************************************************/

void dictionary_add(struct dictionary *d, char *word)
{
    word = pool_strdup(d->pool, word);

    /* Check whether word is already in the dictionary */
    if (assoc_lookup(d->assoc, word))
        return;

    /* Add word to assoc chain */
    assoc_update(d->assoc, word, "1", NIL);

    /* Insert word at correct sorted place in word list */
    list_insert_sorted(d->list, NIL, word);
}

/* dictionary_remove() ***************************************************
 *
 * Remove a word from the dictionary
 *      d: Dictionary
 *   word: Word to remove
 ************************************************************************/

void dictionary_remove(struct dictionary *d, char *word)
{
    word = pool_strdup(d->pool, word);

    /* Remove word from assoc list */
    assoc_delete(d->assoc, word);

    /* Remove word from list */
    list_remove_byname(d->list, word);
}

/* dictionary_lookup() ****************************************************
 *
 * Lookup word in the dictionary.
 *     d: dictionary
 *  word: Word to look up
 *
 * Returns:  T if word was in dictionary, NIL otherwise
 *************************************************************************/

BOOL dictionary_lookup(struct dictionary *d, char *word)
{
    return ((assoc_lookup(d->assoc, word)) ? T : NIL);
}
