/*
* 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
}
}