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