/*
 * 4m v2.15 (getline.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.
 *
 * Input and line editing
 */

#include "4m.h"
#include "externs.h"
#include "../h/term.h"

#include <varargs.h>

#ifdef HAS_STRING
# include <string.h>
#endif

#ifdef HAS_STRINGS
# include <strings.h>
#endif

#include <ctype.h>

int count;
char *p;
int userchars;  /* chars user has typed - not same as # of chars in line */


extern int write ();
extern int _filbuf ();
int specialchar ();
void inserttab ();
extern int histcount ();
extern char *histget ();
extern char *strscat();
/* extern char *strscat(char *, char *, va_alist); */


int getline(s, prompt, expand)
     char *s;
     char *prompt;
     int expand;
{
    register int c;
    char cc;

    linenumber = 0; /* reset line number for paging */
    userchars = 0;  /* reset user char count */

    if (prompt)
        write(1, prompt, strlen(prompt));

    p = s;
    count = 0;

    for (;;) {
        c = getchar();

    /* reset if we were restarted */
        if (continued) {
            continued = 0;
            p = s;
            count = 0;
        }
    /* regular ascii */
        if (c > '\037' && c < '\177') {
            if (count == (MAX_INPUTSTR - 1)) {
                write(1, "\007", 1);
                continue;
            }
            *p++ = (char) c;
            count++;
            userchars++;
            cc = c;
            write(1, &cc, 1);
        } else {
            register int num = specialchar(c, s, prompt, expand);

            if (num < 0)
                continue;
            else
                return (num);
        }
    }
}

int specialchar(c, s, prompt, expand)
     register int c;
     char *s;
     char *prompt;
     int expand;
{
    if (c == '\t') {
    /* space to next tabstop */
        if (userchars) {
            inserttab();
            return (-1);
        }
    /* TAB - enter personal message line */
        if (!expand || histcount() == 0)
            return (-1);

    /* beginning of line */
        if (!count) {
            sprintf(s, "%cm %s ",
                    gv.cmdchar, histget());
            count = strlen(s);
            p = s + count;
            write(1, s, count);
        /* middle of line */
        } else {
            int l;
            char *n = mbuf;

            while (count && isspace(*(p - 1))) {
                p--, count--;
                n = strscat(n, "\b \b", NULL);
            }
            while (count && !isspace(*(p - 1))) {
                p--, count--;
                n = strscat(n, "\b \b", NULL);
            }
            write(1, mbuf, n - mbuf);
            sprintf(p, "%s ", histget());
            l = strlen(p);
            write(1, p, l);
            count = count + l;
            p = s + count;
        }
    }
 /* redraw line */
    else if (c == ttyinfo.redraw) {
        if (count) {
            *p = '\0';
            write(1, "\r\n", 2);
            if (prompt)
                write(1, prompt, strlen(prompt));
            write(1, s, strlen(s));
        }
    }
 /* kill line */
    else if (c == ttyinfo.kill) {
        char *end = mbuf;

        while (count) {
            end = strscat(end, "\b \b", NULL);
            p--, count--;
        }
        write(1, mbuf, end - mbuf);
        *s = '\0';
        if (!prompt)
            return (0);
    }
 /* delete word */
    else if (c == ttyinfo.werase) {
        char *end = mbuf;

        while (count && isspace(*(p - 1))) {
            p--, count--;
            end = strscat(end, "\b \b", NULL);
        }
        while (count && !isspace(*(p - 1))) {
            p--, count--;
            end = strscat(end, "\b \b", NULL);
        }
        write(1, mbuf, end - mbuf);
        if (!count) {
            *s = '\0';
            if (!prompt)
                return (0);
        }
    }
 /* erase character */
    else if (c == ttyinfo.erase || c == '\177' || c == '\b') {
        if (count) {
            write(1, "\b \b", 3);
            p--, count--;
        }
        if (!count) {
            *s = '\0';
            if (!prompt)
                return (0);
        }
    }
 /* new line */
    else if (c == '\n') {
        if (!count)
            *p = '\n';
        else
            *p = '\0';
        write(1, "\r\n", 2);
        if (!dumb)
            clear_eol();
        return (count);
    }
    return (-1);
}


void inserttab()
{
    char *wp = p;

    if (count == (MAX_INPUTSTR - 1)) {
        write(1, "\007", 1);
        return;
    }

    if ((count % 8) == 0) {
        *p++ = ' ';
        count++;
    }

    while ((count % 8) != 0) {
        if (count == (MAX_INPUTSTR - 1))
            return;
        *p++ = ' ';
        count++;
    }

    *p = '\0';
    write(1, wp, strlen(wp));

    return;
}
