/*
* New editor code
* Author: Cronel (cronel_kal@hotmail.com)
* of FrozenMUD (empire.digiunix.net 4000)
*
* Permission to use and distribute this code is granted provided
* this header is retained and unaltered, and the distribution
* package contains all the original files unmodified.
* If you modify this code and use/distribute modified versions
* you must give credit to the original author(s).
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "mud.h"
/****************************************************************************
* Data types and other definitions
*/
typedef struct editor_line EDITOR_LINE;
#define CHAR_BLOCK (80)
#define BLOCK_ROUNDUP( size ) (((size)+CHAR_BLOCK-1) / CHAR_BLOCK * CHAR_BLOCK)
#define RESIZE_IF_NEEDED( buf, buf_size, buf_used, added_use ) \
if( (buf_used) + (added_use) >= (buf_size) ) \
{ \
sh_int added_size; \
added_size = BLOCK_ROUNDUP( added_use ); \
if( added_size == 0 ) \
added_size = CHAR_BLOCK; \
RECREATE( (buf), char, buf_size + added_size ); \
(buf_size) += added_size; \
}
struct editor_line
{
char *line; /* line text */
sh_int line_size; /* size allocated in "line" */
sh_int line_used; /* bytes used of "line" */
EDITOR_LINE *next;
};
struct editor_data
{
EDITOR_LINE *first_line; /* list of lines */
sh_int line_count; /* number of lines allocated */
EDITOR_LINE *on_line; /* pointer to the line being edited */
int text_size; /* total size of text (not counting
* newlines). */
int max_size; /* max size in chars of string being
* edited (counting newlines) */
char *desc; /* buffer description */
};
/* "max_size" is the maximum size of the final text converted to string */
/* "text_size" is equal to the strlen of all lines added up; the actual
* total length when converted to string is equal to this number plus
* line_count * 2, because of the trailing "\n\r" that has to be added
* to each line (of course, plus 1 because of the final \0).
* Thus, if(total_size + line_count * 2 +1) > max_size, the buffer cant
* hold more data.
*/
/* Hence, this define: */
#define TOTAL_BUFFER_SIZE( edd ) (edd->text_size + edd->line_count * 2 +1 )
/****************************************************************************
* Function declarations
*/
/* funcs to manipulate editor datas */
EDITOR_LINE *make_new_line( char *str );
void discard_editdata( EDITOR_DATA * edd );
EDITOR_DATA *clone_editdata( EDITOR_DATA * edd );
EDITOR_DATA *str_to_editdata( char *str, sh_int max_size );
char *editdata_to_str( EDITOR_DATA * edd );
/* simple functions to set a description for what's currently
* being edited */
void set_editor_desc( CHAR_DATA * ch, char *new_desc );
void editor_desc_printf( CHAR_DATA * ch, char *desc_fmt, ... );
/* the main editor functions visible to the rest of the code */
void start_editing_nolimit( CHAR_DATA * ch, char *old_text, sh_int max_total );
char *copy_buffer( CHAR_DATA * ch );
void stop_editing( CHAR_DATA * ch );
/* main editing function */
void edit_buffer( CHAR_DATA * ch, char *argument );
/* misc functions */
char *finer_one_argument( char *argument, char *arg_first );
char *text_replace( char *src, char *word_src, char *word_dst, sh_int * pnew_size, sh_int * prepl_count );
/* editor sub functions */
void editor_print_info( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
void editor_help( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
void editor_clear_buf( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
void editor_search_and_replace( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
void editor_insert_line( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
void editor_delete_line( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
void editor_goto_line( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
void editor_list( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
void editor_abort( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
void editor_escaped_cmd( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
void editor_save( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
void editor_format( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument );
/****************************************************************************
* Edit_data manipulation functions
*/
EDITOR_LINE *make_new_line( char *str )
{
EDITOR_LINE *new_line;
sh_int size;
size = strlen( str );
size = BLOCK_ROUNDUP( size );
if( size == 0 )
size = CHAR_BLOCK;
CREATE( new_line, EDITOR_LINE, 1 );
CREATE( new_line->line, char, size );
new_line->line_size = size;
new_line->line_used = strlen( str );
strcpy( new_line->line, str );
return new_line;
}
void discard_editdata( EDITOR_DATA * edd )
{
EDITOR_LINE *eline, *elnext;
eline = edd->first_line;
while( eline )
{
elnext = eline->next;
DISPOSE( eline->line );
DISPOSE( eline );
eline = elnext;
}
if( edd->desc )
STRFREE( edd->desc );
DISPOSE( edd );
}
EDITOR_DATA *clone_editdata( EDITOR_DATA * edd )
{
EDITOR_DATA *new_edd;
EDITOR_LINE *new_line, *eline, root_line;
CREATE( new_edd, EDITOR_DATA, 1 );
new_line = &root_line;
for( eline = edd->first_line; eline; eline = eline->next )
{
new_line->next = make_new_line( eline->line );
if( edd->on_line == eline )
new_edd->on_line = new_line->next;
new_line = new_line->next;
}
new_edd->max_size = edd->max_size;
new_edd->text_size = edd->text_size;
new_edd->line_count = edd->line_count;
new_edd->first_line = root_line.next;
new_edd->desc = STRALLOC( edd->desc );
return new_edd;
}
EDITOR_DATA *str_to_editdata( char *str, sh_int max_size )
{
char *p;
EDITOR_DATA *edd;
EDITOR_LINE *eline;
sh_int i;
sh_int tsize, line_count;
CREATE( edd, EDITOR_DATA, 1 );
eline = make_new_line( "" );
edd->first_line = eline;
i = 0;
tsize = 0;
line_count = 1;
p = str;
while( *p )
{
if( tsize + line_count * 2 + 1 >= max_size )
break;
if( *p == '\r' )
;
else if( *p == '\n' )
{
eline->line[i] = '\0';
eline->next = make_new_line( "" );
eline = eline->next;
line_count++;
i = 0;
}
else
{
eline->line[i] = *p;
eline->line_used++;
tsize++;
i++;
RESIZE_IF_NEEDED( eline->line, eline->line_size, eline->line_used, 1 );
}
p++;
}
if( eline->line[0] != '\0' )
{
eline->line[i] = '\0';
eline->next = make_new_line( "" );
line_count++;
eline = eline->next;
}
edd->line_count = line_count;
edd->on_line = eline;
edd->max_size = max_size;
edd->text_size = tsize;
edd->desc = STRALLOC( "" );
return edd;
}
char *editdata_to_str( EDITOR_DATA * edd )
{
EDITOR_LINE *eline;
char *buf, *src, *tmp;
sh_int size, used, i;
CREATE( buf, char, MAX_STRING_LENGTH );
size = MAX_STRING_LENGTH;
used = 0;
buf[0] = '\0';
eline = edd->first_line;
i = 0;
while( eline )
{
/*
* ignore the last empty line
*/
if( eline->next == NULL && eline->line[0] == '\0' )
break;
src = eline->line;
while( *src )
{
buf[i++] = *src++;
used++;
if( used >= size - 3 )
{
RECREATE( buf, char, size + MAX_STRING_LENGTH );
size += MAX_STRING_LENGTH;
}
}
buf[i++] = '\n';
buf[i++] = '\r';
used += 2;
eline = eline->next;
}
buf[i++] = '\0';
used++;
tmp = STRALLOC( buf );
DISPOSE( buf );
smush_tilde( tmp );
return tmp;
}
/****************************************************************************
* Main editor functions
*/
void set_editor_desc( CHAR_DATA * ch, char *new_desc )
{
if( !ch || !ch->editor )
return;
if( ch->editor->desc )
STRFREE( ch->editor->desc );
ch->editor->desc = STRALLOC( new_desc );
}
void editor_desc_printf( CHAR_DATA * ch, char *desc_fmt, ... )
{
char buf[MAX_STRING_LENGTH * 2]; /* umpf.. */
va_list args;
va_start( args, desc_fmt );
vsprintf( buf, desc_fmt, args );
va_end( args );
set_editor_desc( ch, buf );
}
void start_editing_nolimit( CHAR_DATA * ch, char *old_text, sh_int max_total )
{
if( !ch->desc )
{
bug( "Fatal: start_editing: no desc", 0 );
return;
}
if( ch->substate == SUB_RESTRICTED )
bug( "NOT GOOD: start_editing: ch->substate == SUB_RESTRICTED", 0 );
set_char_color( AT_GREEN, ch );
send_to_char( "Begin entering your text now (/? = help /s = save /c = clear /l = list)\n\r", ch );
send_to_char( "-----------------------------------------------------------------------\n\r", ch );
if( ch->editor )
stop_editing( ch );
ch->editor = str_to_editdata( old_text, max_total );
ch->editor->desc = STRALLOC( "Unknown buffer" );
ch->desc->connected = CON_EDITING;
send_to_char( "> ", ch );
}
char *copy_buffer( CHAR_DATA * ch )
{
char *buf;
if( !ch )
{
bug( "copy_buffer: null ch", 0 );
return STRALLOC( "" );
}
if( !ch->editor )
{
bug( "copy_buffer: null editor", 0 );
return STRALLOC( "" );
}
buf = editdata_to_str( ch->editor );
return buf;
}
void stop_editing( CHAR_DATA * ch )
{
set_char_color( AT_PLAIN, ch );
discard_editdata( ch->editor );
ch->editor = NULL;
send_to_char( "Done.\n\r", ch );
ch->dest_buf = NULL;
ch->spare_ptr = NULL;
ch->substate = SUB_NONE;
if( !ch->desc )
{
bug( "Fatal: stop_editing: no desc", 0 );
return;
}
ch->desc->connected = CON_PLAYING;
}
void edit_buffer( CHAR_DATA * ch, char *argument )
{
DESCRIPTOR_DATA *d;
EDITOR_DATA *edd;
EDITOR_LINE *newline;
char cmd[MAX_INPUT_LENGTH];
sh_int linelen;
bool cont_line;
char *p;
d = ch->desc;
if( d == NULL )
{
send_to_char( "You have no descriptor.\n\r", ch );
return;
}
if( d->connected != CON_EDITING )
{
send_to_char( "You can't do that!\n\r", ch );
bug( "Edit_buffer: d->connected != CON_EDITING", 0 );
return;
}
if( ch->substate <= SUB_PAUSE )
{
send_to_char( "You can't do that!\n\r", ch );
/*
* bug( "Edit_buffer: illegal ch->substate (%d)", ch->substate );
*/
d->connected = CON_PLAYING;
return;
}
if( !ch->editor )
{
send_to_char( "You can't do that!\n\r", ch );
bug( "Edit_buffer: null editor", 0 );
d->connected = CON_PLAYING;
return;
}
edd = ch->editor;
if( argument[0] == '/' || argument[0] == '\\' )
{
argument = one_argument( argument, cmd );
if( !str_cmp( cmd + 1, "?" ) )
editor_help( ch, edd, argument );
else if( !str_cmp( cmd + 1, "c" ) )
editor_clear_buf( ch, edd, argument );
else if( !str_cmp( cmd + 1, "r" ) )
editor_search_and_replace( ch, edd, argument );
else if( !str_cmp( cmd + 1, "i" ) )
editor_insert_line( ch, edd, argument );
else if( !str_cmp( cmd + 1, "d" ) )
editor_delete_line( ch, edd, argument );
else if( !str_cmp( cmd + 1, "g" ) )
editor_goto_line( ch, edd, argument );
else if( !str_cmp( cmd + 1, "l" ) )
editor_list( ch, edd, argument );
else if( !str_cmp( cmd + 1, "a" ) )
editor_abort( ch, edd, argument );
else if( !str_cmp( cmd + 1, "s" ) )
editor_save( ch, edd, argument );
else if( !str_cmp( cmd + 1, "!" ) )
editor_escaped_cmd( ch, edd, argument );
else if( !str_cmp( cmd + 1, "p" ) )
editor_print_info( ch, edd, argument );
else if( !str_cmp( cmd + 1, "f" ) )
editor_format( ch, edd, argument );
else
send_to_char( "Uh? Type '/?' to see the list of valid editor commands.\n\r", ch );
if( str_cmp( cmd + 1, "a" ) && str_cmp( cmd + 1, "s" ) )
send_to_char( "> ", ch );
return;
}
/*
* Kludgy fix. Read_from_buffer in comm.c adds a space on
* * empty lines. Don't let this fill up usable buffer space..
*/
if( !str_cmp( argument, " " ) )
strcpy( argument, "" );
linelen = strlen( argument );
p = argument + linelen - 1;
while( p > argument && isspace( *p ) )
p--;
if( p > argument && *p == '\\' )
{
cont_line = TRUE;
*p = '\0';
}
else
cont_line = FALSE;
if( TOTAL_BUFFER_SIZE( edd ) + linelen + 2 >= edd->max_size )
{
send_to_char( "Buffer full.\n\r", ch );
editor_save( ch, edd, "" );
}
else
{
/*
* add it to the current line
*/
RESIZE_IF_NEEDED( edd->on_line->line, edd->on_line->line_size, edd->on_line->line_used, linelen + 1 );
strcat( edd->on_line->line, argument );
edd->on_line->line_used += linelen;
edd->text_size += linelen;
/*
* create a line and advance to it
*/
if( !cont_line )
{
newline = make_new_line( "" );
newline->next = edd->on_line->next;
edd->on_line->next = newline;
edd->on_line = newline;
edd->line_count++;
}
else
send_to_char( "(Continued)\n\r", ch );
send_to_char( "> ", ch );
}
}
void editor_print_info( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
sh_int i;
EDITOR_LINE *eline;
eline = edd->first_line;
i = 0;
while( eline )
{
i++;
if( eline == edd->on_line )
break;
eline = eline->next;
}
ch_printf( ch,
"Currently editing: %s\n\r"
"Total lines: %4d On line: %4d\n\r"
"Buffer size: %4d Max size: %4d\n\r",
edd->desc ? edd->desc : "(Null description)", edd->line_count, i, TOTAL_BUFFER_SIZE( edd ), edd->max_size );
}
void editor_help( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
sh_int i;
char *arg[] = { "", "l", "c", "d", "g", "i", "r", "a", "p", "!", "s", NULL };
char *editor_help[] = {
/*
* general help
*/
"Editing commands\n\r"
"---------------------------------\n\r"
"/l [range] list buffer\n\r"
"/c clear buffer\n\r"
"/d <line> delete line\n\r"
"/g <line> goto line\n\r"
"/i <line> insert line\n\r"
"/r <old> <new> global replace (temporarily disabled)\n\r"
"/a abort editing\n\r"
"/f <format> format text in buffer (temporarily disabled)\n\r"
"/p print information\n\r"
"/! <command> execute command (do not use another editing command)\n\r"
"/s save buffer\n\r" "Type /? <command> to get more information on each command.\n\r\n\r",
"/l [range]: Lists the buffer. Shows what you've written. Optionaly\n\r" " takes a range of lines as argument.\n\r",
"/c: Clears the buffer, leaving only one empty line.\n\r",
"/d <line>: Deletes a line. If you delete the line currently being\n\r"
" edited, the insertion point is moved down if possible, if not, up.\n\r",
"/g <line>: Moves the insertion point to a given line.\n\r",
"/i <line>: Inserts an empty line before the given line.\n\r",
"/r <old text> <new text>: Global search and replace text. The arguments\n\r"
" are case-sensitive. To replace a multi-word text, surround it with\n\r"
" single quotes. When inside quotes, you must escape the single quote\n\r"
" character, double quote character, and the bar: (') becomes (\\'),\n\r"
" (\") becomes (\\\") and (\\) becomes (\\\\)\n\r",
"/a: Aborts edition, terminating the edition session and throwing\n\r" " away what you've edited.\n\r",
"/p: Prints information about the current editing session.\n\r",
"/!: Escaped command. Executes the given command as if you were\n\r"
" outside the editor. This is only allowed to imms, since it can\n\r" " potentialy crash the mud.\n\r",
"/s: Saves the current buffer, terminating the edition session.\n\r",
};
for( i = 0; arg[i] != NULL; i++ )
{
if( !str_cmp( argument, arg[i] ) )
break;
}
if( arg[i] == NULL )
send_to_char( "No editor help about that.\n\r", ch );
else
send_to_char( editor_help[i], ch );
}
void editor_clear_buf( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
char *desc;
sh_int max_size;
max_size = edd->max_size;
if( edd->desc )
desc = STRALLOC( edd->desc );
else
desc = STRALLOC( "" );
discard_editdata( edd );
ch->editor = str_to_editdata( "", max_size );
ch->editor->desc = desc;
send_to_char( "Buffer cleared.\n\r", ch );
}
void editor_search_and_replace( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
char word_src[MAX_INPUT_LENGTH];
char word_dst[MAX_INPUT_LENGTH];
EDITOR_DATA *cloned_edd;
EDITOR_LINE *eline;
char *new_text;
sh_int new_size, repl_count, line_repl;
argument = finer_one_argument( argument, word_src );
argument = finer_one_argument( argument, word_dst );
if( word_src[0] == '\0' || word_dst[0] == '\0' )
{
send_to_char( "Need word to replace, and replacement.\n\r", ch );
return;
}
if( strcmp( word_src, word_dst ) == 0 )
{
send_to_char( "Done.\n\r", ch );
return;
}
/*
* Warning: the replacement of the word can result in the buffer growing
* * larger than its maximum allowed size. To control this, the buffer is
* * cloned, the replacement is applied to the clone, and if the size results
* * legal after the operation, the original buffer is discarded and the
* * clone is assigned as the current editing buffer. If the clone's size
* * results too large after the replacement, the clone is simply discarded
* * and a warning is given to the user
*/
cloned_edd = clone_editdata( edd );
eline = cloned_edd->first_line;
repl_count = 0;
while( eline )
{
new_text = text_replace( eline->line, word_src, word_dst, &new_size, &line_repl );
DISPOSE( eline->line );
eline->line = new_text;
cloned_edd->text_size -= eline->line_used;
eline->line_used = strlen( eline->line );
cloned_edd->text_size += eline->line_used;
eline->line_size = new_size;
repl_count += line_repl;
eline = eline->next;
}
if( TOTAL_BUFFER_SIZE( cloned_edd ) >= cloned_edd->max_size )
{
send_to_char( "As a result of this operation, the buffer would grow\n\r"
"larger than its maximum allowed size. Operation has been\n\r" "cancelled.\n\r", ch );
discard_editdata( cloned_edd );
}
else
{
ch_printf( ch, "Replacing all occurrences of '%s' with '%s'...\n\r", word_src, word_dst );
discard_editdata( edd );
ch->editor = cloned_edd;
ch_printf( ch, "Found and replaced %d occurrence(s).\n\r", repl_count );
}
}
void editor_insert_line( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
sh_int lineindex, num;
EDITOR_LINE *eline, *newline;
if( argument[0] == '\0' || !is_number( argument ) )
{
send_to_char( "Must supply the line number.\n\r", ch );
return;
}
lineindex = atoi( argument );
if( lineindex < 1 || lineindex > edd->line_count )
{
ch_printf( ch, "Line number is out of range (1-%d).\n\r", edd->line_count );
return;
}
newline = make_new_line( "" );
if( lineindex == 1 )
{
newline->next = edd->first_line;
edd->first_line = newline;
}
else
{
num = 1;
eline = edd->first_line;
while( num < lineindex - 1 )
{
eline = eline->next;
num++;
}
newline->next = eline->next;
eline->next = newline;
}
edd->line_count++;
ch_printf( ch, "Inserted line at %d.\n\r", lineindex );
}
void editor_delete_line( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
sh_int lineindex, num;
EDITOR_LINE *prev_line, *del_line;
if( argument[0] == '\0' || !is_number( argument ) )
{
send_to_char( "Must supply the line number.\n\r", ch );
return;
}
lineindex = atoi( argument );
if( lineindex < 1 || lineindex > edd->line_count )
{
ch_printf( ch, "Line number is out of range (1-%d).\n\r", edd->line_count );
return;
}
prev_line = NULL;
if( lineindex == 1 )
{
if( edd->line_count == 1 )
{
if( edd->first_line->line[0] != '\0' )
{
edd->first_line->line[0] = '\0';
edd->first_line->line_used = 0;
edd->text_size = 0;
send_to_char( "Deleted line 1.\n\r", ch );
}
else
send_to_char( "The buffer is empty.\n\r", ch );
return;
}
del_line = edd->first_line;
edd->first_line = del_line->next;
}
else
{
num = 1;
prev_line = edd->first_line;
while( num < lineindex - 1 )
{
prev_line = prev_line->next;
num++;
}
del_line = prev_line->next;
prev_line->next = del_line->next;
}
if( edd->on_line == del_line )
{
if( del_line->next )
edd->on_line = del_line->next;
else if( prev_line != NULL )
edd->on_line = prev_line;
else
edd->on_line = edd->first_line;
}
edd->line_count--;
DISPOSE( del_line->line );
DISPOSE( del_line );
ch_printf( ch, "Deleted line %d.\n\r", lineindex );
}
void editor_goto_line( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
sh_int lineindex, num;
if( argument[0] == '\0' || !is_number( argument ) )
{
send_to_char( "Must supply the line number.\n\r", ch );
return;
}
lineindex = atoi( argument );
if( lineindex < 1 || lineindex > edd->line_count )
{
ch_printf( ch, "Line number is out of range (1-%d).\n\r", edd->line_count );
return;
}
edd->on_line = edd->first_line;
num = 1;
while( num < lineindex )
{
edd->on_line = edd->on_line->next;
num++;
}
ch_printf( ch, "On line %d.\n\r", lineindex );
}
void editor_list( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
EDITOR_LINE *eline;
sh_int line_num;
sh_int from, to;
char arg1[MAX_INPUT_LENGTH];
argument = one_argument( argument, arg1 );
if( arg1[0] != '\0' && is_number( arg1 ) )
from = atoi( arg1 );
else
from = 1;
argument = one_argument( argument, arg1 );
if( arg1[0] != '\0' && is_number( arg1 ) )
to = atoi( arg1 );
else
to = edd->line_count;
send_to_pager( "------------------\n\r", ch );
line_num = 1;
eline = edd->first_line;
while( eline )
{
if( line_num >= from && line_num <= to )
pager_printf( ch, "%2d>%c%s\n\r", line_num, eline == edd->on_line ? '*' : ' ', eline->line );
eline = eline->next;
line_num++;
}
send_to_pager( "------------------\n\r", ch );
}
void editor_abort( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
send_to_char( "\n\rAborting... ", ch );
stop_editing( ch );
}
void editor_escaped_cmd( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
if( get_trust( ch ) > LEVEL_IMMORTAL )
{
DO_FUN *last_cmd;
int substate = ch->substate;
last_cmd = ch->last_cmd;
ch->substate = SUB_RESTRICTED;
interpret( ch, argument );
ch->substate = substate;
ch->last_cmd = last_cmd;
set_char_color( AT_GREEN, ch );
send_to_char( "\n\r", ch );
}
else
send_to_char( "You can't use '/!'.\n\r", ch );
}
void editor_save( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
DESCRIPTOR_DATA *d;
d = ch->desc;
d->connected = CON_PLAYING;
if( !ch->last_cmd )
return;
( *ch->last_cmd ) ( ch, "" );
}
char *Justify( char *oldstring, int iAlignment )
{
char xbuf[MAX_STRING_LENGTH * 2];
char xbuf2[MAX_STRING_LENGTH * 2];
// char xbuf[(4*MAX_STRING_LENGTH - 1000)];
// char xbuf2[(4*MAX_STRING_LENGTH - 1000)];
char *rdesc;
int i = 0;
int end_of_line;
bool cap = TRUE;
bool bFormat = TRUE;
xbuf[0] = xbuf2[0] = 0;
i = 0;
if( strlen( oldstring ) > MAX_STRING_LENGTH - 1 )
{
return ( oldstring );
}
if( oldstring[0] == '\0' )
{
return oldstring;
}
for( rdesc = oldstring; *rdesc; rdesc++ )
{
if( bFormat )
{
if( *rdesc == '\n' )
{
if( *( rdesc + 1 ) == '\r' && *( rdesc + 2 ) == ' ' && *( rdesc + 3 ) == '\n' && xbuf[i - 1] != '\r' )
{
xbuf[i] = '\n';
xbuf[i + 1] = '\r';
xbuf[i + 2] = '\n';
xbuf[i + 3] = '\r';
i += 4;
rdesc += 2;
}
else if( *( rdesc + 1 ) == '\r' && *( rdesc + 2 ) == ' ' && *( rdesc + 2 ) == '\n' && xbuf[i - 1] == '\r' )
{
xbuf[i] = '\n';
xbuf[i + 1] = '\r';
i += 2;
}
else if( *( rdesc + 1 ) == '\r' && *( rdesc + 2 ) == '\n' && xbuf[i - 1] != '\r' )
{
xbuf[i] = '\n';
xbuf[i + 1] = '\r';
xbuf[i + 2] = '\n';
xbuf[i + 3] = '\r';
i += 4;
rdesc += 1;
}
else if( *( rdesc + 1 ) == '\r' && *( rdesc + 2 ) == '\n' && xbuf[i - 1] == '\r' )
{
xbuf[i] = '\n';
xbuf[i + 1] = '\r';
i += 2;
}
else if( xbuf[i - 1] != ' ' && xbuf[i - 1] != '\r' )
{
xbuf[i] = ' ';
i++;
}
}
else if( *rdesc == '\r' );
else if( *rdesc == 'i' && *( rdesc + 1 ) == '.' && *( rdesc + 2 ) == 'e' && *( rdesc + 3 ) == '.' )
{
xbuf[i] = 'i';
xbuf[i + 1] = '.';
xbuf[i + 2] = 'e';
xbuf[i + 3] = '.';
i += 4;
rdesc += 3;
}
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 if( xbuf[i - 1] == ' ' && ( xbuf[i - 2] == ',' || xbuf[i - 2] == ';' ) )
{
xbuf[i - 1] = *rdesc;
xbuf[i] = ' ';
i++;
}
else
{
xbuf[i] = *rdesc;
i++;
}
}
else if( *rdesc == ',' || *rdesc == ';' )
{
if( xbuf[i - 1] == ' ' )
{
xbuf[i - 1] = *rdesc;
xbuf[i] = ' ';
i++;
}
else
{
xbuf[i] = *rdesc;
if( *( rdesc + 1 ) != '\"' )
{
xbuf[i + 1] = ' ';
i += 2;
}
else
{
xbuf[i + 1] = '\"';
xbuf[i + 2] = ' ';
i += 3;
rdesc++;
}
}
}
else if( ( *rdesc == '.' && *( rdesc + 1 ) == ' ' ) || *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++;
}
}
else
{
xbuf[i] = *rdesc;
i++;
}
}
xbuf[i] = 0;
strcpy( xbuf2, xbuf );
rdesc = xbuf2;
xbuf[0] = 0;
for( ;; )
{
end_of_line = iAlignment;
for( i = 0; i < end_of_line; i++ )
{
if( *( rdesc + i ) == '`' )
{
end_of_line += 2;
i++;
}
if( !*( rdesc + i ) )
break;
if( *( rdesc + i ) == '\r' )
end_of_line = i;
}
if( i < end_of_line )
{
break;
}
if( *( rdesc + i - 1 ) != '\r' )
{
for( i = ( xbuf[0] ? ( end_of_line - 1 ) : ( end_of_line - 4 ) ); 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
{
*( rdesc + ( end_of_line - 2 ) ) = 0;
strcat( xbuf, rdesc );
strcat( xbuf, "-\n\r" );
rdesc += end_of_line - 1;
}
}
else
{
*( rdesc + i - 1 ) = 0;
strcat( xbuf, rdesc );
strcat( xbuf, "\r" );
rdesc += i;
while( *rdesc == ' ' )
rdesc++;
}
}
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" );
return ( str_dup( xbuf ) );
}
// New editor format taken and altered from AFKMUD. --Saiyr
void editor_format( CHAR_DATA * ch, EDITOR_DATA * edd, char *argument )
{
char *buf;
buf = editdata_to_str( ch->editor );
buf = Justify( buf, 76 );
ch->editor = str_to_editdata( buf, MAX_STRING_LENGTH );
send_to_char( "OK.\n\r", ch );
return;
}
/****************************************************************************
* Misc functions
*/
char *text_replace( char *src, char *word_src, char *word_dst, sh_int * pnew_size, sh_int * prepl_count )
/* Replaces a word word_src in src for word_dst. Returns a pointer to a newly
* allocated buffer containing the line with the replacements. Stores in
* pnew_size the size of the allocated buffer, wich may be different from the
* length of the string and is a multiple of CHAR_BLOCK. Stores in prepl_count
* the number of replacements it made */
{
char *dst_buf;
char *next_found, *last_found;
sh_int dst_used, dst_size, len;
sh_int repl_count;
/*
* prepare the destination buffer
*/
CREATE( dst_buf, char, CHAR_BLOCK );
dst_size = CHAR_BLOCK;
dst_used = 0;
dst_buf[0] = '\0';
last_found = src;
repl_count = 0;
for( ;; )
{
/*
* look for next instance of word
*/
next_found = strstr( last_found, word_src );
if( next_found == NULL )
{
/*
* if theres no more instances of word,
* * copy the rest of the src
*/
len = strlen( last_found );
RESIZE_IF_NEEDED( dst_buf, dst_size, dst_used, len + 1 );
strcat( dst_buf, last_found );
dst_used += len;
break;
}
/*
* copy the buffer up to this instance of the word
* * and then copy the replacement word
*/
len = next_found - last_found + strlen( word_dst );
RESIZE_IF_NEEDED( dst_buf, dst_size, dst_used, len + 1 );
strncat( dst_buf, last_found, next_found - last_found );
strcat( dst_buf, word_dst );
dst_used += len;
last_found = next_found + strlen( word_src );
repl_count++;
}
*pnew_size = dst_size;
*prepl_count = repl_count;
return dst_buf;
}
/*
* Pick off one argument from a string and return the rest.
* Understands quotes.
* A pickier version than regular one_argument, it will not
* convert to lowercase, and it can handle the (') character
* when it's escaped inside '.
*/
char *finer_one_argument( char *argument, char *arg_first )
{
char cEnd;
sh_int count;
bool escaped;
count = 0;
while( isspace( *argument ) )
argument++;
cEnd = ' ';
if( *argument == '\'' || *argument == '"' )
cEnd = *argument++;
escaped = FALSE;
while( *argument != '\0' || ++count >= MAX_INPUT_LENGTH )
{
if( cEnd != ' ' && escaped )
{
if( *argument == '\\' )
*arg_first = '\\';
else if( *argument == '\'' )
*arg_first = '\'';
else if( *argument == '"' )
*arg_first = '"';
else
*arg_first = *argument;
arg_first++;
argument++;
escaped = FALSE;
continue;
}
if( cEnd != ' ' && *argument == '\\' && !escaped )
{
escaped = TRUE;
argument++;
continue;
}
if( *argument == cEnd )
{
argument++;
break;
}
*arg_first = *argument;
arg_first++;
argument++;
}
*arg_first = '\0';
while( isspace( *argument ) )
argument++;
return argument;
}