btmux-0.6-rc4/doc/
btmux-0.6-rc4/event/
btmux-0.6-rc4/game/
btmux-0.6-rc4/game/maps/
btmux-0.6-rc4/game/mechs/
btmux-0.6-rc4/game/text/help/
btmux-0.6-rc4/game/text/help/cat_faction/
btmux-0.6-rc4/game/text/help/cat_inform/
btmux-0.6-rc4/game/text/help/cat_misc/
btmux-0.6-rc4/game/text/help/cat_mux/
btmux-0.6-rc4/game/text/help/cat_mux/cat_commands/
btmux-0.6-rc4/game/text/help/cat_mux/cat_functions/
btmux-0.6-rc4/game/text/help/cat_templates/
btmux-0.6-rc4/game/text/wizhelp/
btmux-0.6-rc4/include/
btmux-0.6-rc4/misc/
btmux-0.6-rc4/python/
btmux-0.6-rc4/src/hcode/btech/
btmux-0.6-rc4/tree/
/*
 * stringutil.c -- string utilities 
 */

#include "copyright.h"
#include "config.h"

#include "mudconf.h"
#include "config.h"
#include "externs.h"
#include "alloc.h"
#include "ansi.h"

#ifdef __linux__
char *___strtok;

#endif

/**
 * Convert raw character sequences into MUX substitutions (type = 1)
 * or strips them (type = 0). 
 */
char *translate_string(const char *str, int type)
{
	char old[LBUF_SIZE];
	static char new[LBUF_SIZE];
	char *j, *c, *bp;
	int i;

	bp = new;
	StringCopy(old, str);

	for(j = old; *j != '\0'; j++) {
		switch (*j) {
		case ESC_CHAR:
			c = strchr(j, 'm');
			if(c) {
				if(!type) {
					j = c;
					break;
				}

				*c = '\0';
				i = atoi(j + 2);
				switch (i) {
				case 0:
					safe_str("%cn", new, &bp);
					break;
				case 1:
					safe_str("%ch", new, &bp);
					break;
				case 5:
					safe_str("%cf", new, &bp);
					break;
				case 7:
					safe_str("%ci", new, &bp);
					break;
				case 30:
					safe_str("%cx", new, &bp);
					break;
				case 31:
					safe_str("%cr", new, &bp);
					break;
				case 32:
					safe_str("%cg", new, &bp);
					break;
				case 33:
					safe_str("%cy", new, &bp);
					break;
				case 34:
					safe_str("%cb", new, &bp);
					break;
				case 35:
					safe_str("%cm", new, &bp);
					break;
				case 36:
					safe_str("%cc", new, &bp);
					break;
				case 37:
					safe_str("%cw", new, &bp);
					break;
				case 40:
					safe_str("%cX", new, &bp);
					break;
				case 41:
					safe_str("%cR", new, &bp);
					break;
				case 42:
					safe_str("%cG", new, &bp);
					break;
				case 43:
					safe_str("%cY", new, &bp);
					break;
				case 44:
					safe_str("%cB", new, &bp);
					break;
				case 45:
					safe_str("%cM", new, &bp);
					break;
				case 46:
					safe_str("%cC", new, &bp);
					break;
				case 47:
					safe_str("%cW", new, &bp);
					break;
				}
				j = c;
			} else {
				safe_chr(*j, new, &bp);
			}
			break;
		case ' ':
			if((*(j + 1) == ' ') && type)
				safe_str("%b", new, &bp);
			else
				safe_chr(' ', new, &bp);
			break;
		case '\\':
			if(type)
				safe_str("\\", new, &bp);
			else
				safe_chr('\\', new, &bp);
			break;
		case '%':
			if(type)
				safe_str("%%", new, &bp);
			else
				safe_chr('%', new, &bp);
			break;
		case '[':
			if(type)
				safe_str("%[", new, &bp);
			else
				safe_chr('[', new, &bp);
			break;
		case ']':
			if(type)
				safe_str("%]", new, &bp);
			else
				safe_chr(']', new, &bp);
			break;
		case '{':
			if(type)
				safe_str("%{", new, &bp);
			else
				safe_chr('{', new, &bp);
			break;
		case '}':
			if(type)
				safe_str("%}", new, &bp);
			else
				safe_chr('}', new, &bp);
			break;
		case '(':
			if(type)
				safe_str("%(", new, &bp);
			else
				safe_chr('(', new, &bp);
			break;
		case ')':
			if(type)
				safe_str("%)", new, &bp);
			else
				safe_chr(')', new, &bp);
			break;
		case '\r':
			break;
		case '\n':
			if(type)
				safe_str("%r", new, &bp);
			else
				safe_chr(' ', new, &bp);
			break;
		default:
			safe_chr(*j, new, &bp);
		}
	}
	*bp = '\0';
	return new;
}

/*
 * capitalizes an entire string
 */

char *upcasestr(char *s)
{
	char *p;

	for(p = s; p && *p; p++)
		*p = ToUpper(*p);
	return s;
}

/*
 * returns a pointer to the non-space character in s, or a NULL if s == NULL
 * or *s == NULL or s has only spaces.
 */
char *skip_space(const char *s)
{
	char *cp;

	cp = (char *) s;
	while (cp && *cp && isspace(*cp))
		cp++;
	return (cp);
}

/**
 * returns a pointer to the next character in s matching c, or a pointer to
 * the \0 at the end of s. Yes, this is a lot like index, but not exactly.
 */
char *seek_char(const char *s, char c)
{
	char *cp;

	cp = (char *) s;
	while (cp && *cp && (*cp != c))
		cp++;
	return (cp);
}

/**
 * Compress multiple spaces to one space, also remove leading and
 * trailing spaces.
 */
char *munge_space(char *string)
{
	char *buffer, *p, *q;

	buffer = alloc_lbuf("munge_space");
	p = string;
	q = buffer;
	while (p && *p && isspace(*p))
		p++;					/*
								 * remove inital spaces 
								 */
	while (p && *p) {
		while (*p && !isspace(*p))
			*q++ = *p++;
		while (*p && isspace(*++p));
		if(*p)
			*q++ = ' ';
	}
	*q = '\0';					/*
								 * remove terminal spaces and terminate * * * 
								 * 
								 * * string 
								 */
	return (buffer);
}

/**
 * Remove leading and trailing spaces.
 */
char *trim_spaces(char *string)
{
	char *buffer, *p, *q;

	buffer = alloc_lbuf("trim_spaces");
	p = string;
	q = buffer;
	while (p && *p && isspace(*p))	/*
									 * remove inital spaces 
									 */
		p++;
	while (p && *p) {
		while (*p && !isspace(*p))	/*
									 * copy nonspace chars 
									 */
			*q++ = *p++;
		while (*p && isspace(*p))	/*
									 * compress spaces 
									 */
			p++;
		if(*p)
			*q++ = ' ';			/*
								 * leave one space 
								 */
	}
	*q = '\0';					/*
								 * terminate string 
								 */
	return (buffer);
}

/**
 * Return portion of a string up to the indicated character. Also
 * returns a modified pointer to the string ready for another call.
 */
char *grabto(char **str, char targ)
{
	char *savec, *cp;

	if(!str || !*str || !**str)
		return NULL;

	savec = cp = *str;
	while (*cp && *cp != targ)
		cp++;
	if(*cp)
		*cp++ = '\0';
	*str = cp;
	return savec;
}

int string_compare(const char *s1, const char *s2)
{
	if(!mudconf.space_compress) {
		while (*s1 && *s2 && ToLower(*s1) == ToLower(*s2))
			s1++, s2++;

		return (ToLower(*s1) - ToLower(*s2));
	} else {
		while (isspace(*s1))
			s1++;
		while (isspace(*s2))
			s2++;
		while (*s1 && *s2 && ((ToLower(*s1) == ToLower(*s2)) ||
							  (isspace(*s1) && isspace(*s2)))) {
			if(isspace(*s1) && isspace(*s2)) {	/*
												 * skip all  
												 * other
												 * spaces 
												 */
				while (isspace(*s1))
					s1++;
				while (isspace(*s2))
					s2++;
			} else {
				s1++;
				s2++;
			}
		}
		if((*s1) && (*s2))
			return (1);
		if(isspace(*s1)) {
			while (isspace(*s1))
				s1++;
			return (*s1);
		}
		if(isspace(*s2)) {
			while (isspace(*s2))
				s2++;
			return (*s2);
		}
		if((*s1) || (*s2))
			return (1);
		return (0);
	}
}

int string_prefix(const char *string, const char *prefix)
{
	int count = 0;

	while (*string && *prefix && ToLower(*string) == ToLower(*prefix))
		string++, prefix++, count++;
	if(*prefix == '\0')			/*
								 * Matched all of prefix 
								 */
		return (count);
	else
		return (0);
}

/**
 * Accepts only nonempty matches starting at the beginning of a word 
 */
const char *string_match(const char *src, const char *sub)
{
	if((*sub != '\0') && (src)) {
		while (*src) {
			if(string_prefix(src, sub))
				return src;
			/*
			 * else scan to beginning of next word 
			 */
			while (*src && isalnum(*src))
				src++;
			while (*src && !isalnum(*src))
				src++;
		}
	}
	return 0;
}

/**
 * Returns an lbuf containing string STRING with all occurances
 * of OLD replaced by NEW. OLD and NEW may be different lengths.
 */
char *replace_string(const char *old, const char *new, const char *string)
{
	char *result, *r, *s;
	int olen;

	if(string == NULL)
		return NULL;
	s = (char *) string;
	olen = strlen(old);
	r = result = alloc_lbuf("replace_string");
	while (*s) {

		/*
		 * Copy up to the next occurrence of the first char of OLD 
		 */

		while (*s && *s != *old) {
			safe_chr(*s, result, &r);
			s++;
		}

		/*
		 * If we are really at an OLD, append NEW to the result and * 
		 * 
		 * *  * *  * * bump the input string past the occurrence of
		 * OLD. *  * * * Otherwise, copy the char and try again. 
		 */

		if(*s) {
			if(!strncmp(old, s, olen)) {
				safe_str((char *) new, result, &r);
				s += olen;
			} else {
				safe_chr(*s, result, &r);
				s++;
			}
		}
	}
	*r = '\0';
	return result;
}

/**
 * Returns string STRING with all occurances * of OLD replaced by NEW. OLD
 * and NEW may be different lengths. Modifies string, so: Note - STRING must
 * already be allocated large enough to handle the new size. (mitch 1 feb 91)
 */
char *replace_string_inplace(const char *old, const char *new, char *string)
{
	char *s;

	s = replace_string(old, new, string);
	StringCopy(string, s);
	free_lbuf(s);
	return string;
}

/**
 * Counts occurances of C in STR. - mnp 7 feb 91 
 */
int count_chars(const char *str, const char c)
{
	int out = 0;
	const char *p = str;

	if(p)
		while (*p != '\0')
			if(*p++ == c)
				out++;
	return out;
}

/**
 * returns the number of identical characters in the two strings 
 */
int prefix_match(const char *s1, const char *s2)
{
	int count = 0;

	while (*s1 && *s2 && (ToLower(*s1) == ToLower(*s2)))
		s1++, s2++, count++;
	/*
	 * If the whole string matched, count the null.  (Yes really.) 
	 */
	if(!*s1 && !*s2)
		count++;
	return count;
}

int minmatch(char *str, char *target, int min)
{
	while (*str && *target && (ToLower(*str) == ToLower(*target))) {
		str++;
		target++;
		min--;
	}
	if(*str)
		return 0;
	if(!*target)
		return 1;
	return ((min <= 0) ? 1 : 0);
}

char *strsave(const char *s)
{
	char *p;
	p = (char *) XMALLOC(sizeof(char) * (strlen(s) + 1), "strsave");

	if(p)
		StringCopy(p, s);
	return p;
}

/**
 * Copy buffers, watching for overflows.
 */
int safe_copy_str(char *src, char *buff, char **bufp, int max)
{
	char *tp;

	tp = *bufp;
	if(src == NULL)
		return 0;
	while (*src && ((tp - buff) < max))
		*tp++ = *src++;
	*bufp = tp;
	return strlen(src);
}

/**
 * Copy buffers, watching for overflows.
 */
int safe_copy_chr(char src, char *buff, char **bufp, int max)
{
	char *tp;
	int retval;

	tp = *bufp;
	retval = 0;
	if((tp - buff) < max) {
		*tp++ = src;
	} else {
		retval = 1;
	}
	*bufp = tp;
	return retval;
}

int matches_exit_from_list(char *str, char *pattern)
{
	char *s;

	while (*pattern) {
		for(s = str;			/*
								 * check out this one 
								 */
			(*s && (ToLower(*s) == ToLower(*pattern)) && *pattern &&
			 (*pattern != EXIT_DELIMITER)); s++, pattern++);

		/*
		 * Did we match it all? 
		 */

		if(*s == '\0') {

			/*
			 * Make sure nothing afterwards 
			 */

			while (*pattern && isspace(*pattern))
				pattern++;

			/*
			 * Did we get it? 
			 */

			if(!*pattern || (*pattern == EXIT_DELIMITER))
				return 1;
		}
		/*
		 * We didn't get it, find next string to test 
		 */

		while (*pattern && *pattern++ != EXIT_DELIMITER);
		while (isspace(*pattern))
			pattern++;
	}
	return 0;
}