/* truncate.c (rsxnt) -- Copyright (c) 1996-1997 Rainer Schnitker */

#include "rsxnt.h"

#define TRUNC_UNC       (1 << 0)
#define TRUNC_DRV(c)    (1 << ((c) & 0x1f))
#define TRUNC_ALL       (~0)

void _rsxnt_truncate_name (char *dst, const char *src)
{
    int dst_count;
    unsigned trunc_bit;
    EMXPROCESS *p = _rsxnt_get_process_ptr();
    char *slash = dst;

    dst_count = 512 - 1;

    trunc_bit = TRUNC_ALL;

    if (src[0] == '/' || src[0] == '\\') {
        if (src[1] == '/' || src[1] == '\\') {
            /* It's a UNC path: don't prepend drive letter; check `-t/'. */
            trunc_bit = TRUNC_UNC;
        }
        else if (_rsxnt_dir_check (src + 1, "dev") || _rsxnt_dir_check (src + 1, "pipe")) {
          trunc_bit = 0;
        }
        else if (p->rsxnt_opt.defdisk != 0) {
            /* Prepend drive letter; check `-t' for that drive letter. */
            *dst++ = p->rsxnt_opt.defdisk;
            *dst++ = ':';
            dst_count -= 2;
            trunc_bit = TRUNC_DRV (p->rsxnt_opt.defdisk);
        }
    }
    else if (((src[0] >= 'A' && src[0] <= 'Z') || (src[0] >= 'a'
            && src[0] <= 'z')) && src[1] == ':')
        trunc_bit = TRUNC_DRV (src[0]);

    if (p->rsxnt_opt.truncate & trunc_bit) {
        unsigned char rest, dot;

        rest = 8; dot = FALSE;
        while (*src != 0 && dst_count != 0) {
            if (*src == ':' || *src == '/' || *src == '\\') {
                *dst++ = *src;
                --dst_count;
                rest = 8; dot = FALSE;
            }
            else if (*src == '.') {
                if (rest == 8) {
                    for (;;) {
                        *dst++ = *src;
                        --dst_count; --rest;
                        if (src[1] != '.' || dst_count == 0)
                            break;
                        ++src;
                    }
                }
                else if (dot) {
                    /* If the element has two or more dots, truncate at
                        the second dot.  This does not apply to ".."
                        which is handled above. */
                    rest = 0;
                }
                else {
                    /* Start of a suffix. */
                    rest = 3; dot = TRUE;
                    *dst++ = *src;
                    --dst_count;
                }
            }
            else if (rest != 0) {
                /* Copy an ordinary character unless the truncation
                    limit (8 or 3 characters) has been reached. */

                *dst++ = *src;
                --dst_count; --rest;
            }
            ++src;
        }
    }
    else {
        /* The -t option is not used, don't truncate the file name to
           8.3 format (however, truncate it to avoid overflowing the
           destination buffer. */

        /* fix for root dirs (makeinfo) with two slashes */
        if (src[0] == '/' && src[1] == '/' && strchr(src+2, '/') == NULL)
          ++src;

        while (*src != 0 && dst_count != 0) {
            *dst++ = *src++;
            --dst_count;
        }
    }

    /* Add the terminating null character. */
    *dst = 0;


    /* rsxnt additionals */

    if (p->rsxnt_opt.truncate & trunc_bit)
        CharUpper (slash);
    while ((slash = strchr(slash, '/')))
        *slash++ = '\\';
}
