/* * 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; }