dotd-2.3.7/area/
dotd-2.3.7/clans/
dotd-2.3.7/classes/
dotd-2.3.7/councils/
dotd-2.3.7/deity/
dotd-2.3.7/dict/
dotd-2.3.7/doc/mudprogs/
dotd-2.3.7/player/a/
dotd-2.3.7/player/g/
/******************************************************************************
 Snippet: Text justification function.
 Author:  Richard Woolcock (aka KaVir).
 Date:    23rd November 1999.
 ******************************************************************************
 This code is copyright (C) 1999 by Richard Woolcock.  It may be used and
 distributed freely, as long as you don't remove this copyright notice.
 ******************************************************************************/

/******************************************************************************
 Remove the following line to use this code in your mud.
 ******************************************************************************/

/*#define STANDALONE_PROGRAM*/

/******************************************************************************
 Required library files.
 ******************************************************************************/

#ifdef STANDALONE_PROGRAM
#define MEMDEBUG
#include "/home/jdefer/memdebug/memdebug.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "justify.h"

/******************************************************************************
 Local operation prototypes.
 ******************************************************************************/

static void AddSpaces ( char **ppszText, int iNumber );

/******************************************************************************
 Standalone main function.
 ******************************************************************************/

#ifdef STANDALONE_PROGRAM
void main( void )
{
   char *pszText = "  a small two-seater Cessna plane crashed into a   cemetery early this afternoon in Mullingarin.irish search and rescue workers have recovered 826 bodies so far and expect that number to climb as digging continues into the night.";
   printf( "Was:[%s]\n\r", pszText );
   printf( "Now:\n\r[%s]\n\r", Justify( pszText, 40, justify_left ) );
   printf( "Now:\n\r[%s]\n\r", Justify( pszText, 40, justify_centre ) );
   printf( "Now:\n\r[%s]\n\r", Justify( pszText, 40, justify_right ) );
}
#endif

/******************************************************************************
 Global operations.
 ******************************************************************************/

/* Function: Justify
 *
 * This function is used to format a piece of text so that it doesn't wrap
 * over the line.  It also allows you to specify the line width and left,
 * right or centre justification.
 *
 * The function takes three parameters, as follows:
 *
 * pszText:    A pointer to the string to be justified.
 * iAlignment: The width in characters of the formatted text.
 * eJustify:   The style of justification: left, right or centre.
 *
 * The return value is a pointer to a non-stack based string which contains
 * the newly formatted text.
 */
char *Justify( char *pszText, int iAlignment, justify_type eJustify )
{
   static char s_szResult[4096];
   char *      pszResult = &s_szResult[0];
   char        szStore[4096];
   int         iMax;
   int         iLength = iAlignment-1;
   int         iLoop = 0;

   if ( strlen( pszText ) < 10 )
   {
      /* You may want to add your own error message routine in here */
      /*      strcpy( s_szResult, "BUG: Justified string cannot be less than 10 characters long." );
        return( &s_szResult[0] );
        */
      return( pszText );
   }

   /* Discard all leading spaces */
   while ( *pszText == ' ' ) pszText++;

   /* Store the character */
   szStore[iLoop++] = *pszText++;

   if ( szStore[iLoop-1] >= 'a' && szStore[iLoop-1] <= 'z' )
   {
      /* Capitalize the first character if it's a letter */
      szStore[iLoop-1] &= ~32;
   }

   /* The first loop goes through the string, copying it into szStore.  The
    * string is formatted to remove all newlines, capitalise new sentences,
    * remove excess white spaces and ensure that full stops, commas and
    * exclaimation marks are all followed by two white spaces.
    */
   while ( *pszText )
   {
      switch ( *pszText )
      {
         default:
            /* Store the character */
            szStore[iLoop++] = *pszText++;
            break;
         case ' ':
            /* There shall only be one space between non-space characters */
            if ( *(pszText+1) != ' ' )
            {
               /* Store the character */
               szStore[iLoop++] = *pszText;
            }
            pszText++;
            break;
         case '.': case '?': case '!':
            /* Store the character */
            szStore[iLoop++] = *pszText++;
            switch ( *pszText )
            {
               default:
                  /* Sentence terminators shall be followed by two spaces */
                  szStore[iLoop++] = ' ';
                  szStore[iLoop++] = ' ';
                  /* Discard all leading spaces */
                  while ( *pszText == ' ' ||
                          *pszText == '\n' ||
                          *pszText == '\r' )
                      pszText++;
                  /* Store the character */
                  szStore[iLoop++] = *pszText++;
                  if ( szStore[iLoop-1] >= 'a' && szStore[iLoop-1] <= 'z' )
                  {
                     /* Capitalize if it's a letter */
                     szStore[iLoop-1] &= ~32;
                  }
                  break;
               case '.': case '?': case '!':
                  /* Multiple terminators shall not be separated by spaces */
                  break;
            }
            break;
         case ',':
            /* Store the character */
            szStore[iLoop++] = *pszText++;
            /* Discard all leading spaces */
            while ( *pszText == ' ' ) pszText++;
            /* Commas shall be followed by one space */
            szStore[iLoop++] = ' ';
            break;
         case '$':
            /* Store the character */
            szStore[iLoop++] = *pszText++;
            /* Discard all leading spaces */
            while ( *pszText == ' ' ) pszText++;
            break;
         case '\n':
            szStore[iLoop++] = ' ';
         case '\r':
            /* Discard newlines and returns */
            pszText++;
            break;
      }
   }

   /* Terminate the string */
   szStore[iLoop] = '\0';

   /* Initialise iMax to the size of szStore */
   iMax = strlen( szStore );

   /* The second loop goes through the string, inserting newlines at every
    * appropriate point.
    */
   while ( iLength < iMax )
   {
      /* Go backwards through the current line searching for a space */
      while ( szStore[iLength] != ' ' && iLength > 1 )
      {
         iLength--;
      }

      if ( szStore[iLength] == ' ' )
      {
         /* If a space is found, replace it with a newline */
         szStore[iLength] = '\n';
         iLength += iAlignment;
      }
      else
      {
         /* If no space is found, drop out of the loop */
         break;
      }
   }

   /* Add spaces to the front of the line as appropriate */
   switch ( eJustify )
   {
      case justify_left:
         /* Do nothing */
         break;
      case justify_right:
         AddSpaces( &pszResult, 80-iAlignment );
         break;
      case justify_centre:
         AddSpaces( &pszResult, (80-iAlignment)/2 );
         break;
   }

   /* Reset the counter */
   iLoop = 0;

   /* The third and final loop goes through the string, making sure that there
    * is a \r (return to beginning of line) following every newline, with no
    * white spaces at the beginning of a particular line of text.
    */
   while ( iLoop < iMax )
   {
      /* Store the character */
      *pszResult++ = szStore[iLoop];
      switch ( szStore[iLoop] )
      {
         default:
            break;
         case '\n':
            /* Insert a return after the newline and remove any leading spaces */
            *pszResult++ = '\r';
            while ( szStore[iLoop+1] == ' ' ) iLoop++;
            /* Add spaces to the front of the line as appropriate */
            switch ( eJustify )
            {
               case justify_left:
                  /* Do nothing */
                  break;
               case justify_right:
                  AddSpaces( &pszResult, 80-iAlignment );
                  break;
               case justify_centre:
                  AddSpaces( &pszResult, (80-iAlignment)/2 );
                  break;
            }
            break;
      }
      iLoop++;
   }

   /* Terminate the string */
   *pszResult++ = '\0';

   return( &s_szResult[0] );
}

/******************************************************************************
 Local operations.
 ******************************************************************************/

/* Function: AddSpaces
 *
 * This function is used to add spaces to the front of a line of text.  It
 * is used for right and centre justification.
 *
 * The function takes two parameters, as follows:
 *
 * ppszText: Pointer to the pointer to the string to have the spaces added to.
 * iNumber:  The number of spaces to be added to the front of the line.
 *
 * There is no return value.
 */
static void AddSpaces( char **ppszText, int iNumber )
{
   int iLoop;

   for ( iLoop = 0; iLoop < iNumber; iLoop++ )
   {
      *(*ppszText)++ = ' ';
   }
}