/*************************************************************************** * File: string.c * * * * 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. * * * * This code was freely distributed with the The Isles 1.1 source code, * * and has been used here for OLC - OLC would not be what it is without * * all the previous coders who released their source code. * * * ***************************************************************************/ #include "merc.h" #include "tables.h" #include "interp.h" #include "olc.h" char *string_linedel( char *, int ); char *string_lineadd( char *, char *, int ); char *numlineas( char * ); /***************************************************************************** Name: string_edit Purpose: Clears string and puts player into editing mode. Called by: none ****************************************************************************/ void string_edit( CHAR_DATA *ch, char **pString ) { send_to_char( "-========- Entering EDIT Mode -=========-\n\r", ch ); send_to_char( " Type /h on a new line for help\n\r", ch ); send_to_char( " Terminate with /s on a blank line.\n\r", ch ); send_to_char( "-=======================================-\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( "-=======- Entering APPEND Mode -========-\n\r", ch ); send_to_char( " Type /h on a new line for help\n\r", ch ); send_to_char( " Terminate with /s on a blank line.\n\r", ch ); send_to_char( "-=======================================-\n\r", ch ); if ( *pString == NULL ) *pString = str_dup( "" ); send_to_char(numlineas(*pString), ch); ch->desc->pString = pString; return; } /***************************************************************************** Purpose: Substitutes one string for another. ****************************************************************************/ char * string_replace( char * orig, char *sOld, char *sNew ) { char xbuf[MAX_STRING_LENGTH]; int i; xbuf[0] = '\0'; strcpy( xbuf, orig ); if ( strstr( orig, sOld ) != NULL ) { i = strlen( orig ) - strlen( strstr( orig, sOld ) ); xbuf[i] = '\0'; strcat( xbuf, sNew ); strcat( xbuf, &orig[i+strlen( sOld )] ); free_string( orig ); } return str_dup( xbuf ); } #define PARSE_REPLACE 0 #define PARSE_HELP 1 #define PARSE_DELETE 2 #define PARSE_INSERT 3 #define PARSE_EDIT 4 #define PARSE_LIST_NORM 5 #define PARSE_LIST_NUM 6 void parse_action(int command, char *string, CHAR_DATA *ch) { char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH]; switch (command) { case PARSE_HELP: send_to_char("Edit 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("/h - get help (this info)\n\r", ch); send_to_char("/l - show string so far\n\r", ch); send_to_char("/n - show numbered string so far\n\r", ch); 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# - delete line number <num>\n\r", ch); send_to_char("/i# <str> - insert <str> on line <num>\n\r", ch); send_to_char("/e# <str> - replace line <num> with <str>\n\r", ch); send_to_char("/s - end string\n\r", ch); break; case PARSE_EDIT: string = one_argument(string, arg1); if (arg1[0] == '\0') { send_to_char("You must specify a line number.\n\r", ch); return; } *ch->desc->pString = string_linedel(*ch->desc->pString, atoi(arg1)); *ch->desc->pString = string_lineadd(*ch->desc->pString, string, atoi(arg1)); send_to_char("Line replaced.\n\r", ch); break; case PARSE_DELETE: *ch->desc->pString = string_linedel(*ch->desc->pString, atoi(string)); send_to_char("Line deleted.\n\r", ch); break; case PARSE_REPLACE: string = first_arg(string, arg1, FALSE); string = first_arg(string, arg2, FALSE); if (arg1[0] == '\0') { send_to_char("Usage: /r 'old string' 'new string'\n\r", ch); return; } *ch->desc->pString = string_replace(*ch->desc->pString, arg1, arg2); ch->Send("'%s' replaced with '%s'.\n\r", arg1, arg2); break; case PARSE_INSERT: string = first_arg(string, arg1, FALSE); *ch->desc->pString = string_lineadd(*ch->desc->pString, string, atoi(arg1)); send_to_char("Line inserted.\n\r", ch); break; case PARSE_LIST_NORM: send_to_char("String so far:\n\r", ch); send_to_char(*ch->desc->pString, ch); break; case PARSE_LIST_NUM: send_to_char("String so far:\n\r", ch); send_to_char(numlineas(*ch->desc->pString), ch); break; default: send_to_char("Invalid command.\n\r", ch); mudlogf(BRF, LVL_CODER, TRUE, "SYSERR: invalid command passed to parse_action"); break; } } void string_add( CHAR_DATA *ch, char *str ) { int i = 2, j = 0, action = 0; char buf[MAX_STRING_LENGTH], actions[MAX_INPUT_LENGTH]; bool terminate = FALSE; smash_tilde( str ); if ((action = (*str == '/'))) { while (str[i] != '\0') { actions[j] = str[i]; i++; j++; } actions[j] = '\0'; *str = '\0'; switch (str[1]) { case 's': terminate = TRUE; *str = '\0'; break; case 'c': send_to_char("String cleared.\n\r", ch); free_string(*ch->desc->pString); *ch->desc->pString = str_dup(""); return; case 'l': parse_action(PARSE_LIST_NORM, actions, ch); return; case 'n': parse_action(PARSE_LIST_NUM, actions, ch); return; case 'r': parse_action(PARSE_REPLACE, actions, ch); return; case 'f': *ch->desc->pString = format_string(*ch->desc->pString); send_to_char("String formatted.\n\r", ch); return; case 'd': parse_action(PARSE_DELETE, actions, ch); return; case 'i': parse_action(PARSE_INSERT, actions, ch); return; case 'e': parse_action(PARSE_EDIT, actions, ch); return; case 'h': parse_action(PARSE_HELP, actions, ch); return; default: send_to_char("Invalid command.\n\r", ch); return; } } if (terminate) { if (ch->desc->editor == ED_MPCODE) { MOB_INDEX_DATA *mob; int hash; MPROG_LIST *mpl; MPROG_CODE *mpc; EDIT_MPCODE(ch, mpc); if ( mpc != NULL ) for ( hash = 0; hash < MAX_KEY_HASH; hash++ ) for ( mob = mob_index_hash[hash]; mob; mob = mob->next ) for ( mpl = mob->mprogs; mpl; mpl = mpl->next ) if ( mpl->vnum == mpc->vnum ) { sprintf( buf, "Updating mob %d.\n\r", mob->vnum ); send_to_char( buf, ch ); mpl->code = mpc->code; } } ch->desc->pString = NULL; if (STATE(ch->desc) == CON_EXDESC) { extern char *MENU; send_to_char(MENU, ch); STATE(ch->desc) = CON_MENU; } return; } strcpy( buf, *ch->desc->pString ); /* * Truncate strings to MAX_STRING_LENGTH. * -------------------------------------- */ if (strlen(buf) + strlen(str) >= (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( str ); strcat( buf, str ); 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. */ /***************************************************************************** Name: format_string Purpose: Special string formating and word-wrapping. Called by: string_add(string.c) (many)olc_act.c ****************************************************************************/ 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)); } /* * Used above in string_add. Because this function does not * modify case if fCase is FALSE and because it understands * parenthesis, it would probably make a nice replacement * for one_argument. */ /***************************************************************************** Purpose: Pick off one argument from a string and return the rest. Understands quates, parenthesis (barring ) ('s) and percentages. Called by: string_add(string.c) ****************************************************************************/ 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; } /* * Used in olc_act.c for aedit_builders. */ 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 ); } /* * Same as capitalize but changes the pointer's data. * Used in olc_act.c in aedit_builder. */ 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; } char *string_linedel( char *string, int line ) { char *strtmp = string; char buf[MAX_STRING_LENGTH]; int cnt = 1, tmp = 0; buf[0] = '\0'; for ( ; *strtmp != '\0'; strtmp++ ) { if ( cnt != line ) buf[tmp++] = *strtmp; if ( *strtmp == '\n' ) { if ( *(strtmp + 1) == '\r' ) { if ( cnt != line ) buf[tmp++] = *(++strtmp); else ++strtmp; } cnt++; } } buf[tmp] = '\0'; free_string(string); return str_dup(buf); } char *string_lineadd( char *string, char *newstr, int line ) { char *strtmp = string; int cnt = 1, tmp = 0; bool done = FALSE; char buf[MAX_STRING_LENGTH]; buf[0] = '\0'; for ( ; *strtmp != '\0' || (!done && cnt == line); strtmp++ ) { if ( cnt == line && !done ) { strcat( buf, newstr ); strcat( buf, "\n\r" ); tmp += strlen(newstr) + 2; cnt++; done = TRUE; } buf[tmp++] = *strtmp; if ( done && *strtmp == '\0' ) break; if ( *strtmp == '\n' ) { if ( *(strtmp + 1) == '\r' ) buf[tmp++] = *(++strtmp); cnt++; } buf[tmp] = '\0'; } free_string(string); return str_dup(buf); } /* buf queda con la linea sin \n\r */ char *getline( char *str, char *buf ) { int tmp = 0; bool found = FALSE; while ( *str ) { if ( *str == '\n' ) { found = TRUE; break; } buf[tmp++] = *(str++); } if ( found ) { if ( *(str + 1) == '\r' ) str += 2; else str += 1; } /* para que quedemos en el inicio de la prox linea */ buf[tmp] = '\0'; return str; } char *numlineas( char *string ) { int cnt = 1; static char buf[MAX_STRING_LENGTH*2]; char buf2[MAX_STRING_LENGTH], tmpb[MAX_STRING_LENGTH]; buf[0] = '\0'; while ( *string ) { string = getline( string, tmpb ); sprintf( buf2, "%2d. %s\n\r", cnt++, tmpb ); strcat( buf, buf2 ); } return buf; }