mud++0.35/etc/
mud++0.35/etc/guilds/
mud++0.35/help/propert/
mud++0.35/mudC/
mud++0.35/player/
mud++0.35/src/interface/
mud++0.35/src/os/cygwin32/
mud++0.35/src/os/win32/
mud++0.35/src/os/win32/bcppbuilder/
mud++0.35/src/osaddon/
mud++0.35/src/util/
/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@hom.net 
MUD++ development mailing list    mudpp@van.ml.org
------------------------------------------------------------------------------
help.cc
*/

#include "config.h"
#include "io.h"
#include "string.h"
#include "llist.h"
#include "hash.h"
#include "help.h"
#include "global.h"
#include "pc.h"
#include "bit.h"


const bitType help_bit_list[] =
{
	{0,				0				},
	{"all",			ALL_CAN_READ	},
	{"no-title", 	NO_TITLE		},
	{0,				0				}
};

/*
 *	Helps are registered in both LList and HashTable.
 *  LList is used for keeping them for later saving
 *	and HashTable is used for quick lookups
 *  One help has one entru in LList, but may have many in HashTables
 *  (one for every keyword)
 */

void Help::add( Help * help )
{
	char buf[BUF];
	const char * name;

	// add it to hashtable under each of the names
	// maybe we will add later '' delimited strings, not only words

	// Temp copy - strtok do not use const pointers
	strcpy( buf, help->getName().chars() );
	name = strtok( buf, " " );
	helps_ht.add( String(name), help );

	while ( ( name = strtok( NULL, " "	) ) != NULL )
		helps_ht.add( String(name), help );
	
	// Add also to normal LList
	helps_ll.add(help);
}

void Help::remove( Help * help )
{
	// remove from LList
	helps_ll.remove(help);

	// and from hashTable
	helps_ht.removeAllInstancesOf(help);

}

void loadHelps()
{
	char filename[BUF];
	char buf[BUF];
	Help * help;

	sprintf( filename, "%s/%s", HELP_DIR, HELP_FILE );

	InputFile in( filename );
 
	if( !in )
	{
		Cout<<"loadHelps : can't open help file "<<filename<<endl;
		return;
	}

	int i = 0;

	while( in && ( (*buf = in.getch()) != '#' ) )
	{
		in.putback();
		help = new Help();
		help->readFrom(in);
		Help::add(help);
		i++;
		in.skipwhite();
	}
 
	Cout<<"Help index loaded with "<<i<<" keywords.\n"; 
}

void saveHelps()
{
	char filename[BUF];
	Help * help;
	sprintf( filename, "%s/%s", HELP_DIR, HELP_FILE );

	OutputFile out( filename );
 
	if( !out )
	{
		Cout<< "saveHelps : can't open help file "<<filename<<endl;
		return;
	}

	for_each( helps_ll, help )
	{
		help->writeTo(out);
	}
	out << "#";
	out.close(); 
}

int Help::readFrom( StaticInput &in )
{
	if( !in )
		return -1;

	char buf[ BUF ];
	setName( in.getstring( buf ) );
	level = in.getnum();
	filename = in.getword( buf );
	//in.getbitfield( priv_needed );
	in.getnum();
	priv_needed = in.getnum();
	in.getbitfield( help_bits );
	return 0;
}

int Help::writeTo( Output &out ) const
{
	if( !out ) 
		return -1;

	out << name << "~\t" << level << "\t" << filename << " ";
	//out.putbitfield( priv_needed, MAX_PRIV_BIT_FIELDS );
	out << "1 " << priv_needed;
	out << " ";
	out.putbitfield( help_bits, MAX_HELP_BIT_FIELDS );
	out << endl;
	return 0;
}

bool Help::isAllowed( PC * pc )
{
	if ( pc->getLevel() < level )
		return false;

	if ( IS_SET( help_bits, ALL_CAN_READ ) )
		return true;
	
	return pc->authorized(priv_needed);
}


// HINTS HANDLING


Array<char *> hints;
char * hint_space = NULL;
bool hints_in_edit = false;

int loadHints()
{
	InputFile hints_file(HINTS_FILE);
	int size,i;
	char * data;

	if ( hint_space != NULL )
		delete hint_space;

	hints.clr();

	if ( !hints_file )
		return 0;

	size = hints_file.size();
	if ( !size )
		return 0;

	hint_space = new char[size+1];

	memcpy(hint_space, hints_file.getBuf() , size);

	data = &hint_space[0];
	for ( i=0; i < size; i++ )
	{
		if ( hint_space[i] == '~' )
		{
			hint_space[i] = '\0';
			hints.add(data);
			data = &hint_space[i+1];
		}
	}
	hint_space[size] = '\0';
	return hints.length();
}