/
LIB3/
LIB3/D/ADMIN/
LIB3/D/ADMIN/OBJ/
LIB3/D/ADMIN/ROOM/W/
LIB3/D/HOME/
LIB3/D/HOME/CITY/ARENA/
LIB3/D/HOME/CITY/ITEMS/
LIB3/D/HOME/CITY/POSTOFFI/
LIB3/DOC/
LIB3/GLOBAL/SPECIAL/
LIB3/GLOBAL/VIRTUAL/
LIB3/NET/
LIB3/NET/CONFIG/
LIB3/NET/DAEMON/CHARS/
LIB3/NET/GOPHER/
LIB3/NET/INHERIT/
LIB3/NET/OBJ/
LIB3/NET/SAVE/
LIB3/NET/VIRTUAL/
LIB3/OBJ/B_DAY/
LIB3/OBJ/HANDLERS/TERM_TYP/
LIB3/PLAYERS/B/
LIB3/PLAYERS/N/
LIB3/ROOM/
LIB3/SAVE/
LIB3/SAVE/BOARDS/
LIB3/SAVE/ENVIRON/
LIB3/SAVE/POST/
LIB3/STD/COMMANDS/SHADOWS/
LIB3/STD/CREATOR/
LIB3/STD/DOM/
LIB3/STD/EFFECTS/
LIB3/STD/EFFECTS/HEALING/
LIB3/STD/EFFECTS/OTHER/
LIB3/STD/EFFECTS/POISONS/
LIB3/STD/ENVIRON/
LIB3/STD/GUILDS/
LIB3/STD/LIQUIDS/
LIB3/STD/ROOM/
LIB3/STD/TRIGGER/SHADOW/
LIB3/W/
LIB3/W/BANNOR/
LIB3/W/NEWSTYLE/
/*
 * A nroff like object for formating text files.
 *
 * This creates a saveable file format thingy.
 */
#include "nroff.h"

mixed  *nroffed_file;
string  nroffed_file_name;
int     modified_time;

void    create()
{
    nroffed_file = ({ });
    seteuid( "Root" );		/* Security risk?  nahhhhh */
}				/* create() */

#define do_bounds(bing) (bing<0?bing+cols:bing)

/*
 * Creates a string from a nroffed file
 *
 * If update is non zero it will try and find the file_name and return
 * 0 from here if it is either not found, or non existant...
 */
string  cat_file( string fname, int update )
{
    int     i, cols;
    string  ret;

    if( !"/secure/master"->valid_read( fname, geteuid( previous_object() ),
				       "restore_object" ) )
	return 0;
    nroffed_file_name = 0;
    modified_time = 0;
    if( !restore_object( fname ) )
	return 0;
    if( !nroffed_file_name && update )
	return 0;
    if( update )
    {
	mixed * something;

	if( !"/secure/master"->valid_read( nroffed_file_name,
					   geteuid( previous_object() ),
					   "restore_object" ) )
	    return 0;
	if( file_size( nroffed_file_name ) <= 0 )
	    return 0;
	something = stat( nroffed_file_name );
	if( something[ 1 ] > modified_time )
	    return 0;
    }
    ret = "";
    cols = (int)this_player()->query_cols();
    for( i = 0; i < sizeof( nroffed_file ); i++ )
	if( stringp( nroffed_file[ i ] ) )
	    ret += nroffed_file[ i ];
	else
	    switch( nroffed_file[ i ] )
	    {
		case V_CENTER:
		    ret += sprintf( "%|=*s", cols, nroffed_file[ i + 1 ] );
		    i++;
		    break;
		case V_ALL:
		    ret += sprintf( "%-*s%|*s%*s\n", nroffed_file[ i + 1 ],
				    nroffed_file[ i + 2 ],
				    cols - nroffed_file[ i + 1 ] * 2,
				    nroffed_file[ i + 3 ],
				    nroffed_file[ i + 1 ],
				    nroffed_file[ i + 4 ] );
		    i += 4;
		    break;
		case V_INDENT:
		    ret += sprintf( "%*=s%-=*s\n", nroffed_file[ i + 1 ], "",
				    cols - nroffed_file[ i + 1 ],
				    nroffed_file[ i + 2 ] );
		    i += 2;
		    break;
		case V_PARA:
		    ret += sprintf( "%*=s%-=*s%=*s\n", nroffed_file[ i + 1 ], "",
				    cols - nroffed_file[ i + 1 ] -
				    nroffed_file[ i + 2 ], nroffed_file[ i + 3 ],
				    nroffed_file[ i + 2 ], "" );
		    i += 3;
		    break;
		case V_LEFT:
		    ret += sprintf( "%-=*s", cols, nroffed_file[ i + 1 ] );
		    i++;
		    break;
		case V_TABLE:
		    ret += sprintf( "%-#*s", cols, nroffed_file[ i + 1 ] );
		    i++;
		    break;
		case V_COLUMN:
		    {
			int     j;

			switch( sizeof( nroffed_file[ i + 1 ] ) )
			{
			    case 2:
				for( j = 0; j < sizeof( nroffed_file[ i + 2 ] ); j++ )
				    ret += sprintf( "%*-=s%*-=s\n", do_bounds( nroffed_file[ i + 1 ][ 0 ] ),
						    nroffed_file[ i + 2 ][ j ],
						    do_bounds( nroffed_file[ i + 1 ][ 1 ] ),
						    nroffed_file[ i + 3 ][ j ] );
				i += 3;
				break;
			    case 3:
				for( j = 0; j < sizeof( nroffed_file[ i + 2 ] ); j++ )
				    ret += sprintf( "%*-=s%*-=s%*-=s\n",
						    do_bounds( nroffed_file[ i + 1 ][ 0 ] ),
						    nroffed_file[ i + 2 ][ j ],
						    do_bounds( nroffed_file[ i + 1 ][ 1 ] ),
						    nroffed_file[ i + 3 ][ j ],
						    do_bounds( nroffed_file[ i + 1 ][ 2 ] ),
						    nroffed_file[ i + 4 ][ j ] );
				i += 4;
				break;
			}
			break;
		    }
	    }
    return " \n" + ret;
}

static int new_string, force_string;

void    add_array( mixed *i )
{
    if( !sizeof( nroffed_file ) )
	nroffed_file += ({ i });
    else
	if( force_string )
	    nroffed_file += ({ "", i });
	else
	    nroffed_file += ({ i });
    force_string = 0;
    new_string = 0;
}

void    add_int( int i )
{
    if( !sizeof( nroffed_file ) )
	nroffed_file += ({ i });
    else
	if( force_string )
	    nroffed_file += ({ "", i });
	else
	    nroffed_file += ({ i });
    force_string = 0;
    new_string = 0;
}

void    add_string( string s )
{
    if( !sizeof( nroffed_file ) || new_string )
	nroffed_file += ({ s });
    else
	if( stringp( nroffed_file[ sizeof( nroffed_file ) - 1 ] ) )
	    nroffed_file[ sizeof( nroffed_file ) - 1 ] += s;
	else
	    nroffed_file += ({ s });
    new_string = 0;
    force_string = 0;
}

int     create_nroff( string in_file, string out_file )
{
    string  text, tmp, *bits;
    string *bing;
    mixed * cols;
    int     strip_crs, col_mode, conv_tabs, i, j, k, num_cols;

    if( !"/secure/master"->valid_read( in_file, geteuid( previous_object() ),
				       "read_file" ) )
	return 0;
    if( !"/secure/master"->valid_write( out_file, geteuid( previous_object() ),
					"save_object" ) )
	return 0;
    nroffed_file_name = in_file;
    modified_time = time();
    text = read_file( in_file );
    if( !text )
	return 0;
    bits = explode( "#\n" + text, "\n." );
    bits[ 0 ] = bits[ 0 ][ 1..100000 ];
    nroffed_file = ({ 0 });
    if( strlen( bits[ 0 ] ) )
	add_string( bits[ 0 ] );
    for( i = 1; i < sizeof( bits ); i++ )
    {
/*
   if (!strlen(bits[i])) {
   if (col_mode) {
   for (j=0;j<num_cols;j++)
   cols[j] += "\n";
   } else if (strip_crs)
   add_string("\n\n");
   else
   add_string("\n");
   } else if (bits[i][0] == '.') {
 */
	if( sscanf( bits[ i ], "%s\n%s", tmp, bits[ i ] ) != 2 )
	{
	    tmp = bits[ i ];
	    bits[ i ] = "";
	}
	switch( tmp[ 0..1 ] )
	{
	    case "SI":		/* Start indent */
		add_int( V_INDENT );
		j = 0;
		sscanf( tmp[ 2..1000 ], "%d%s", j, tmp );
		add_int( j );
		force_string = 1;
		break;
	    case "EI":		/* End paragraph */
		new_string = 1;
		break;
	    case "SP":		/* Start paragraph */
		add_int( V_PARA );
		j = 0;
		sscanf( tmp[ 2..1000 ], "%d%s", j, tmp );
		add_int( j );
		j = 0;
		sscanf( tmp, " %d%s", j, tmp );
		add_int( j );
		force_string = 1;
		strip_crs = 1;
		break;
	    case "EP":		/* End paragraph */
		new_string = 1;
		strip_crs = 0;
		break;
	    case "SC":		/* start centering */
		add_int( V_CENTER );
		force_string = 1;
		break;
	    case "EC":		/* End centering */
		new_string = 1;
		break;
	    case "SL":		/* Start left justify */
		add_int( V_LEFT );
		force_string = 1;
		break;
	    case "EL ":	/* End left justify */
		new_string = 1;
		break;
	    case "ST":		/* Start table mode (Turn tabs into new lines) */
		add_int( V_TABLE );
		force_string = 1;
		conv_tabs = 1;
		break;
	    case "ET":		/* End table mode */
		new_string = 1;
		conv_tabs = 0;
		break;
	    case "DT":		/* Do title.  Take the next three lines... */
		bing = explode( bits[ i ], "\n" );
		if( sizeof( bing ) < i + 3 )
		    return 0;	/* failed! */
		add_int( V_ALL );
		if( strlen( bing[ 0 ] ) > strlen( bing[ 2 ] ) )
		    add_int( strlen( bing[ 0 ] ) );
		else
		    add_int( strlen( bing[ 2 ] ) );
		new_string = 1;
		add_string( bing[ 0 ] );
		new_string = 1;
		add_string( bing[ 1 ] );
		new_string = 1;
		add_string( bing[ 2 ] );
		new_string = 1;
		bits[ i ] = implode( bing[ 3..1000 ], "\n" );
		break;
	    case "SO":		/* starts column mode. The numbers after it
				 * are column size */
		num_cols = 0;
		tmp = tmp[ 2..1000 ];
		cols = ({ });
		while( sscanf( tmp, "%d%s", j, tmp ) == 2 )
		{
		    cols += ({ j });
		    num_cols++;
		    while( strlen( tmp ) && tmp[ 0 ] == ' ' )
			tmp = tmp[ 1..1000 ];
		}
		add_int( V_COLUMN );
		if( sscanf( tmp, "%d", j ) == 1 )
		{
		    cols += ({ j });
		    num_cols++;
		}
		add_array( cols );
		cols = allocate( num_cols );
		for( j = 0; j < num_cols; j++ )
		    cols[ j ] = ({ });
		col_mode = 1;
		break;
	    case "EO":		/* End column mode */
		for( j = 0; j < num_cols; j++ )
		{
		    add_array( cols[ j ] );
		}
		col_mode = 0;
		break;
	}
/* Now dis bit...  */
	if( !strlen( bits[ i ] ) )
	    continue;
	if( conv_tabs )
	    bits[ i ] = replace( bits[ i ], "\t", "\n" );
	if( col_mode )
	{
	    string *frog;

	    frog = explode( bits[ i ], "\n" );
	    for( k = 0; k < sizeof( frog ); k++ )
	    {
		bing = explode( "#" + frog[ k ], "\t" );
		bing[ 0 ] = bing[ 0 ][ 1..1000 ];
		for( j = 0; j < num_cols && j < sizeof( bing ); j++ )
		    cols[ j ] += ({ bing[ j ] });
		for( j = sizeof( bing ); j < num_cols; j++ )
		    cols[ j ] += ({ "\n" });
	    }
	}
	else
	    if( strip_crs )
	    {
		bits[ i ] = replace_string( bits[ i ], "\n\n", "$%^NeW_LiNe^%$" );
		bits[ i ] = replace_string( bits[ i ], "\n", " " );
		bits[ i ] = replace_string( bits[ i ], "$%^NeW_LiNe^%$", "\n\n" );
		add_string( bits[ i ] + " " );
	    }
	    else
		add_string( bits[ i ] + "\n" );
/*
   }
 */
    }
    new_string = 0;
    force_string = 0;
    save_object( out_file );
    return 1;
}

void    create_help( string path, string file )
{
    if( path[ 0..4 ] == "/doc/" )
	this_object()->create_nroff( path + file, NROFF_DIR + file );
    else
	write( "Invalid path. " + path + "\n" );
}

void    create_chelp( string path, string file )
{
    if( path[ 0..4 ] == "/doc/" )
	this_object()->create_nroff( path + file, CNROFF_DIR + file );
    else
	write( "Invalid path.\n" );
}