/******************************************************************************
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)++ = ' ';
}
}