/*
 * this file is a part of yabbs - yet another bulletin board system.
 * Copyright (C) 1993, 1994 Alex Wetmore.  
 * email: alex@phred.org
 * address: 6 rech ave
 *          oreland pa 19075
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 * unix.c - part of the yabbs bulletin board package by alex wetmore
 *          see bbs.c for information on the system and copying.
 */

#include "bbsdefs.h"
#ifdef TERMIO
#include <termio.h>
#else
#ifdef SGTTYB
#include <sgtty.h>
#else
#error "either TERMIO or SGTTYB must be #defined to compile this file"
#endif
#endif
#include <sys/ioctl.h>

char    termcap[1024],                      /* termcap info             */
        t_clrscr[33],                       /* code to clear screen     */
        t_hion[33],                         /* code to start highlight  */
        t_hioff[33],                        /* code to end highlight    */
        t_cleol[81],                        /* code to clear line       */
        t_upcur[33],                        /* code to go up a line     */
        termname[33];                       /* name of terminal         */

#ifdef TERMIO
struct  termio term, save;                  /* terminal modes (termio)  */
#else
#ifdef SGTTYB
struct  sgttyb term, save;                  /* terminal modes (sgtty)   */
#endif
#endif

#ifndef STDIN
#define STDIN 0
#endif

/*
 * helper function for t_puts()
 */
int putch(int c) {
    return fputc(c, stdout);
}

/*
 * put a character to the users screen without any processing (used to put
 * escape sequences for term stuff).
 */
void t_puts(char *tstr) {
    tputs(tstr, 1, putch);
    fflush(stdout);
}

/*
 * Clear the screen
 */
void clearscreen(void) {
    t_puts(t_clrscr);
}

/*
 * clear to the end of the current line
 */
void clearline(void) {
    t_puts(t_cleol);
}

/*
 * turn on highlighting
 */
void hion(void) { 
    t_puts(t_hion); 
}

/*
 * turn off highlighting
 */
void hioff(void) { 
    t_puts(t_hioff); 
}

/*
 * move the cursor up one row
 */
void up(void) {     
    t_puts(t_upcur); 
}

/*
 * helper function for readc
 */
char inkey(void) {
    unsigned char ch;

    if (read(STDIN, &ch, 1) != 1) {
        /* an error in reading means that we should just close the      */
        /* connection                                                   */
        killconnection(K_FERR_NW);
    }

    return ch;
}

/*
 * read one character from the user but dont process commands from the server
 */
char readc_pause(void) {
    unsigned char ch;
    int readkey = FALSE;

    while (!readkey) {
        line = 1;
        ch = inkey();
        if ((ch == 4)) {
            if (ynprompt("\n\nDo you want to logout? [yN] ", FALSE)) {
                killconnection(K_USER);
            } else {
                readkey = FALSE;
            }
        } else if (((ch >= 32) && (ch <= 127)) || (ch == 21) ||
                   (ch == 10) || (ch == 13) || (ch == '\t') || (ch == 8)) {
            return ch;
        } else {
            readkey = FALSE;
        }
    }
}

/*
 * read one character from the user and process commands from the server
 */
char readc(void) {
    unsigned char ch;
    int readkey = FALSE, readstdin = FALSE, readbbs_s;
    fd_set fds;

    while (!readkey) {
        readbbs_s = FALSE;

        FD_ZERO(&fds);
        FD_SET(STDIN, &fds);
        FD_SET(bbs_s, &fds);

        while (select(bbs_s+1, &fds, NULL, NULL, NULL) == -1);
        if (FD_ISSET(bbs_s, &fds)) readbbs_s = TRUE;
        if (FD_ISSET(STDIN, &fds)) readstdin = TRUE;
    
        if (readbbs_s) {
            bbs_handlemsg();                /* read and deal with packet    */
        }
        if (readstdin) {
            line = 1;
            ch = inkey();
            if ((ch == 4)) {
                if (ynprompt("\n\nDo you want to logout? [yN] ", FALSE)) {
                    killconnection(K_USER);
                } else {
                    readkey = FALSE;
                }
            } else if (((ch >= 32) && (ch <= 127)) || (ch == 21) ||
                       (ch == 10) || (ch == 13) || (ch == '\t') || (ch == 8)) {
                return ch;
            } else {
                readkey = FALSE;
            }
        }
    }
    /* should never be reached */
    assert(FALSE);
    return 0;
}

/*
 * write one character to the user
 */
void writec(char c) {
    if (((c >= 32) && (c < 127)) || 
        (c == 27) ||
        (c == 10) || 
        (c == 13) ||
        (c == 8) ||
        (c == 7)) fputc(c, stdout);
}

/*
 * initialize the terminal.  this would open a window on a windowing system,
 * etc.  called before anything is printed to the screen.
 */
void terminit(void) {
}

/*
 * get the terminal type and other information.  
 */
void getterm(void) {
    char buf[80], **area;
    int  i;

    strcpy(termname, getenv("TERM"));
    if (!getfromenv("DontAskTermType", buf)) {
        sputs("If you don't know your terminal type, enter \"none\" at the next prompt.\n");
        sputs("Hit enter to accept the default type (in []'s).\n");
        i = FALSE;
        sprintf(buf, "What is your terminal type? [%s] ", termname); sputs(buf);

        sgets(buf, 32);

        if ((strcmp(buf, "none") == 0) || 
              (strcmp(buf, "unknown") == 0) || 
              (strcmp(buf, "dumb") == 0)) {
            strcpy(termname, "none");
        } else if (buf[0] != 0) {
            strcpy(termname, buf);
        }
    } 

    if (strcmp(termname, "none") == 0) {
        sputs("\nUsing dumb terminal\n\n\n\n\n\n"); 
        strcpy(t_cleol, "                                                                              \r");
        *t_clrscr = 0;
        *t_hion = 0;
        *t_hioff = 0;
        *t_upcur = 0;
    } else if (tgetent(termcap, termname) != 1) {
        sputs("\nThere is no termcap entry for you terminal, using no terminal features\n\n\n\n\n\n\n");
        strcpy(t_cleol, "                                                                              \r");
        strcpy(termname, "none");
        *t_clrscr = 0;
        *t_hion = 0;
        *t_hioff = 0;
        *t_upcur = 0;
    } else {
        area = malloc(sizeof(area));
        area[0] = malloc(sizeof(char) * 1024);
        strcpy(t_clrscr, tgetstr("cl", area));
        if (tgetstr("cl", area) != NULL) strcpy(t_clrscr, tgetstr("cl", area));
        else *t_clrscr = 0;
        if (tgetstr("md", area) != NULL) {
            strcpy(t_hion, tgetstr("md", area));
            strcpy(t_hioff, tgetstr("me", area));
        } else *t_hioff = *t_hion = 0;
        if (tgetstr("ce", area) != NULL) strcpy(t_cleol, tgetstr("ce", area));
        else *t_cleol = 0;
        if (tgetstr("up", area) != NULL) strcpy(t_upcur, tgetstr("up", area));
        else *t_upcur = 0;
    }
    t_puts(t_cleol);
    writec('\n');
}

/*
 * gets called when the terminal is no longer needed.
 */
void termclose(void) {
}

/*
 * disable echo on the tty device
 */
void echooff(void) {
#ifdef TERMIO
    /* Get terminal modes.                                              */
    ioctl(2, TCGETA, &term);

    /* Save modes and set certain variables dependent on modes.         */
    save = term;

    /* Set the modes to the way we want them.                           */
    term.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
    term.c_oflag |=  (OPOST|ONLCR|TAB3);
    term.c_oflag &= ~(OCRNL|ONOCR|ONLRET);
    term.c_cc[VMIN] = 1;
    term.c_cc[VTIME] = 0;

    /* set the new modes                                                */
    ioctl(2, TCSETAW, &term);
#else
#ifdef SGTTYB
    /* Get terminal modes.                                              */
    ioctl(2, TIOCGETP, &term);

    /* Save modes and set certain variables dependent on modes.         */
    save = term;

    /* Set the modes to the way we want them.                           */
    term.sg_flags |= CBREAK;
    term.sg_flags &= ~(ECHO|XTABS);
            
    /* set the new modes                                                */
    ioctl(2, TIOCSETN, &term);
#endif
#endif
}

/*
 * enable echo on the tty device
 */
void echoon(void) {
#ifdef TERMIO
    ioctl(2, TCSETAW, &save);
#else
#ifdef SGTTYB
    ioctl(2, TIOCSETN, &save);
#endif
#endif
}

char *yabbssystype(void) {
    static char *systype = "unix/posix";
    return systype;
}

char *cli_hiddenyabbsrcname(void) {
    static char *yabbsrc = ".yabbsrc";
    return yabbsrc;
}

char *cli_yabbsrcname(void) {
    static char *yabbsrc = "yabbsrc";
    return yabbsrc;
}
