/*=========================================================================
 *
 * GENSTRIN.CPP - 29 March 1999, Dave Humphrey (uesp@m0use.net)
 *
 * Contains various general string routines I use often.
 *
 *=======================================================================*/

	/* User Defined Includes */
#include "genutil.h"


#undef  __FUNC__
#define __FUNC__  "BooleanToString()"
/*=========================================================================
 *
 * Function - char *BooleanToString (bool);
 *
 * Returns a string pointer to "TRUE" or "FALSE" depending on the 
 * boolean value passed.
 *
 *=======================================================================*/
char *BooleanToString (const boolean b) { 
  return (b ? "TRUE" : "FALSE"); 
 }
/*=========================================================================
 *		End of Function BooleanToString()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "chradd()"
/*=========================================================================
 *
 * Function - boolean chradd (pString, CharIndex, NewChar);
 *
 * Attempts to insert the specified character into the string at the
 * given position (CharIndex).  First character in string is at position 0.
 * Assumes the string is long enough to add another character.  Returns
 * FALSE on any error and sets the appropiate error code.
 *
 *=======================================================================*/
boolean chradd (char *pString, const size_t CharIndex, const char NewChar) {
  char *pInsertPosition;
  size_t StringLength;

	/* Ignore any invalid input */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (FALSE);
   }

	/* Save length of string to a variable */
  StringLength = strlen(pString);
  
	/* Make sure we have a valid insert position */
  if (CharIndex > StringLength) {
    SET_EXT_ERROR(ERR_INPUT);
    return (FALSE);
   }

	/* Compute insert position and shift the remaining characters right by one */
  pInsertPosition = pString + CharIndex;
  memmove (pInsertPosition + 1, pInsertPosition, StringLength - CharIndex + 1);

	/* Add the new character to the string */
  *pInsertPosition = NewChar;
  return (TRUE);
 }
/*=========================================================================
 *		End of Function chradd()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "chrcat()"
/*=========================================================================
 *
 * Function - boolean chrcat (pString, NewChar);
 *
 * Adds the specified character to the end of the string.  Assumes that
 * the string is long enough to hold another character.  Returns FALSE on
 * any error and sets the appropiate error code.
 *
 *=======================================================================*/
boolean chrcat(char *pString, const char NewChar) {
  char *pInsertPosition;

	/* Ignore a NULL pointer */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (FALSE);
   }

	/* Find the end of the string */
  pInsertPosition = pString + strlen(pString);

	/* Add the character to end of string, making sure we NUL pad the
	 * end of the string */
  pInsertPosition[1] = '\0';
  pInsertPosition[0] = NewChar;
  return (TRUE);
 }
/*=========================================================================
 *		End of Function chrcat()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "chrdel()"
/*=========================================================================
 *
 * Function - boolean chrdel (pString, CharIndex);
 *
 * Attempts to delete the character at the given position from the string.
 * Position 0 is the first character in the string.  Returns FALSE on
 * any error and sets the appropiate error code.
 *
 *=======================================================================*/
boolean chrdel (char* pString, const size_t CharIndex) {
  char*  pDeletePosition;
  size_t StringLength;

	/* Ignore a NULL pointer */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (FALSE);
   }

	/* Save length of string*/
  StringLength = strlen(pString);
  
	/* Make sure the delete position given is valid */
  if (CharIndex > StringLength) {
    SET_EXT_ERROR(ERR_INPUT);
    return (FALSE);
   }

	/* Compute delete position and shift the characters left by one */
  pDeletePosition = pString + CharIndex;
  memmove (pDeletePosition, pDeletePosition + 1, StringLength - CharIndex + 1);
  return (TRUE);
 }
/*=========================================================================
 *		End of Function chrdel()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "chrdellast()"
/*=========================================================================
 *
 * Function - boolean chrdellast (pString);
 *
 * Deletes the last character from the given string.  Returns FALSE on
 * any error and sets the appropiate error code.
 *
 *=======================================================================*/
boolean chrdellast (char *pString) {
  size_t StringLength;

	/* Ignore a NULL pointer */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (FALSE);
   }

	/* Find last character in string, and ensure at least one exists */
  StringLength = strlen(pString);
  if (StringLength == 0) return (FALSE);

  	/* Delete the last character in the string */
  pString[StringLength - 1] = '\0';
  return (TRUE);
 }
/*=========================================================================
 *		End of Function chrdellast()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "chr_rpunc()"
/*=========================================================================
 *
 * Function - int chr_rpunc (string);
 *
 * Looks for the first puncuation character from the end of the string.
 * Returns the character index if one is found (0 is the first character
 * in the string) or CHARACTER_NOT_FOUND on error.
 *
 *=======================================================================*/
int chr_rpunc (const char *pString) {
  size_t StringPosition;

	/* Ignore any invalid input */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (CHARACTER_NOT_FOUND);
   }

	/* Start at the end of the string */
  StringPosition = strlen(pString);

	/* Look for a punctuating character until start of string is reached */
  while (StringPosition != 0) {
    StringPosition--;
    if (IsPunctuation(pString[StringPosition])) return (StringPosition);
   }

	/* Character not found in string */
  return (CHARACTER_NOT_FOUND);
 }
/*=========================================================================
 *		End of Function chr_rpunc()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "chrtok()"
/*========================================================================
 *
 * Function - char* chrtok (pString, Token);
 *
 * Seperates the given string into substrings divided by the given token 
 * character, much like strtok().  Returns NULL when no substrings are 
 * left.
 *
 *======================================================================*/
char* chrtok (char* pString, const char Token) { 
  static char* pParse = NULL;
  char*	 pChar;
  char*	 pResult;

	/* Nothing to parse? */ 
  if (pString == NULL && pParse == NULL) return (NULL);
  if (pString != NULL) pParse = pString;

	/* Search for the next substring */
  pChar = strchr(pParse, Token);

	/* No more substrings */
  if (pChar == NULL) {
    pResult = pParse;
    pParse = NULL;
    return (pResult);
   }

	/* Terminate substring */
  *pChar = NULL_CHAR;
  pResult = pParse;
  pParse = pChar + 1;
  return (pResult);
 }
/*========================================================================
 *		End of Function chktok()
 *======================================================================*/


#undef  __FUNC__
#define __FUNC__  "CountSubStrings()"
/*===========================================================================
 *
 * Function - int CountSubStrings (pString, pSubString);
 *
 * Counts occurences of sub string in string.
 *
 *=========================================================================*/
int CountSubStrings (const char* pString, const char* pSubString) {
  int   Count = 0;
  char* pFind;

	/* Ensure valid input */
  if (pString == NULL || pSubString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (0);
   }
	/* Special case for nul character */
  else if (*pSubString == NULL_CHAR) {
    return(1);
   }

  pFind = strstr(pString, pSubString);

  while (pFind != NULL) {
    Count++;
    pFind = strstr(pFind+1, pSubString);
   }

  return (Count);
 }
/*===========================================================================
 *		End of Function CountSubStrings()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__  "GetString()"
/*===========================================================================
 *
 * Function - int GetString (pInputBuffer, MaxStringLength);
 *
 * Replacement for gets(), inputs a string from keyboard up to the given
 * string length. Returns the number of characters input, or GETSTRING_ESC
 * if the ESC key was presser, or GETSTRING_ERROR on any error.
 *
 *=========================================================================*/
int GetString (char* pInputBuffer, const size_t MaxStringLength) {
  int StringSize;
  int InputChar;

	/* Ensure valid input */
  if (pInputBuffer == NULL || MaxStringLength == 0) {
    SET_EXT_ERROR(ERR_NULL);
    return (GETSTRING_ERROR);
   }

	/* Initialize loop variables */
  StringSize = 0;
  pInputBuffer[0] = NULL_CHAR;

	/* Main input loop */
  do {
		/* Return character from keyboard */
    InputChar = getch();

    if (InputChar == EOF) {
      SET_EXT_ERROR(ERR_READ);
      pInputBuffer[StringSize] = NULL_CHAR;
      return(FALSE);
     }
		/* Check for ESC or newline characters */
    else if (InputChar == ESC_CHAR) {
      putc(CR_CHAR, stdout);
      pInputBuffer[StringSize] = NULL_CHAR;
      return (GETSTRING_ESC);
     }
    else if (InputChar == CR_CHAR || InputChar == LF_CHAR) {
      putc(CR_CHAR, stdout);
      break;
     }
    else if (InputChar == DEL_CHAR && StringSize > 0) {
      putc(DEL_CHAR, stdout);
      putc(' ', stdout);
      putc(DEL_CHAR, stdout);
      StringSize--;
     }
		/* Ensure new character will fit in string */
    else if (isprint(InputChar) && StringSize < (int)MaxStringLength) {
      putc(InputChar, stdout);
      pInputBuffer[StringSize] = (char) InputChar;
      StringSize++;
     }

  } while(TRUE);

	/* Terminate string and return string length */
  pInputBuffer[StringSize] = NULL_CHAR;
  return(StringSize);
 }
/*===========================================================================
 *		End of Function GetString()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__  "lstrip()"
/*=========================================================================
 *
 * Function - char *lstrip (char *pString);
 *
 * Returns a pointer to the first non-whitespace character in the string.
 * Whitespace includes spaces and tabs.
 *
 *=======================================================================*/
char *lstrip (char *pString) {
  register size_t Index = 0;

	/* Don't do anything to a NULL pointer */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (NULL);
   }

	/* Ignore any spaces or TABs until end of string */
  while (pString[Index] != '\0' && (pString[Index] == ' ' || pString[Index] == 9)) {
    Index++;
   }

	/* Return pointer to the first non-whitespace char */
  return (pString + Index);
 }
/*=========================================================================
 *		End of Function lstrip()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "m_strlen()"
/*=========================================================================
 *
 * Function - size_t m_strlen (pString);
 *
 * Returns the number of characters in string up to the first Carriage
 * Return (or end of the string if no CR found).
 *
 *=======================================================================*/
size_t m_strlen (const char *pString) {
  size_t Index = 0;

	/* Make sure there is something to do */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (0);
   }

  while (pString[Index] != '\0' && pString[Index] != '\n') {
    Index++;
   }

  return (Index);
 }
/*=========================================================================
 *		End of Function m_strlen()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "PrintNumber()"
/*=========================================================================
 *
 * Function - char *PrintNumber (Number, pString);
 *
 * Prints a regular, decimal, comma delimited number to the specified
 * string.  The string must be preallocated and a minimum of 14 characters
 * in length.  Returns a pointer to the string.
 *
 *=======================================================================*/
char *PrintNumber (const unsigned long Number, char *pString) {
  unsigned long l;
  unsigned int i, j, k, m;

	/* Can't use a NULL string buffer */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (NULL);
   }

	/* Output number based on its size */
  if (Number >= 1000000000l) {
    i = (unsigned int) (Number/1000000000l);
    l = Number % 1000000000l;
    j = (unsigned int) (l/1000000l);
    l = l % 1000000l;
    k = (unsigned int) (l/1000l);
    l = l % 1000l;
    m = (unsigned int) l;
    sprintf (pString, "%d,%03d,%03d,%03d", i, j, k, m);
   }
  else if (Number >= 1000000l) {
    i = (unsigned int) (Number/1000000l);
    l = Number % 1000000l;
    j = (unsigned int) (l/1000l);
    l = l % 1000l;
    k = (unsigned int) l;
    sprintf (pString, "%d,%03d,%03d", i, j, k);
   }
  else if (Number >= 1000l) {
    i = (unsigned int) (Number/1000l);
    l = Number % 1000l;
    j = (unsigned int) l;
    sprintf (pString, "%d,%03d", i, j);
   }
  else {
    sprintf (pString, "%ld", Number);
   }

	/* Return a pointer to the string */
  return (pString);
 }
/*=========================================================================
 *		End of Function PrintNumber()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "PrintString()"
/*=========================================================================
 *
 * Function - char *PrintString (string, arg);
 *
 * Takes a variable number of arguments and prints them to a string using
 * the standard printf() format.  Returns the pointer to the string or
 * NULL on error.  An error might occur if the given string is longer than
 * 1024 characters in size.  Returned strings must be unallocated with
 * delete at some point.
 *
 *=======================================================================*/
char *PrintString (const char *pString, va_list ArgumentList) {
  char *pNewString;

	/* Ignore if nothing to print */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (NULL);
   }

	/* Allocate the new string */
  pNewString = CreateString(1025);

	/* Print the string */
  vsprintf (pNewString, pString, ArgumentList);

	/* Return the new string */
  return (pNewString);
 }
/*=========================================================================
 *		End of Function PrintString();
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "rstrip()"
/*=========================================================================
 *
 * Function - char *rstrip (char *pString);
 *
 * Strips all the whitespace characters from the right of the string.
 * Returns a pointer to the string parameter.
 *
 *=======================================================================*/
char *rstrip (char *pString) {
  register size_t Index;

	/* Don't want to do anything to a NULL pointer */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (NULL);
   }

	/* Start at the end of the string */
  Index = strlen(pString);

  while (Index != 0) {
    Index--;
		/* Terminate string and return if non-whitespace found */
    if (pString[Index] != ' ' && pString[Index] != 9) {
      pString[Index + 1] = 0;
      return (pString);
     }
   }

	/* Return an empty string */
  *pString = 0;
  return (pString);
 }
/*=========================================================================
 *		End of Functioh rstrip()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "SeperateVarValue()"
/*========================================================================
 *
 * Fuction - boolean SeperateVarValue (pString, CommentChar, SeperatorChar, ppVariable, ppValue);
 *
 * Seperate a string of the form:
 *	"Variable = Value		# Comment"
 * Returns a pointer the to Variable and value.  Parses out the comment
 * if a comment character is given and uses the given Seperator Character
 * to seperate the variable/value pair.  All leading/trailing spaces
 * are removed from the variable/value.  Returns FALSE if no variable/value
 * pair was found.
 *
 *======================================================================*/
boolean SeperateVarValue (char* pString, const char CommentChar, const char SeperatorChar, char** ppVariable, char** ppValue) {
  char* pParse;

	/* Ensure valid input */
  if (pString == NULL || ppVariable == NULL || ppValue == NULL || SeperatorChar == NULL_CHAR) {
    SET_EXT_ERROR(ERR_NULL);
    return (FALSE);
   }

	/* Remove any comments, if required */
  if (CommentChar != NULL_CHAR) {
    pParse = strchr(pString, CommentChar);
    if (pParse != NULL) *pParse = NULL_CHAR;
   }

	/* Initialize the variable pointer */
  *ppVariable = trim(pString);

	/* Look for the seperator char */
  pParse = strchr(pString, SeperatorChar);
  if (pParse == NULL) return (FALSE);
  *pParse = NULL_CHAR;

	/* Remove trailing spaces from variable */
  rtrim(*ppVariable);

	/* Remove lead spaces from value */
  *ppValue = ltrim(pParse + 1);
  return (TRUE);
 }
/*========================================================================
 *		End of Function SeperateVarValue()
 *======================================================================*/


#undef  __FUNC__
#define __FUNC__  "StringToBoolean()"
/*===========================================================================
 *
 * Function - boolean StringToBoolean (string);
 *
 * Converts a string to a TRUE/FALSE value.  The possible string values are:
 *	"TRUE", "FALSE", "0" (FALSE), Any Non-Zero Number(TRUE)
 * Anything else returns FALSE.
 *
 *=========================================================================*/
boolean StringToBoolean (const char *pString) {

	/* Make sure the string is valid */
  if (pString == NULL) return (FALSE);

	/* See if the string contains TRUE/FALSE */
  if (!stricmp(pString, "TRUE")) return (TRUE);
  if (!stricmp(pString, "FALSE")) return (FALSE);

	/* Convert the string to a number as a last resort*/
  if (atoi(pString)) return (TRUE);
  return (FALSE);
 }
/*===========================================================================
 *		End of Function StringToBoolean()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "StringChanged()"
/*===========================================================================
 *
 * Function - boolean StringChanged (const char* pString1, const char* pString2, CaseSensitive)
 *
 * Smart string compare which returns TRUE if the two strings are different.
 * Handles NULL cases and case sensitivity.
 *
 *=========================================================================*/
boolean StringChanged (const char* pString1, const char* pString2, const boolean CaseSensitive) {
 
	/* Check for NULL strings */
  if (pString1 == NULL && pString2 == NULL) return (FALSE);
  if (pString1 == NULL) return (TRUE);
  if (pString2 == NULL) return (TRUE);

	/* Compare the two valid strings depending on the case option */
  if (CaseSensitive) {
    if (strcmp(pString1, pString2) == 0) return (FALSE);
   }
  else {
    if (stricmp(pString1, pString2) == 0) return (FALSE);
   }

  return (TRUE);
 }
/*===========================================================================
 *		End of Function StringChanged()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "StringDigit()"
/*===========================================================================
 *
 * Function - boolean StringDigit (const char* pString)
 *
 * Returns TRUE if the given string is made of only of digit characters.
 * Uses the isdigit() macro/function.
 *
 *=========================================================================*/
boolean StringDigit (const char* pString) {

	/* Ensure valid input */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (FALSE);
   }

	/* Check each character in the string */
  while (*pString != NULL_CHAR) {
    if (!isdigit(*pString) && !isspace(*pString)) return (FALSE);
    pString++;
   }

  return (TRUE);
 }
/*===========================================================================
 *		End of Function StringDigit()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__  "stristr()"
/*=========================================================================
 *
 * Function - char *stristr (pString1, pSearchString);
 *
 * Searches for the search string in the target string using a case-
 * insensitive text compare.  Returns the pointer to the substring 
 * or NULL if the string was not found error.
 *
 *=======================================================================*/
char *stristr (char *pString, const char *pSearchString) {
  size_t StringIndex = 0;
  size_t SearchIndex = 0;

	/* Can't use NULL pointers */
  if (pString == NULL || pSearchString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (NULL);
   }

	/* The main search loop */
  while (pString[StringIndex] != '\0') {

    if (toupper(pString[StringIndex]) == toupper(pSearchString[SearchIndex])) {
      SearchIndex++;
      if (pSearchString[SearchIndex] == '\0') return (pString + StringIndex - SearchIndex + 1);
     }
    else if (SearchIndex != 0) {
      StringIndex -= SearchIndex;
      SearchIndex = 0;
     }

    StringIndex++;
   }

	/* Nothing found... */
  return (NULL);
 }
/*=========================================================================
 *		End of Function stristr()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "strlicmp()"
/*=========================================================================
 *
 * Function - int strlicmp (pString1, pString2);
 *
 * Compares the two strings, up to the end of the shortest string
 * (with case insensitivity).
 *
 *=======================================================================*/
int strlicmp (const char *pString1, const char *pString2) {
  int StringDifference;
  size_t Index = 0;

	/* Can't use NULL pointers */
  if (pString1 == NULL) {
    SET_EXT_ERROR(ERR_NULL);

    if (pString2 == NULL) 
      return (0);
    else
      return (-(*pString2));
   }
  else if (pString2 == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (*pString1);
   }

	/* Compare the strings up to maxlen or end of string */
  while (pString1[Index] != '\0' && pString2[Index] != '\0') {
    StringDifference = toupper(pString1[Index]) - toupper(pString2[Index]);
    if (StringDifference != 0) return (StringDifference);
    Index++;
   }

  return (0);
 }
/*=========================================================================
 *		End of Function strlicmp()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "strnncpy()"
/*=========================================================================
 *
 * Function - char *strnncpy (char *pDestString, const char *pSourceString, size_t MaxStringLegth);
 *
 * Just like the standard strncpy function but appends a NUL character
 * to the end of the destination if required.  Returns a pointer to the
 * destination string.
 *
 *=======================================================================*/
char *strnncpy (char *pDestString, const char *pSourceString, size_t MaxStringLength) {
  size_t Index = 0;

	/* Ignore any invalid Input */
  if (pDestString == NULL || pSourceString == NULL) return (pDestString);

	/* Start copying */
  while (Index < MaxStringLength && *pSourceString != '\0') {
    pDestString[Index] = *pSourceString;
    pSourceString++;
    Index++;
   }

	/* Null terminate */
  pDestString[Index] = 0;

  return (pDestString);
 }
/*=========================================================================
 *		End of Function strnncpy()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "strproper()"
/*=========================================================================
 *
 * Function - char *strproper (pString);
 *
 * Converts the specified string to proper case (first letter in each word
 * is capitalized).  Returns a pointer to the modified string.
 *
 *=======================================================================*/
char *strproper (char *pString) {
  char *pInitialString = pString;

	/* Make sure it is a valid string */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (NULL);
   }

	/* Find the next non-whitespace character */
  while (*pString != '\0') {
    pString = lstrip(pString);
    *pString = toupper(*pString);

		/* Find the next whitespace character */
    while (*pString != '\0' && *pString != ' ' && *pString != 9) {
      pString++;
     }   
   }

	/* Return the string pointer */
  return (pInitialString);
 }
/*=========================================================================
 *		End of Function strproper()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "strstr_b()"
/*=========================================================================
 *
 * Function - long strstr_b (pString, pSearchString, StringLength, SearchLength, StartIndex);
 *
 * Searches for the search string in given string using a 'binary' search
 * using the given string lengths.  Starts searching in the target string at
 * the given index.  Returns the position of the search string in the target
 * string (0 is first character) or CHARACTER_NOT_FOUND if none found.
 *
 *=======================================================================*/
long strstr_b (const char *pString, const char *pSearchString, 
	       const size_t StringLength, const size_t SearchLength, const size_t StartIndex) {
  size_t StringIndex;		/* Loop counters */
  size_t SearchIndex;

	/* Can't use NULL pointers */
  if (pString == NULL || pSearchString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (CHARACTER_NOT_FOUND);
   }

	/* Ensure string lengths allow a possible match */
  if (StringLength < StartIndex || SearchLength > StringLength - StartIndex) return (CHARACTER_NOT_FOUND);
  StringIndex = StartIndex;
  SearchIndex = 0;

	/* The main search loop */
  while (StringIndex < StringLength) {

    if (pString[StringIndex] == pSearchString[SearchIndex]) {
      SearchIndex++;
      if (SearchIndex >= SearchLength) return (StringIndex - SearchLength + 1);
     }
    else if (SearchIndex != 0) {
      StringIndex -= SearchIndex;
      SearchIndex = 0;
     }

    StringIndex++;
   }

	/* Nothing found... */
  return (CHARACTER_NOT_FOUND);
 }
/*=========================================================================
 *		End of Function strstr_b()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "strstr_bi()"
/*=========================================================================
 *
 * Function - long strstr_bi (pString, pSearchString, StringLength, SearchLength, StartIndex);
 *
 * Searches for the search string in given string using a 'binary' search
 * using the given string lengths and with case insensitivity.  Starts 
 * searching in the target string at the given index.  Returns the position
 * of the search string in the target string (0 is first character) or 
 * CHARACTER_NOT_FOUND if none found. 
 *
 *=======================================================================*/
long strstr_bi (const char *pString, const char *pSearchString, 
		const size_t StringLength, const size_t SearchLength, const size_t StartIndex) {
  size_t StringIndex;		/* Loop counters */
  size_t SearchIndex;

	/* Can't use NULL pointers */
  if (pString == NULL || pSearchString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (CHARACTER_NOT_FOUND);
   }

	/* Ensure string lengths allow a possible match */
  if (StringLength < StartIndex || SearchLength > StringLength - StartIndex) return (CHARACTER_NOT_FOUND);
  StringIndex = StartIndex;
  SearchIndex = 0;

	/* The main search loop */
  while (StringIndex < StringLength) {

    if (tolower(pString[StringIndex]) == tolower(pSearchString[SearchIndex])) {
      SearchIndex++;
      if (SearchIndex >= SearchLength) return (StringIndex - SearchLength + 1);
     }
    else if (SearchIndex != 0) {
      StringIndex -= SearchIndex;
      SearchIndex = 0;
     }

    StringIndex++;
   }

	/* Nothing found... */
  return (CHARACTER_NOT_FOUND);
 }
/*=========================================================================
 *		End of Function strstr_bi()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "w_strhgt()"
/*=========================================================================
 *
 * Function - size_t w_strhgt (pString);
 *
 * Returns the number of lines in the string (seperated by a Carriage
 * Return).
 *
 *=======================================================================*/
size_t w_strhgt (const char *pString) {
  size_t LineCount = 1;

	/* Make sure there is something to do */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (0);
   }

  while (*pString != '\0') {
    if (*pString == '\n') LineCount++;
    pString++;
   }

  return (LineCount);
 }
/*=========================================================================
 *		End of Function w_strhgt()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "w_strlen()"
/*=========================================================================
 *
 * Function - size_t w_strlen (pString);
 *
 * Finds and returns the length of the longest substring in the string
 * separated by Carriage returns.
 *
 *=======================================================================*/
size_t w_strlen (const char *pString) {
  size_t LineLength = 0;
  size_t MaxLineLength = 0;

	/* Make sure there is something to do */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (0);
   }

  while (*pString != '\0') {

    if (*pString == '\n') {
      if (LineLength > MaxLineLength) MaxLineLength = LineLength;
      LineLength = 0;
     }

    LineLength++;
    pString++;
   }
  
  if (LineLength > MaxLineLength) MaxLineLength = LineLength;
  return (MaxLineLength);
 }
/*=========================================================================
 *		End of Function w_strlen()
 *=======================================================================*/


	/* Define some functions for unix/ANSI */
#if (defined(__STDC__) || !defined(__TURBOC__)) && !defined(_WIN32)

#undef  __FUNC__
#define __FUNC__  "strlwr()"
/*=========================================================================
 *
 * Function - char *strlwr (string);
 *
 * Converts a string to lowercase.
 *
 *=======================================================================*/
char *strlwr (char *pString) {
  size_t Index = 0;

	/* Make sure there is something there to work on */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (NULL);
   }

  while (pString[Index]) {
    if (pString[Index] >= 'A' && pString[Index] <= 'Z') pString[Index] += 32;
    Index++;
   }

  return (pString);
 }
/*=========================================================================
 *		End of Function strlwr()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "strnicmp()"
/*====================================================================<====
 *
 * Function - int strnicmp (pString1, pString2, MaxStringLength);
 *
 * Compares the two strings, up to maxlen characters, and returns a value
 * based on their equality (with case insensitivity).
 *
 *=======================================================================*/
int strnicmp (const char *pString1, const char *pString2, size_t MaxStringLength) {
  int StringDiff;
  size_t Index = 0;

	/* Can't use NULL pointers */
  if (pString1 == NULL) {
    SET_EXT_ERROR(ERR_NULL);

    if (pString2 == NULL)
      return (0);
    else
      return (-(*pString2));
   }
  else if (pString2 == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (*pString1);
   } 

	/* Compare the strings up to maxlen or end of string */
  while (pString1[Index] != '\0' && pString2[Index] != '\0' && Index < MaxStringLength) {
    StringDiff = toupper(pString1[Index]) - toupper(pString2[Index]);
    if (StringDiff) return (StringDiff);
    Index++;
   }

  if (Index == MaxStringLength) return (0);
  return (toupper(pString1[Index]) - toupper(pString2[Index]));
 }
/*=========================================================================
 *		End of Function strnicmp()
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__  "strupr()"
/*=========================================================================
 *
 * Function - char *strupr (pString);
 *
 * Converts a string to upper case.
 *
 *=======================================================================*/
char *strupr (char *pString) {
  size_t Index = 0;

	/* Make sure there is something there to work on */
  if (pString == NULL) {
    SET_EXT_ERROR(ERR_NULL);
    return (NULL);
   }

  while (pString[Index] == '\0') {
    if (pString[Index] >= 'a' && pString[Index] <= 'z') pString[Index] -= 32;
    Index++;
   }

  return (pString);
 }
/*=========================================================================
 *		End of Function strupr()
 *=======================================================================*/

#endif 	/* End of if UNIX section */