/*
 * 4m v2.15 (strings.c)
 * (C) Copyright 1990 by Carrick Sean Casey
 * (C) Copyright 1993 by Scott Chasin and Michaeljon Miller
 *
 * 3-24-93 See file COPYING for copyright information.
 *
 * Miscellaneous string manipulation
 */

#include "4m.h"
#include "externs.h"
#include <varargs.h>

#ifdef SYSV
#include <string.h>
#include <sys/types.h>
#endif

extern char *charmap;

#define OKGROUPCHARS	"-.!'$+,/?_"
#define OKNICKCHARS	"-.!'$+,/?_"

#include <ctype.h>


void mprint ();
extern void build ();
extern void putl ();
extern int puts ();
char *strlwr ();

int numeric(txt)
     char *txt;
{
    for (; *txt != '\0'; txt++)
        if (!(*txt >= '0' && *txt <= '9'))
            return (0);
    return (1);
}

char *
findspace(s)
     char *s;
{
 /* find EOS or whitespace */
    while (*s != '\0' && *s != ' ' && *s != '\t')
        s++;

    if (*s == '\0')
    /* oops found no whitespace */
        return (0);
    else {
    /* point to char *after* whitespace */
        *s = '\0';
        return (++s);
    }

    /* NOTREACHED */
}

void catargs(argv)
     char **argv;
{
    char *s, *p = mbuf;

    while (*argv != NULL) {
        s = *argv;
        while (*s)
            *p++ = *s++;
        if (*(argv + 1) != NULL)
            *p++ = ' ';
        argv++;
    }
    *p = '\0';

    return;
}

/* this is a bad hack! */

void mbreakprint(per, from, s)
     int per;
     char *from;
     char *s;
{
    int count = 0;
    char *p, *lastw;
    char tmp1, tmp2;

 /* traverse s and try to break on a word */
    p = s;
    lastw = p;
    while (*p != '\0') {
        if (*p == '\n') {
            *p++ = '\0';
            mprint(per, from, s);
            count = 0;
            lastw = p;
            s = p;
            continue;
        }
        if (*p == ' ')
        /* remember location of last word break */
            lastw = p;

    /* break line if we are at max length */
        if (count == (MAX_TEXTLEN - 1)) {
            if ((p - lastw) > 40) {
            /* have to break in the middle of a word */
                tmp1 = *(p - 1);
                tmp2 = *p;
                *(p - 1) = '-';
                *p = '\0';
                mprint(per, from, s);
                *(p - 1) = tmp1;
                *p = tmp2;
                p--;
                s = p;
            } else {
            /* break at last space char */
                tmp1 = *lastw;
                *lastw = '\0';
                mprint(per, from, s);
                *lastw = tmp1;
                p = lastw + 1;
                s = p;
            }
            lastw = p;
            count = 0;
        } else {
            count++;
            p++;
        }
    }
    if (count > 0)
        mprint(per, from, s);

    return;
}

void mprint(per, from, s)
     int per;
     char *from;
     char *s;
{
    strcpy(msg_from, from);
    strcpy(msg_str, s);

    switch (per) {
        case 1:
            build(gv.p_msgformat, mbuf);
            break;
        case 0:
            build(gv.o_msgformat, mbuf);
            break;
        case 2:
            build(gv.p_echoback, mbuf);
            break;
        case 3:
            build(gv.s_msgformat, mbuf);
            break;
    }
    putl(mbuf, PL_ALL);

    return;
}

int wordcmp(s1, s2)
     char *s1;
     char *s2;
{
    while (*s1 == *s2++)
        if (*s1 == '\0' || *s1 == ' ' || *s1++ == '\t')
            return (0);
    if (*s1 == ' ' && *(s2 - 1) == '\0')
        return (0);
    return (*s1 - *--s2);
}

char *
getword(s)
     char *s;
{
    static char word[64];
    char *w = word;

    while (*s != ' ' && *s != '\t' && *s != '\0' && ((w - word) < 64))
        *w++ = *s++;
    *w = '\0';
    return (word);
}

/* Read a line containing zero or more colons. Split the string into */
/* an array of strings, and return the number of fields found. */

char *fields[MAX_FIELDS];

void split(s)
     char *s;
{
    char *p = s;
    int i = 0;

    fields[i] = s;
    for (;;) {

        i++;

    /* find delim or EOS */
        while (*p != ' ' && *p != '\0')
            p++;

        if (*p == ' ') {
        /* got delim */
            *p = '\0';
            fields[i] = ++p;
        } else
            return;
    }

    /* NOTREACHED */
}

/* cat multiple strings into one */
/* call with strscat(dest, src, src, ...) */
/* strscat(char *, char *, va_alist) */

char *
strscat(va_alist)
va_dcl
{
    char *dest, *src;
    va_list args;

    va_start(args);

 /* get the dest pointer */
    if ((dest = va_arg(args, char *)) == 0) {
        puts("fatal error: strscat called without dest");
        exit(-1);
    }
 /* copy strings */
    while ((src = va_arg(args, char *)) != NULL) {
        while (*src != '\0')
            *dest++ = *src++;
    }

    va_end(args);

    *dest = '\0';
    return (dest);
}

char *
skipword(s)
     char *s;
{
 /* skip first word */
    while (*s != ' ' && *s != '\t' && *s != '\0')
        *s++;
 /* And first space */
    *s++;
    return (s);
}

char *
get_tail(s)
     char *s;
{
 /* skip first word */
    while (*s != ' ' && *s != '\t' && *s != '\0')
        *s++;
 /* skip white space */
    while ((*s == ' ' || *s == '\t') && *s != '\0')
        *s++;
    return (s);
}

/*
 *  m a t c h
 *
 *  Determine whether the given string suitably matches
 *  given wildcard 'wild'. This has some limitations but should
 *  at this point handle most * and ? wildcard situations.
 *
 */

int 
match(wild, str)
     char *wild;
     char *str;
{
    strlwr(wild);
    strlwr(str);

    for ( /* yip */ ; /* yip */ ; wild++, str++) {
        if (*wild == '*') {
            int namlen = strlen(str);
            int matlen = strlen(wild);

            if (matlen > namlen + 1)
                return FALSE;
            else
                str = str + namlen - matlen;
        } else if (*wild != *str && *str != '?')
            return FALSE;

        else if (!*str || !*str)
            return *wild == *str;
    }
}

/*
 *  s t r l w r / s t r u p r
 *
 *  Convert a string to lower/upper case.
 *  Why doesn't BSD have this? We're wondering..
 *  This does not call lower() or upper() to save time.
 *
 */

char *
strlwr(s)
     char *s;
{
    char *save = s;

    while (s && *s) {
        if (*s >= 'A' && *s <= 'Z')
            *s += ' ';
        s++;
    }

    return save;
}

#if !defined(SUN) && !defined(SOLARIS)
/*
 * s t r d u p
 *
 * Return a duplicate string, allocating memory as we go along. Excessive use of
 * this function will result in dimished memory, Alzheimers, or worse. Is
 * there another name for this?
 *
 *
 */

char *
strdup(s)
    char *s;
{
    char *ret = (char *) malloc(strlen(s) + 1);

    strcpy(ret, s);
    return (ret);
}

#endif  /* SUN */

/*
 *  l o c a t e
 *
 *  Substring search. This returns the original part of s1 following
 *  the occurrence of s2, to allow multiple occurrences. NULL is returned
 *  if s2 is not a substring of s1.
 *
 */

char *locate (s1, s2)
  char *s1, *s2;
  {
  int len = strlen (s2);
  do {
     if (!strnicmp (s1, s2, len))
       return s1;
     }
     while (*s1++);
  return NULL;
  }
 
int scanstr(s1, s2)
char *s1, *s2;
{
    int i, max, len;

    len = strlen(s2);
    max = strlen(s1) - len;
    for (i = 0; i <= max; i++, s1++)
        {
          if (!strnicmp(s1, s2, len))
              return (i + 1);
        }
    return (0);
}


#if defined(SOLARIS) || defined(DGUX) || !defined(strnicmp)

int strnicmp(s1, s2, n)
    char *s1, *s2;
    int n;
{
    register char c1, c2;
 
    while (--n >= 0) {
        c1 = lower(*s1);
        c2 = lower(*s2);
 
        if (!c1 || c1 != c2)
            return c1 - c2;
 
        s1++;
        s2++;
    }
 
    return 0;
}

#endif /* SOLARIS */
