/*****************************************************************
* mobstring.c
* This snippet allows a certain mobile to restring objects for
* players. To just drop into your box, you will need to add an
* ACT flag: ACT_IS_RESTRINGER, or you can change it to whatever
* fits your MUD best. Quite easy to change this into needing no
* mobile at all.
* Code by Evangelion <jeremyhill@cox.net>
*
* Last updated: Nov 27 2003
******************************************************************/
/* Much of the string iteration looping is borrowed from
 *Snafu Life. Here is the header that is included in his file:      
 *************************************************************
  Name:       count_color_string
  Purpose:    Returns the string length minus color codes.
  Written By: Snafu Life.
 *************************************************************
* Void do_mob_string
* Code by Evangelion <jeremyhill@cox.net>
* Last modified: Nov 27 2003
*    - Changed to match Lope's standard color set.  Originally
*      created for a MUD that uses ` as the color key.
* Aug 15 02:
*    - Initial release
* One potential problem:  string{{x.  This wouldn't bleed, but
* it would look like 'stringx'.  The only way to solve this is
* to go through the string backwards and make sure there's enough
* {'s to go around (there'd need to be an odd number of {'s before
* x).  I'd rather let the mort pay more money than check this
* with code. :)
***************************************************************/

void do_mob_string (CHAR_DATA * ch, char *argument)
{
   int i;
   long cost;
   OBJ_DATA *obj;
   CHAR_DATA *mob;
   char arg1[MAX_INPUT_LENGTH];   /*Object*/
   char string_where[MAX_INPUT_LENGTH];
   char *string;
   bool errors, isName; 

   isName = FALSE;
   errors = FALSE;
   cost   = 250000;
   
   for (mob = ch->in_room->people; mob; mob = mob->next_in_room)
   {
	if(IS_NPC(mob) && IS_SET(mob->act, ACT_IS_RESTRINGER))
		break;
   }
    
   if (mob == NULL)
   {
	send_to_char("No one here is skilled enough to do that.\n\r", ch);
	return;
   }

   /*Gold check*/
   if ((ch->gold - cost) < 0)
   {
      act("$N says '{MYou're poor!  Get a job, you shiftless bum!{x'", ch, NULL, mob, TO_CHAR);
      send_to_char("(Payment comes out of your bank account)\n\r)", ch);
      return;
   }

   if ( argument == NULL || argument[0] == '\0' )
      return;

   smash_tilde (argument);
   argument = one_argument (argument, arg1);
   argument = one_argument (argument, string_where);
   string = argument;

   if ((obj = get_obj_carry (ch, arg1)) == NULL)
   {
       send_to_char ("You aren't carrying that object.\n\r", ch);
       return;
   }

   /* Sanity check for empty strings */
   if( string == NULL || string[0] == '\0'){
      act("$N says '{PYou have to provide a string, smartypants!{7'", ch, NULL, mob, TO_CHAR);   	
      return;
   }
  
   /*Don't allow colors at all in 'name' for objects'*/
   if (!str_prefix(string_where, "name"))
      isName = TRUE;
      
   /* Start looping through *string */
   for(i = 0; i < strlen(string); i++)
   {      
       /* When the end is reached, break.*/
	if(string[i] == '\0') {
		break;
	}
        
        /* If string[i] isn't '{', then continue.
         * Placed here to save time as most chars won't be.
         */
	else if(string[i] != '{' ) {
		continue;
	}
        else if(string[i] == '{' && isName) {
              {errors = TRUE; break;}
        }
        		
	/* If string[i] is '{' and string[i+1] is '\0'
         * Whoa, wrong, return.  It'll bleed.  For example, string{ .
         */
	else if (string[i] == '{' && string[i+1] == '\0' ) {
		send_to_char_bw("That string will colorbleed--please"
		             " end your strings with {x.\n\r", ch);
		return;
	}
	
	/* If string[i] is '{' and string[i+1] isn't '\0', but
	 * string[i+2] is \0.  If so, we need to make sure that
	 * the color won't bleed.  
	 */
	else if (string[i] == '{' && string[i+1] != '\0' && string[i+2] == '\0')
	{
	   /* All done*/
	   if (string[i+1] == 'x')
	      break;
	   else
	   /*Color bleeding (string{{ or string{O for example)*/
	   {
		send_to_char_bw("That string will colorbleed--please"
		             " end your strings with {x.\n\r", ch);
		return;
           }
	}
        	
	/* Isn't needed, but makes me feel better ;)
         */
	else { continue; }
   }

   if (errors)
   {
      send_to_char("Colors are not allowed in the name of an object.\n\r", ch);
      return;
   }

   if (!str_prefix (string_where, "name"))
   {
       free_string (obj->name);
       obj->name = str_dup (string);
   }
   else if (!str_prefix (string_where, "short"))
   {
       free_string (obj->short_descr);
       obj->short_descr = str_dup (string);
   }
   else if (!str_prefix (string_where, "long"))
   {
       free_string (obj->description);
       obj->description = str_dup (string);
   }
   else
   {
      send_to_char("The commissary man stares blankly at you for a moment before finally pointing at a sign on the wall labeled '{Chelp autostring{x'.\n\r",ch);
      return;
   }
   
   ch->gold -= cost;
   act("$N says '{MAll done!{x'", ch, NULL, mob, TO_CHAR);
   return;
}