mux2.0/game/
mux2.0/game/data/
mux2.0/src/tools/
/*
 * help.c -- commands for giving help 
 */
/*
 * $Id: help.cpp,v 1.4 2000/06/05 19:09:42 sdennis Exp $ 
 */

#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "externs.h"

#include <fcntl.h>

#include "mudconf.h"
#include "db.h"
#include "interface.h"
#include "help.h"
#include "htab.h"
#include "alloc.h"

/*
 * Pointers to this struct is what gets stored in the help_htab's 
 */
struct help_entry
{
    int pos;        // Position, copied from help_indx
    char original;  // 1 for the longest name for a topic. 0 for
                    // abbreviations.
    char *key;      // The key this is stored under.
};

void helpindex_clean(CHashTable *htab)
{
    struct help_entry *htab_entry;
    for (htab_entry = (struct help_entry *)hash_firstentry(htab);
         htab_entry;
         htab_entry = (struct help_entry *)hash_nextentry(htab))
    {
        MEMFREE(htab_entry->key);
        MEMFREE(htab_entry);
    }

    hashflush(htab);
}

int helpindex_read(CHashTable *htab, char *filename)
{
    help_indx entry;
    char *p;
    int count;
    FILE *fp;

    // Let's clean out our hash table, before we throw it away.
    //
    helpindex_clean(htab);

    if ((fp = fopen(filename, "rb")) == NULL)
    {
        STARTLOG(LOG_PROBLEMS, "HLP", "RINDX")
        p = alloc_lbuf("helpindex_read.LOG");
        sprintf(p, "Can't open %s for reading.", filename);
        log_text(p);
        free_lbuf(p);
        ENDLOG
        return -1;
    }
    DebugTotalFiles++;
    count = 0;
    while ((fread((char *)&entry, sizeof(help_indx), 1, fp)) == 1)
    {
        // Convert the entry to all lowercase letters and add all leftmost substrings.
        //
        // Substrings already added will be rejected by hashaddLEN.
        //
        _strlwr(entry.topic);
        BOOL bOriginal = 1; // First is the longest.
        int nTopic = strlen(entry.topic);

        for (nTopic = strlen(entry.topic); nTopic > 1; nTopic--)
        {
            if (Tiny_IsSpace[(unsigned char)entry.topic[nTopic-1]])
            {
                continue;
            }
            struct help_entry *htab_entry = (struct help_entry *)MEMALLOC(sizeof(struct help_entry));
            ISOUTOFMEMORY(htab_entry);
            htab_entry->pos = entry.pos;
            htab_entry->original = bOriginal;
            bOriginal = 0;
            htab_entry->key = StringCloneLen(entry.topic, nTopic);

            if ((hashaddLEN(entry.topic, nTopic, (int *)htab_entry, htab)) == 0)
            {
                count++;
            }
            else
            {
                MEMFREE(htab_entry->key);
                MEMFREE(htab_entry);
            }
        }
    }
    if (fclose(fp) == 0)
    {
        DebugTotalFiles--;
    }
    hashreset(htab);
    return count;
}

void helpindex_load(dbref player)
{
    int news, help, whelp;
    int phelp, wnhelp;
    int shelp;

    shelp= helpindex_read(&mudstate.staffhelp_htab, mudconf.staffhelp_indx);
    phelp = helpindex_read(&mudstate.plushelp_htab, mudconf.plushelp_indx);
    wnhelp = helpindex_read(&mudstate.wiznews_htab, mudconf.wiznews_indx);
    news = helpindex_read(&mudstate.news_htab, mudconf.news_indx);
    help = helpindex_read(&mudstate.help_htab, mudconf.help_indx);
    whelp = helpindex_read(&mudstate.wizhelp_htab, mudconf.whelp_indx);
    if ((player != NOTHING) && !Quiet(player))
        notify(player,
               tprintf("Index entries: News...%d  Help...%d  Wizhelp...%d  +Help...%d  Wiznews...%d",
                   news, help, whelp, phelp, wnhelp));
}

void NDECL(helpindex_init)
{
    helpindex_load(NOTHING);
}

void help_write(dbref player, char *topic, CHashTable *htab, char *filename, int eval)
{
    FILE *fp;
    char *p, *line, *bp, *str, *result;
    int offset;
    struct help_entry *htab_entry;
    char matched;
    char *topic_list = 0, *buffp = 0;

    if (*topic == '\0')
    {
        topic = (char *)"help";
    }
    else
    {
        _strlwr(topic);
    }
    htab_entry = (struct help_entry *)hashfindLEN(topic, strlen(topic), htab);
    if (htab_entry)
        offset = htab_entry->pos;
    else {
        matched = 0;
        for (htab_entry = (struct help_entry *)hash_firstentry(htab);
             htab_entry != NULL;
           htab_entry = (struct help_entry *)hash_nextentry(htab)) {
            if (htab_entry->original &&
                quick_wild(topic, htab_entry->key)) {
                if (matched == 0) {
                    matched = 1;
                    topic_list = alloc_lbuf("help_write");
                    buffp = topic_list;
                }
                safe_str(htab_entry->key, topic_list, &buffp);
                safe_chr(' ', topic_list, &buffp);
                safe_chr(' ', topic_list, &buffp);
            }
        }
        if (matched == 0)
            notify(player, tprintf("No entry for '%s'.", topic));
        else {
            notify(player, tprintf("Here are the entries which match '%s':", topic));
            *buffp = '\0';
            notify(player, topic_list);
            free_lbuf(topic_list);
        }
        return;
    }
    if ((fp = fopen(filename, "rb")) == NULL)
    {
        notify(player, "Sorry, that function is temporarily unavailable.");
        STARTLOG(LOG_PROBLEMS, "HLP", "OPEN")
        line = alloc_lbuf("help_write.LOG.open");
        sprintf(line, "Can't open %s for reading.", filename);
        log_text(line);
        free_lbuf(line);
        ENDLOG
        return;
    }
    DebugTotalFiles++;
    if (fseek(fp, offset, 0) < 0L)
    {
        notify(player, "Sorry, that function is temporarily unavailable.");
        STARTLOG(LOG_PROBLEMS, "HLP", "SEEK")
        line = alloc_lbuf("help_write.LOG.seek");
        sprintf(line, "Seek error in file %s.", filename);
        log_text(line);
        free_lbuf(line);
        ENDLOG
        if (fclose(fp) == 0)
        {
            DebugTotalFiles--;
        }
        return;
    }
    line = alloc_lbuf("help_write");
    result = alloc_lbuf("help_write.2");
    for (;;)
    {
        if (fgets(line, LBUF_SIZE - 1, fp) == NULL)
            break;
        if (line[0] == '&')
            break;
        for (p = line; *p != '\0'; p++)
            if (*p == '\n')
                *p = '\0';
        if (eval)
        {
            str = line;
            bp = result;
            TinyExec(result, &bp, 0, player, player, EV_NO_COMPRESS | EV_FIGNORE | EV_EVAL, &str, (char **)NULL, 0);
            *bp = '\0';
            notify(player, result);
        }
        else
        {
            notify(player, line);
        }
    }
    if (fclose(fp) == 0)
    {
        DebugTotalFiles--;
    }
    free_lbuf(line);
    free_lbuf(result);
}

/*
 * ---------------------------------------------------------------------------
 * * do_help: display information from new-format news and help files
 */

void do_help(dbref player, dbref cause, int key, char *message)
{
    char *buf;

    switch (key) {
    case HELP_HELP:
        help_write(player, message, &mudstate.help_htab, mudconf.help_file, 0);
        break;
    case HELP_NEWS:
        help_write(player, message, &mudstate.news_htab, mudconf.news_file, 1);
        break;
    case HELP_WIZHELP:
        help_write(player, message, &mudstate.wizhelp_htab, mudconf.whelp_file, 0);
        break;
    case HELP_PLUSHELP:
        help_write(player, message, &mudstate.plushelp_htab, mudconf.plushelp_file, 1);
        break;
    case HELP_STAFFHELP:
        help_write(player, message, &mudstate.staffhelp_htab, mudconf.staffhelp_file, 1);
        break;
    case HELP_WIZNEWS:
        help_write(player, message, &mudstate.wiznews_htab, mudconf.wiznews_file, 0);
        break;
    default:
        STARTLOG(LOG_BUGS, "BUG", "HELP")
        buf = alloc_mbuf("do_help.LOG");
        sprintf(buf, "Unknown help file number: %d", key);
        log_text(buf);
        free_mbuf(buf);
        ENDLOG
    }
}