/***********************
 * FILE: GRAEMEUTILS.C *
 ***********************/

#include <stdio.h>
#include <string.h>
#include <ctype.h>

    /*  Authors:      Graeme B. Boyd, Michael A. Campbell 
     *  Revised Date: 16 Sep 2004
     *
     */

#include "../def/common.def"
#include "../str/vestruct.str"


void insert (spaces, str)

    char *str;
    int spaces;

{

    char *pt;

    for(pt=str; *pt != '\0'; pt++) ;    /* find end of string */
    while(pt > str)
        *(pt-- + spaces) = *pt;         /* move string        */

    for(pt++; spaces > 0; spaces--)
        *pt++ = ' ';                    /* put in spaces      */

}



int next_tab (position, tab_distance)

    int position, tab_distance;

{

    int tab;
    
    tab = position;
    while(tab >= tab_distance) tab -= tab_distance; 

    return (position + (tab_distance - tab));
}

/* .page */


void del_char (pt)

    char *pt;

{

    while(*pt++ = *(pt+1));
}

/* .page */

int pack (str, str_length, tab)

    /*  This routine pack's the string pointed to
     *  by "str". The output is left in the input
     *  string. The new length of the string is returned.
     */

    char *str;
    int  str_length, tab;

{

    char *pt;
    int count,space;

    pt = str + str_length;
    *pt =  '\0';             /* put in end of string: VE doesn't have one   */


    /*  Kill any white space at the end of the line */

    for (pt--; pt >= str; pt--)
        if(isspace(*pt))    /* if tab or space at end */
            *pt = '\0';     /* of line kill it        */
        else
            break;          /* else found data, leave */


    for (count=space=0, pt=str; *pt != '\0'; count++, pt++) {

        if(isspace(*pt)) {

            if(*pt == '\t'){    /* if tab update count */
                count = next_tab(count, tab) - 1;
                space = 0;      /* and reset space    */
            }

            else {          /* else must be a space   */

                    space++;

                    if(count == next_tab(count, tab) - 1) {
                        *(pt - --space) = '\t';
                        for(count--; space; del_char(pt-- - --space)) ;
                        pt--;
                    }
                }
        }
        else
            space = 0;      /* else must be a char so reset space */

    }
            
    return (strlen (str));  /* return output string length */
}

/* .page */

int unpack (str, str_length, tab)

    /*
     *  This routine unpack's the string pointed to
     *  by "str". The output is left in the input
     *  string. The ouput string length is returned.
     */

    char *str;
    int  str_length, tab;

{

    char *pt;
    int count,space;

    pt = str + str_length;
    *pt = '\0';            /* put in string end */

    for (count=0, pt=str; (*pt != '\0' && count < (254 - tab) ); count++, pt++) {

        if(*pt == '\t'){    /* if tab expand     */
            *pt = ' ';      /* make into a space */

            if((space = next_tab(count, tab) - (count + 1)))
                insert(space, pt);  /* insert spaces if needed */
        }
    }

    return (strlen (str));      /* return string length */

}

/* .page */

int white_space (line_ptr)

    /*
     *  This routine determines the amount of white 
     *  space at the head of a line, and returns 
     *  the number of white space chars found, or 0,
     *  if no white space was found.
     */

    struct node *line_ptr;

{

    int i = 0, space = 0, valid = FALSE;

    if (line_ptr->length) {

        /*  Do until the line is exhausted or a valid (non white space) char  */
        /*  is found.                                                         */

        while( (i < line_ptr->length) && !valid ) {

            if (isspace (line_ptr->text[i++]) )
                space++;
            else
                valid = TRUE;

        }

    }

    return (space);

}

/* .page */

int kill_trailing_white_space (str, str_length)

    /*  This routine removes any trailing white space at the end of 
     *  the string pointed to by str.
     */

    char *str;
    int  str_length;

{

    char *pt;
    int count,space;

    pt = str + str_length;
    *pt =  '\0';             /* put in end of string: VE doesn't have one   */


    /*  Kill any white space at the end of the line */

    for (pt--; pt >= str; pt--)
        if(isspace(*pt))    /* if tab or space at end */
            *pt = '\0';     /* of line kill it        */
        else
            break;          /* else found data, leave */

    return ( strlen(str) );
}

/* .page */

int compress_white_space ( str, len )

/* This routine compresses all of the white space in a line, such that
 * any leading or trailing white space is eliminated, and consecutive
 * runs of white space are reduced to a single white space character
 */

char str [];  /* input string - not zero terminated */
int len;      /* the length of the string           */

{
   int read_ix, write_ix;

   str[len] = '\0';
   read_ix = write_ix = 0;

   while ( str[read_ix] != '\0' )
      if ( str[read_ix] == ' ' && str[read_ix+1] == ' ' )
         read_ix += 1;
      else
         if ( str[read_ix] == ' ' && write_ix == 0 )
            read_ix += 1;
         else
            str[write_ix++] = str[read_ix++];

   if ( str[write_ix - 1] == ' ' )  /* Check for, delete trialing ' ' */
      write_ix -= 1;
   str[write_ix] = '\0';            /* terminate the string           */

   return ( write_ix );

}

