Customizable ANSI Color Code
----------------------------

Original code by Matthew Bafford. See credits info in color.c
Enhanced ANSI parser by Samson of Alsherok.

Note: FUSS users need not bother. This has already been added since it's
considered a bug fix for Smaug 1.4a.

Terms of Use
------------

1. You may use this snippet in your code provided that any included
comment headers in the code are left intact. You may add your own, but
do not take mine out.

2. This snippet may not be posted for redistribution on any site
without obtaining prior written consent from the Alsherok team.

3. ( optional ) Register with the forums at http://forums.alsherok.net
Registration is not required to make use of the snippet, but since I no
longer provide email support for any of the code I release, forum posts
are your only avenue for direct support. This may seem overly stupid,
but you can blame the continuing abuse I suffer from spammers for this.
Don't post stuff to TMC or TMS asking about my code. I'm highly unlikely
to ever notice it there on the rare ocassions I skim posts in either place.

If forum registration doesn't appeal to you, then you can try to get ahold
of me via IMC on the code channel.

If you can't agree to these terms, don't use this code, and don't expect
me to help if something breaks while installing it. Harsh? Hardly. I'm
tired of people who come crawling to whine and complain when they haven't
bothered to comply with the terms first.

What this code does
-------------------

This code allows your players to customize much of their display colors.
In addition it replaces the absolute trash that is Smaug's make_color_sequence
function so that the ANSI codes are processed properly. It also adds a new
tag to reset color to either the default custom setting for a particular
line, or to the default display color for the user's client program.

For Smaug 1.4a users, this is designed to completely replace the stock colorize
command which is more or less a pile of bugware :)

Some mud clients will also support the additional underline, italic, reverse
video, and strikeover color tags that have been added. To determine if they do,
you'll need to install this code and the accompanying help file and see the
results in the examples there.

Installation Instructions
-------------------------

1. To install the code, place color.c an color.h in your src directory.
   Add color.o and color.c to the proper places in the Makefile.

   Remove colorize.o and colorize.c from the Makefile.
   Delete the colorize.c file from your src directory.

   In your dist directory, create a color directory.
   Upload the AFK and Smaug files into the color directory.

2. In mud.h:
   
   Find the following code:

	#define LEVEL_HIGOD		    LEVEL_GOD
   
	and below it add: #include "color.h"

   Find the section of code that starts with:

 /*
  * Real action "TYPES" for act.
  */
   
   Remove everything from there up to and including:

#define AT_MAXCOLOR	(AT_TOPCOLOR-AT_COLORBASE)

   Then find the section that starts out as:

#if 0
#define AT_PLAIN	   AT_GREY

   Remove everything from there up to and including:

#define AT_MORPH           AT_GREY
#endif

   Find and remove:

extern	struct	at_color_type	at_color_table	[AT_MAXCOLOR];

   Find and remove:

struct at_color_type
{
  char *name;
  sh_int def_color;
};

   Find and remove:

DECLARE_DO_FUN( do_colorize	); /* Alty */

   Find and remove:

#define COLOR_FILE	SYSTEM_DIR "colors.dat"	  /* User-definable color*/

   Find struct char_data and add the following to the end:
       
   short colors[MAX_COLORS];

   Find struct pc_data and REMOVE the following line:

    sh_int	colorize	[AT_MAXCOLOR];

3. In comm.c:

   Find and remove the following functions:

   set_char_color, set_pager_color, send_to_pager_color, send_to_char_color,
   send_to_char, send_to_pager, pager_printf, ch_printf, figure_color,
   write_to_pager, ch_printf_color, pager_printf_color, and make_color_sequence.

   Find the following code segment:

    case CON_GET_WANT_RIPANSI:
	switch ( argument[0] )
	{
	case 'r': case 'R':
	    xSET_BIT(ch->act,PLR_RIP);
	    xSET_BIT(ch->act,PLR_ANSI);
	    break;
	case 'a': case 'A': xSET_BIT(ch->act,PLR_ANSI);  break;
	case 'n': case 'N': break;
	default:
	    write_to_buffer( d, "Invalid selection.\r\nRIP, ANSI or NONE? ", 0 );
	    return;
	}

   and below it add: reset_colors( ch );

   In function display_prompt, locate the following:

  if ( ansi )
  {
    strcpy(pbuf, "\033[m");
    d->prevcolor = 0x07;
    pbuf += 3;
  }

   Replace that with the following:

  if ( ansi )
  {
    strcpy( pbuf, ANSI_RESET );
    d->prevcolor = 0x08;
    pbuf += 4;
  }

   Then locate the following:

    /*
     * '&' = foreground color/intensity bit
     * '{' = background color/blink bit
     * '%' = prompt commands
     * Note: foreground changes will revert background to 0 (black)
     */
    if ( *prompt != '&' && *prompt != '{' && *prompt != '%' )
    {
      *(pbuf++) = *prompt;
      continue;
    }

   Change it to read as follows:

    /*
     * '%' = prompt commands
     * Note: foreground changes will revert background to 0 (black)
     */
    if( *prompt != '%' )
    {
      *(pbuf++) = *prompt;
      continue;
    }

   Further down, locate the following code:

    case '&':
    case '^':
      pstat = make_color_sequence(&prompt[-1], pbuf, d);
      if ( pstat < 0 )
        --prompt;
      else if ( pstat > 0 )
        pbuf += pstat;
      break;

   Remove that segment.

   Then right at the bottom of the function, locate the following:

  *pbuf = '\0';
  write_to_buffer(d, buf, (pbuf-buf));
  return;

   Change it to read as follows:

  *pbuf = '\0';
  send_to_char( buf, ch );
  return;

   Locate function pager_output and find the following code:

   if( xIS_SET( ch->act, PLR_ANSI ) )
      if( write_to_descriptor( d->descriptor, "\033[1;36m", 7 ) == FALSE )
	   return FALSE;

   Change that to read as follows:

   if( xIS_SET( ch->act, PLR_ANSI ) )
      if( write_to_descriptor( d->descriptor, ANSI_LBLUE, 0 ) == FALSE )
	   return FALSE;

   Then locate the following code:

      if ( d->pagecolor == 7 )
	   strcpy( buf, "\033[0m" );
      else
	   sprintf( buf, "\033[0;%d;%s%dm", (d->pagecolor & 8) == 8,
		(d->pagecolor > 15 ? "5;" : ""), (d->pagecolor & 7)+30);

   Change that to read as follows:

	snprintf( buf, 32, "%s", color_str( d->pagecolor, ch ) );

   Then locate the following in the act() function:

	if (to->desc)
	{
	  if ( AType == AT_COLORIZE )
	  {
	     if ( txt[0] == '&' )
	     	send_to_char_color( txt, to );
	     else
	     {
	        set_char_color(AT_MAGIC, to );
		write_to_buffer( to->desc, txt, strlen(txt) );
	     }
	  }
	  else {
	     set_char_color(AType, to);
	     write_to_buffer( to->desc, txt, strlen(txt) );
	  }
	}

   Change that all to read as follows:

	if (to->desc)
	{
        set_char_color(AType, to);
        send_to_char( txt, to );
	}

4. In save.c, find the following code in fwrite_char:

    track = URANGE( 2, ((ch->level+3) * MAX_KILLTRACK)/LEVEL_AVATAR, MAX_KILLTRACK );
    for ( sn = 0; sn < track; sn++ )
    {
	if ( ch->pcdata->killed[sn].vnum == 0 )
	  break;
	fprintf( fp, "Killed       %d %d\n",
		ch->pcdata->killed[sn].vnum,
		ch->pcdata->killed[sn].count );
    }

    Below that, add:

    /* Save color values - Samson 9-29-98 */
    { 
	int x;
      fprintf( fp, "MaxColors    %d\n",     MAX_COLORS            );
      fprintf( fp, "Colors       " );
        for ( x = 0; x < MAX_COLORS ; x++ )
            fprintf( fp, "%d ", ch->colors[x] );
      fprintf( fp, "\n" );
    }

   Locate and remove the following segment of code:

        for (sn = 0; sn < AT_MAXCOLOR; ++sn)
          if (ch->pcdata->colorize[sn] != -1)
            fprintf( fp, "Color        %s %d\n", at_color_table[sn].name,
            		ch->pcdata->colorize[sn] );

   Then locate function fread_char:

   Below: bool fMatch;
   add: int max_colors = 0; /* Color code */

   Below: file_ver = 0;
          killcnt = 0;
   add:
    /* Setup color values in case player has none set - Samson */
    memcpy( &ch->colors, &default_set, sizeof(default_set) );

   Locate the following segment of code:

	    if ( !str_cmp( word, "Color" ) )
	    {
		char *cword;
		int at;
		
		cword = fread_word(fp);
		for (at = 0; at < AT_MAXCOLOR; ++at)
		  if (!str_cmp(cword, at_color_table[at].name))
		    break;
		if (at < AT_MAXCOLOR)
		  ch->pcdata->colorize[at] = fread_number(fp);
		else
		{
		  bug("Fread_char: color %s invalid.", cword);
		  fread_number(fp);
		}
		fMatch = TRUE;
		break;
	    }

     Replace it with the following:

          /* Load color values - Samson 9-29-98 */
          {
		int x;
		if ( !str_cmp( word, "Colors" ) )
            {
               for ( x = 0; x < max_colors; x++ )
                  ch->colors[x] = fread_number( fp );
               fMatch = TRUE;
               break;
            }
          }

     Above the following segment:

	    KEY( "MDeaths",	ch->pcdata->mdeaths,	fread_number( fp ) );

     add:

	    KEY( "MaxColors",   max_colors,             fread_number( fp ) );

   Locate and remove the following segment of code:

    for (i = 0; i < AT_MAXCOLOR; ++i)
      ch->pcdata->colorize[i] = -1;

5. In tables.c:

   Find:

	if ( !str_cmp( name, "do_colorize" ))		return do_colorize;

   Replace with:

	if ( !str_cmp( name, "do_color" ))			return do_color;

   Find:

    if ( skill == do_colorize )		return "do_colorize";

   Replace with:

    if ( skill == do_color )		return "do_color";

6. In db.c, find and remove the following:

        log_string ("Loading Colors");
        load_colors( );

7. In magic.c, find all instances of AT_COLORIZE and change them to AT_MAGIC

8. Make clean, and recompile.

9. Replace the contents of "help pcolors" with the contents of color.help
     
10. After rebooting, delete the "colorize" command and replace it with a "color" command.

If there are any problems with this installation, feel free to post your
question to the forums at http://forums.alsherok.net

This code has been installed and tested on Smaug 1.6 FUSS, which is a bugfixed
and cleaned up version of the base Smaug 1.4a code. The Smaug FUSS Project is
maintained on servers which run the Redhat and Fedora family of Linux. Limited
testing has also been done on the Cygwin package under WindowsXP SP1 and SP2.
Users of BSD, MSVC, MSVC++, or Macintosh platforms are on their own as The
Smaug FUSS Project does not have access to these development environments for testing.
The Smaug FUSS Project can be found at: http://www.smaugfuss.org

No guarantees are made that this code will be compatible with your codebase and any
modifications you may have made to it. No warranty of any kind is expressed or implied
by the use of this code, and we are not responsible for any damages which may result
from the application of this snippet to your codebase.

Adventure beckons in the lands of mystique....
Samson, Implementor of Alsherok
http://www.alsherok.net
telnet://alsherok.net:5500

IMC2 contact: Samson@Alsherok