/***************************************************************************
* File: string.c *
* Usage: various functions for new NOTE system *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
* *
* Much of this code came from CircleMUD. *
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. *
* *
* Revised for Merc 2.1 by Jason Dinkel. *
* Revised for Envy 1.0 by Jason Dinkel. *
***************************************************************************/
/***************************************************************************
* God Wars Mud originally written by KaVir aka Richard Woolcock. *
* Changes done to the code done by Sage aka Walter Howard, this mud is *
* for the public, however if you run this code it means you agree *
* to the license.low, license.gw, and license.merc have fun. :) *
***************************************************************************/
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
/*
* Colour codes.
*/
int is_colour args( ( char code ) );
/*
* Special codes.
*/
#define C_UDL "\x1B[4m" /* Underline ANSI code */
#define C_NRM CLEAR
#define MAX_COLOURS 17
const char *COLOURLIST[] = {
C_NRM,
C_RED, C_GREEN, C_YELLOW, C_BLUE, C_MAGENTA, C_CYAN, C_WHITE, C_D_GREY,
C_B_RED, C_B_GREEN, C_B_YELLOW, C_B_BLUE, C_B_MAGENTA, C_B_CYAN,
C_B_WHITE,
C_UDL
};
void string_edit( CHAR_DATA *ch, char **pString )
{
send_to_char( " --<[====]>--<[ String Editor ]>--<[====]>--\n\r"
" [ Type .h on a new line for help. ]\n\r"
" [ @ on a blank line to finish. ]\n\r"
" --<[===================================]>--\n\r", ch );
if ( *pString == NULL )
{
*pString = str_dup( "" );
}
else
{
**pString = '\0';
}
ch->desc->pString = pString;
return;
}
void string_append( CHAR_DATA *ch, char **pString )
{
send_to_char( " --<[====]>--<[ String Editor ]>--<[====]>--\n\r"
" [ Type .h on a new line for help. ]\n\r"
" [ @ on a blank line to finish. ]\n\r"
" --<[===================================]>--\n\r", ch );
if ( *pString == NULL )
{
*pString = str_dup( "" );
}
send_to_char( *pString, ch );
if ( *(*pString + strlen( *pString ) - 1) != '\r' )
send_to_char( "\n\r", ch );
ch->desc->pString = pString;
return;
}
char * string_replace( char * orig, char * old, char * new )
{
char xbuf[MAX_STRING_LENGTH];
int i;
xbuf[0] = '\0';
strcpy( xbuf, orig );
if ( strstr( orig, old ) != NULL )
{
i = strlen( orig ) - strlen( strstr( orig, old ) );
xbuf[i] = '\0';
strcat( xbuf, new );
strcat( xbuf, &orig[i+strlen( old )] );
free_string( orig );
}
return str_dup( xbuf );
}
char *string_replace2 (CHAR_DATA * ch, char *orig, int line, char *new)
{
char *rdesc;
char xbuf[MAX_STRING_LENGTH];
int current_line = 1;
int i;
bool fReplaced = FALSE;
xbuf[0] = '\0';
strcpy (xbuf, orig);
i = 0;
for (rdesc = orig; *rdesc; rdesc++)
{
if (current_line == line && !fReplaced)
{
xbuf[i] = '\0';
if (*new)
strcat (xbuf, new);
strcat (xbuf, "\n\r");
fReplaced = TRUE;
}
if (current_line == line + 1)
{
strcat (xbuf, &orig[i]);
free_string (orig);
send_to_char ("Line replaced.\n\r", ch);
return str_dup (xbuf);
}
i++;
if (*rdesc == '\r')
current_line++;
}
if (current_line - 1 != line)
{
send_to_char ("That line does not exist.\n\r", ch);
return str_dup (xbuf);
}
free_string (orig);
send_to_char ("Line replaced.\n\r", ch);
return str_dup (xbuf);
}
/*****************************************************************************
Name: string_insertline
Purpose: Inserts a line, blank or containing text.
Called by: string_add(string.c) (aedit_builder)olc_act.c.
****************************************************************************/
char *string_insertline (CHAR_DATA * ch, char *orig, int line, char *addstring)
{
char *rdesc;
char xbuf[MAX_STRING_LENGTH];
int current_line = 1;
int i;
xbuf[0] = '\0';
strcpy (xbuf, orig);
i = 0;
for (rdesc = orig; *rdesc; rdesc++)
{
if (current_line == line)
break;
i++;
if (*rdesc == '\r')
current_line++;
}
if (!*rdesc)
{
send_to_char ("That line does not exist.\n\r", ch);
return str_dup (xbuf);
}
xbuf[i] = '\0';
if (*addstring)
strcat (xbuf, addstring);
strcat (xbuf, "\n\r");
strcat (xbuf, &orig[i]);
free_string (orig);
send_to_char ("Line inserted.\n\r", ch);
return str_dup (xbuf);
}
/*****************************************************************************
Name: string_deleteline
Purpose: Deletes a specified line of the string.
Called by: string_add(string.c) (aedit_builder)olc_act.c.
****************************************************************************/
char *string_deleteline (char *orig, int line)
{
char *rdesc;
char xbuf[MAX_STRING_LENGTH];
int current_line = 1;
int i = 0;
xbuf[0] = '\0';
for (rdesc = orig; *rdesc; rdesc++)
{
if (current_line != line)
{
xbuf[i] = *rdesc;
i++;
}
if (*rdesc == '\r')
current_line++;
}
free_string (orig);
xbuf[i] = 0;
return str_dup (xbuf);
}
/*****************************************************************************
Name: string_add
Purpose: Interpreter for string editing.
Called by: game_loop_xxxx(comm.c).
****************************************************************************/
void string_add (CHAR_DATA * ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
/*
* Thanks to James Seng
*/
smash_tilde (argument);
if (*argument == '.')
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
argument = one_argument (argument, arg1);
if (!str_cmp (arg1, "./"))
{
interpret(ch, argument);
send_to_char ("Command performed.\n\r", ch);
return;
}
argument = first_arg (argument, arg2, FALSE);
argument = first_arg (argument, arg3, FALSE);
if (!str_cmp (arg1, ".c"))
{
send_to_char ("String cleared.\n\r", ch);
**ch->desc->pString = '\0';
return;
}
if (!str_cmp (arg1, ".s"))
{
char *rdesc;
int i = 1;
ch_printf (ch, "`5%2d`` ", i);
for (rdesc = *ch->desc->pString; *rdesc; rdesc++)
{
if (*rdesc != '{') /* ` */
ch_printf (ch, "%c", rdesc[0]);
else
{
if (rdesc[1] == 'Z')
send_to_char ("{Z}", ch);
else
ch_printf (ch, "%c%c",
rdesc[0],
rdesc[1]);
rdesc++;
}
if (*rdesc == '\r' && *(rdesc + 1))
{
i++;
ch_printf (ch, "`5%2d`` ", i);
}
}
/* send_to_char( *ch->desc->pString, ch ); */
return;
}
#ifdef ISPELL
if (!str_cmp (arg1, ".sp"))
{
spell_check (ch, *ch->desc->pString);
return;
}
#endif
if (!str_cmp (arg1, ".r"))
{
if (arg2[0] == '\0')
{
send_to_char (
"usage: .r \"old string\" \"new string\"\n\r", ch);
return;
}
smash_tilde (arg3); /* Just to be sure -- Hugin */
*ch->desc->pString =
string_replace (*ch->desc->pString, arg2, arg3);
sprintf (buf, "'%s' replaced with '%s'.\n\r", arg2, arg3);
send_to_char (buf, ch);
return;
}
if (!str_cmp (arg1, ".rl"))
{
if (arg2[0] == '\0' || !is_number (arg2))
{
send_to_char (
"usage: .rl <line> <text>\n\r", ch);
return;
}
smash_tilde (arg3); /* Just to be sure -- Hugin */
*ch->desc->pString =
string_replace2 (ch, *ch->desc->pString, atoi (arg2), arg3);
return;
}
if (!str_cmp (arg1, ".i"))
{
if (arg2[0] == '\0' || !is_number (arg2))
{
send_to_char (
"usage: .i <line> {text}\n\r", ch);
return;
}
smash_tilde (arg3); /* Just to be sure -- Hugin */
*ch->desc->pString =
string_insertline (ch, *ch->desc->pString, atoi (arg2), arg3);
return;
}
if (!str_cmp (arg1, ".d"))
{
if (arg2[0] == '\0' || !is_number (arg2))
{
send_to_char (
"usage: .d <line>\n\r", ch);
return;
}
*ch->desc->pString =
string_deleteline (*ch->desc->pString, atoi (arg2));
sprintf (buf, "Line %d deleted.\n\r", atoi (arg2));
send_to_char (buf, ch);
return;
}
if (!str_cmp (arg1, ".f"))
{
*ch->desc->pString = format_string (*ch->desc->pString);
send_to_char ("String formatted.\n\r", ch);
return;
}
if (!str_cmp (arg1, ".h"))
{
send_to_char ("Sedit help (commands on blank line): \n\r", ch);
send_to_char (".r 'old' 'new' - replace a substring \n\r", ch);
send_to_char (" (requires '', \"\") \n\r", ch);
send_to_char (".rl <line> <text> - replaces a line \n\r", ch);
send_to_char (".h - get help (this info)\n\r", ch);
send_to_char (".s - show string so far \n\r", ch);
#ifdef ISPELL
send_to_char (".sp - spell check string \n\r", ch);
#endif
send_to_char (".f - (word wrap) string \n\r", ch);
send_to_char (".c - clear string so far \n\r", ch);
send_to_char (".d <line> - deletes a line \n\r", ch);
send_to_char (".i <line> {{text} - inserts a line \n\r", ch);
send_to_char ("./ <command> - do a regular command\n\r", ch);
send_to_char ("@ - end string \n\r", ch);
return;
}
send_to_char ("SEdit: Invalid dot command.\n\r", ch);
return;
}
if (*argument == '~' || *argument == '@')
{
/* if (ch->desc->editor == ED_NOTE_AJUST)
write_all_notes (); */
ch->desc->pString = NULL;
ch->desc->editor = 0;
return;
}
strcpy (buf, *ch->desc->pString);
/*
* Truncate strings to MAX_STRING_LENGTH.
* --------------------------------------
*/
if (strlen (buf) + strlen (argument) >= (MAX_STRING_LENGTH - 4))
{
send_to_char ("String too long, last line skipped.\n\r", ch);
/* Force character out of editing mode. */
ch->desc->pString = NULL;
return;
}
/*
* Ensure no tilde's inside string.
* --------------------------------
*/
smash_tilde (argument);
strcat (buf, argument);
strcat (buf, "\n\r");
free_string (*ch->desc->pString);
*ch->desc->pString = str_dup (buf);
return;
}
/*
* Thanks to Kalgen for the new procedure (no more bug!)
* Original wordwrap() written by Surreality.
*/
char *format_string( char *oldstring /*, bool fSpace */)
{
char xbuf[MAX_STRING_LENGTH];
char xbuf2[MAX_STRING_LENGTH];
char *rdesc;
int i=0;
bool cap=TRUE;
xbuf[0]=xbuf2[0]=0;
i=0;
for (rdesc = oldstring; *rdesc; rdesc++)
{
if (*rdesc=='\n')
{
if (xbuf[i-1] != ' ')
{
xbuf[i]=' ';
i++;
}
}
else if (*rdesc=='\r') ;
else if (*rdesc==' ')
{
if (xbuf[i-1] != ' ')
{
xbuf[i]=' ';
i++;
}
}
else if (*rdesc==')')
{
if (xbuf[i-1]==' ' && xbuf[i-2]==' ' &&
(xbuf[i-3]=='.' || xbuf[i-3]=='?' || xbuf[i-3]=='!'))
{
xbuf[i-2]=*rdesc;
xbuf[i-1]=' ';
xbuf[i]=' ';
i++;
}
else
{
xbuf[i]=*rdesc;
i++;
}
}
else if (*rdesc=='.' || *rdesc=='?' || *rdesc=='!') {
if (xbuf[i-1]==' ' && xbuf[i-2]==' ' &&
(xbuf[i-3]=='.' || xbuf[i-3]=='?' || xbuf[i-3]=='!')) {
xbuf[i-2]=*rdesc;
if (*(rdesc+1) != '\"')
{
xbuf[i-1]=' ';
xbuf[i]=' ';
i++;
}
else
{
xbuf[i-1]='\"';
xbuf[i]=' ';
xbuf[i+1]=' ';
i+=2;
rdesc++;
}
}
else
{
xbuf[i]=*rdesc;
if (*(rdesc+1) != '\"')
{
xbuf[i+1]=' ';
xbuf[i+2]=' ';
i += 3;
}
else
{
xbuf[i+1]='\"';
xbuf[i+2]=' ';
xbuf[i+3]=' ';
i += 4;
rdesc++;
}
}
cap = TRUE;
}
else
{
xbuf[i]=*rdesc;
if ( cap )
{
cap = FALSE;
xbuf[i] = UPPER( xbuf[i] );
}
i++;
}
}
xbuf[i]=0;
strcpy(xbuf2,xbuf);
rdesc=xbuf2;
xbuf[0]=0;
for ( ; ; )
{
for (i=0; i<77; i++)
{
if (!*(rdesc+i)) break;
}
if (i<77)
{
break;
}
for (i=(xbuf[0]?76:73) ; i ; i--)
{
if (*(rdesc+i)==' ') break;
}
if (i)
{
*(rdesc+i)=0;
strcat(xbuf,rdesc);
strcat(xbuf,"\n\r");
rdesc += i+1;
while (*rdesc == ' ') rdesc++;
}
else
{
bug ("No spaces", 0);
*(rdesc+75)=0;
strcat(xbuf,rdesc);
strcat(xbuf,"-\n\r");
rdesc += 76;
}
}
while (*(rdesc+i) && (*(rdesc+i)==' '||
*(rdesc+i)=='\n'||
*(rdesc+i)=='\r'))
i--;
*(rdesc+i+1)=0;
strcat(xbuf,rdesc);
if (xbuf[strlen(xbuf)-2] != '\n')
strcat(xbuf,"\n\r");
free_string(oldstring);
return(str_dup(xbuf));
}
/*
* Pick off one argument from a string and return the rest.
* Understands quotes, parenthesis (barring ) ('s) and percentages.
*/
char *first_arg( char *argument, char *arg_first, bool fCase )
{
char cEnd;
while ( *argument == ' ' )
argument++;
cEnd = ' ';
if ( *argument == '\'' || *argument == '"'
|| *argument == '%' || *argument == '(' )
{
if ( *argument == '(' )
{
cEnd = ')';
argument++;
}
else cEnd = *argument++;
}
while ( *argument != '\0' )
{
if ( *argument == cEnd )
{
argument++;
break;
}
if ( fCase ) *arg_first = LOWER(*argument);
else *arg_first = *argument;
arg_first++;
argument++;
}
*arg_first = '\0';
while ( *argument == ' ' )
argument++;
return argument;
}
char * string_unpad( char * argument )
{
char buf[MAX_STRING_LENGTH];
char *s;
s = argument;
while ( *s == ' ' )
s++;
strcpy( buf, s );
s = buf;
if ( *s != '\0' )
{
while ( *s != '\0' )
s++;
s--;
while( *s == ' ' )
s--;
s++;
*s = '\0';
}
free_string( argument );
return str_dup( buf );
}
char * string_proper( char * argument )
{
char *s;
s = argument;
while ( *s != '\0' )
{
if ( *s != ' ' )
{
*s = UPPER(*s);
while ( *s != ' ' && *s != '\0' )
s++;
}
else
{
s++;
}
}
return argument;
}
int arg_count( char *argument )
{
int total;
char *s;
total = 0;
s = argument;
while ( *s != '\0' )
{
if ( *s != ' ' )
{
total++;
while ( *s != ' ' && *s != '\0' )
s++;
}
else
{
s++;
}
}
return total;
}
char * current_date( )
{
static char buf [ 128 ];
struct tm * datetime;
datetime = localtime( ¤t_time );
strftime( buf, sizeof( buf ), "%x", datetime );
return buf;
}
/*
* This operation draws an 80 character line with a word in the centre
*/
void text_bar( CHAR_DATA *ch, char *argument, bool pager )
{
char bar_buf[MAX_INPUT_LENGTH]; /* Buffer to store text bar */
int text_length = strlen( argument ); /* Length of the text */
int word_start; /* Start of text word */
int loop; /* Loop counter */
word_start = 37 - ((text_length+1) >> 1); /* Initialise word start */
/* If the text is too big, just display it as is */
if ( text_length > 70 )
{
send_to_char(argument,ch);
send_to_char("\n\r",ch);
return;
}
sprintf( bar_buf, "-%s", capitalize(ch->name) );
/* Set the left half of the bar to spaces */
for ( loop = strlen(bar_buf); loop < word_start; loop++ )
{
bar_buf[loop] = '-';
}
/* Terminate the bar string so that strcat can be used to add the word */
bar_buf[word_start] = '\0';
strcat( bar_buf, "[ ");
strcat( bar_buf, argument );
strcat( bar_buf, " ]" );
for( loop = strlen(bar_buf)-1; loop < SCREEN_WIDTH-10; loop++ )
strcat( bar_buf, "-");
strcat( bar_buf, current_date());
strcat( bar_buf, "-" );
strcat( bar_buf, "\n\r" );
/* Display the text bar */
if( pager )
page_to_char( bar_buf, ch );
else
send_to_char( bar_buf, ch );
return;
}
/*
* Take a number like 43 and make it forty-three.
*/
char * const ones_numerals [10] =
{
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
};
char * const tens_numerals [10] =
{
"-",
"-",
"twenty",
"thirty",
"forty",
"fifty",
"sixty",
"seventy",
"eighty",
"ninety"
};
char * const meta_numerals [4] =
{
"hundred",
"thousand",
"million",
"billion"
};
char * const special_numbers [10] =
{
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen"
};
char *numberize( int n )
{
static char buf[MAX_STRING_LENGTH];
sh_int digits[3];
int t = abs(n);
buf[0] = '\0';
/*
* Special cases (10-19)
*/
if ( n >= 10 && n <= 19 )
{
sprintf( buf, "%s", special_numbers[n-10] );
return buf;
}
if ( n < 10 && n >= 0 )
{
sprintf( buf, "%s", ones_numerals[n] );
return buf;
}
/*
* Cha.
*/
if ( n >= 10000 || n < 0 )
{
sprintf( buf, "%d", n );
return buf;
}
digits[3] = t / 1000;
t -= 1000*digits[3];
digits[2] = t / 100;
t -= 100*digits[2];
digits[1] = t / 10;
t -= 10*digits[1];
digits[0] = t;
if ( digits[3] > 0 )
{
sprintf( buf, "%s%s", buf, ones_numerals[digits[3]] );
sprintf( buf, "%s thousand ", buf );
}
if ( digits[2] > 0 )
{
sprintf( buf, "%s%s", buf, ones_numerals[digits[2]] );
sprintf( buf, "%s hundred ", buf );
}
if ( digits[1] > 0 )
{
sprintf( buf, "%s%s", buf, tens_numerals[digits[1]] );
if ( digits[0] > 0 ) sprintf( buf, "%s-", buf );
}
if ( digits[0] > 0 )
{
sprintf( buf, "%s%s", buf, ones_numerals[digits[0]] );
}
if ( buf[(t = strlen(buf)-1)] == ' ' ) buf[t] = '\0';
if ( buf[(t = strlen(buf)-1)] == ' ' ) buf[t] = '\0';
return buf;
}
char *smash_article( char *text )
{
char *arg;
char buf[MAX_STRING_LENGTH];
static char buf2[MAX_STRING_LENGTH];
one_argument( text, buf );
if ( !str_cmp( buf, "the" ) ||
!str_cmp( buf, "an" ) ||
!str_cmp( buf, "a" ) )
{
arg = one_argument( text, buf );
sprintf( buf2, "%s", arg );
}
else strcpy( buf2, text );
return buf2;
}
/*
* Sees if last char is 's' and returns 'is' or 'are' pending.
*/
char * is_are( char *text )
{
while ( *text != '\0' )
{
text++;
}
text--;
if ( LOWER(*text) == 's' && LOWER(*text-1) != 's' )
return "are";
else return "is";
}
char *pluralize( char *argument )
{
static char buf[MAX_STRING_LENGTH];
char *v;
sprintf( buf, "%s", smash_article(argument) );
v = strstr( buf, " of " );
if ( v == NULL )
{
if ( LOWER(buf[strlen(buf)-1]) == 'y' )
{
buf[strlen(buf)-1] = 'i';
strcat( buf, "es" );
}
else
if ( LOWER(buf[strlen(buf)-1]) == 'f'
&& !(LOWER(buf[strlen(buf)-2]) == 'i'
&& LOWER(buf[strlen(buf)-3]) == 'o') )
{
buf[strlen(buf)-1] = 'v';
strcat( buf, "es" );
}
else
if ( LOWER(buf[strlen(buf)-1]) == 'h' )
strcat( buf, "es" );
else
if ( LOWER(buf[strlen(buf)-1]) == 's' )
{
if ( LOWER(buf[strlen(buf)-2]) == 'u'
&& !IS_VOWEL(LOWER(buf[strlen(buf)-3])) )
{
buf[strlen(buf)-2] = 'i';
buf[strlen(buf)-1] = '\0';
}
else
strcat( buf, "es" );
}
else
strcat( buf, "s" );
}
else
{
char xbuf[MAX_STRING_LENGTH];
sprintf( xbuf, "%s", v );
buf[strlen(buf)-strlen(v)] = '\0';
if ( LOWER(buf[strlen(buf)-1]) == 'y' )
{
buf[strlen(buf)-1] = 'i';
strcat( buf, "es" );
}
else
if ( LOWER(buf[strlen(buf)-1]) == 'f'
&& !(LOWER(buf[strlen(buf)-2]) == 'i'
&& LOWER(buf[strlen(buf)-3]) == 'o') )
{
buf[strlen(buf)-1] = 'v';
strcat( buf, "es" );
}
else
if ( LOWER(buf[strlen(buf)-1]) == 'h' )
strcat( buf, "es" );
else
if ( LOWER(buf[strlen(buf)-1]) == 's' )
{
if ( LOWER(buf[strlen(buf)-2]) == 'u'
&& !IS_VOWEL(LOWER(buf[strlen(buf)-3])) )
{
buf[strlen(buf)-2] = 'i';
buf[strlen(buf)-1] = '\0';
}
else
strcat( buf, "es" );
}
else
strcat( buf, "s" );
strcat( buf, xbuf );
}
return buf;
}
char *trunc_fit( char *argument, int length )
{
static char buf[MAX_STRING_LENGTH];
int x;
if ( argument == NULL )
return argument;
for ( x = 0; (x < length) && (*argument != '\0'); x++ )
{
buf[x] = *argument;
argument++;
};
buf[x] = '\0';
return buf;
};
int is_colour( char code )
{
switch( code )
{
case 'x':
return 0; break;
case 'r':
return 1; break; /* Red */
case 'g':
return 2; break; /* Green */
case 'y':
return 3; break; /* Yellow */
case 'b':
return 4; break; /* Blue */
case 'm':
return 5; break; /* Magenta */
case 'c':
return 6; break; /* Cyan */
case 'n':
return 7; break; /* White */
case 'D':
return 8; break; /* Black */
case 'R':
return 9; break; /* Bold red */
case 'G':
return 10; break; /* Bold green */
case 'Y':
return 11; break; /* Bold yellow */
case 'B':
return 12; break; /* Bold blue */
case 'M':
return 13; break; /* Bold magenta */
case 'C':
return 14; break; /* Bold cyan */
case 'W':
return 15; break; /* Bold white */
}
return 0;
}
/*
* Length of the string as seen minus colour codes.
*/
int colour_strlen( const char *str )
{
int j;
j = 0;
while( *str != '\0' )
{
if( *str != '{' )
{
str++;
j++;
continue;
}
str++;
}
return j;
}
/*
* Makes the string the correct length for format with colour.
* Note: isprint checks for any printable character, including
* a space.
*/
char *colour_strpad( char *outstr, const char *str, const int length )
{
int i, j;
j = 0;
for( i = 0; str[i] && j < length; i++ )
{
outstr[i] = str[i];
if( str[i] == '{' )
{
if( !isprint( COLOURLIST[is_colour( str[i + 1] )][0] ) )
j--;
}
else
j++;
}
outstr[i++] = '{';
outstr[i++] = 'x';
while( j < length )
{
outstr[i++] = ' ';
j++;
}
outstr[i] = '\0';
return outstr;
}
/*
* Centres the string on a certain length line.
*/
char *colour_strcentre( char *outstr, const char *str, const int length )
{
char *p = outstr;
int pad, i;
pad = length - colour_strlen( str );
if( pad <= 0 )
return colour_strpad( outstr, str, length );
for( i = 0; i < pad / 2; ++i )
*p++ = ' ';
for( i = 0; str[i] != '\0'; ++i )
*p++ = str[i];
for( i = pad / 2; i < pad; ++i )
*p++ = ' ';
*p = '\0';
return outstr;
}
/*
* Limits the length of a colourised string.
* Very similar to the above, except destructive to the string.
*/
void str_limit( char *str, const int length )
{
int i, j;
j = 0;
for( i = 0; str[i] && j < length; i++ )
{
if( str[i] == '{' )
{
if( !isprint( COLOURLIST[is_colour( str[i + 1] )][0] ) )
j--;
}
else
j++;
}
str[i++] = '{';
str[i++] = 'x';
str[i] = '\0';
}
/*
* Remove as much of the colour code as possible.
*/
char *kill_colour( char *outstr, const char *str )
{
int i, j;
j = 0;
for( i = 0; str[i]; i++ )
{
if( str[i] == '{' )
{
if( isprint( COLOURLIST[is_colour( str[++i] )][0] ) )
outstr[j++] = COLOURLIST[is_colour( str[i] )][0];
}
else
outstr[j++] = str[i];
}
outstr[j] = '\0';
return outstr;
}