/* Copyright (c) 2002
 *	Marko Boomstra (m.boomstra@chello.nl).  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
#include <conf.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <ctype.h>
#include <ncurses.h>
#include <panel.h>
#include "mudix.h"

/*
 * Externals
 */
extern 	time_t	current_time;
extern  char    connect_name[];
extern  int     statusTimer;

/*
 * Locals
 */
SCROLL *scrollbuf;
int     current_line = 0;
int     first_line = 0;
int     pos = 0;

void scroll_setup(int lines)
{
    int i;

    scrollbuf = (SCROLL *)calloc(sizeof(SCROLL), lines);
    for(i=0; i<MAX_LINES; i++) {
	scrollbuf[i].data = (char *)malloc(LEN_COL*sizeof(char));
	scrollbuf[i].attr = (int *)malloc(LEN_COL*sizeof(int));
    }
}

void draw_border(WINDOW *win) 
{
    wborder(win, ACS_VLINE, ACS_VLINE, ACS_HLINE, ACS_HLINE, ACS_ULCORNER,
                 ACS_URCORNER, ACS_LLCORNER, ACS_LRCORNER);
    return;
}

void do_status(char *string, int st_time)
{
    char *time;

    if (!fStatusReport)
	return;

    time = ctime(&current_time);
    time[strlen(time)-1] = '\0';
    wscrl(wStatus, 1);
    mvwprintw(wStatus, 6, 1, "%s: %s", time, string);
    wclrtoeol(wStatus);
    draw_border(wStatus);
    mvwaddstr(wStatus, 0, 3, "MUDix Status");
    show_panel(pStatus);
    statusTimer = st_time;
    return;
}

void create_banner(void) 
{
           TRIGGER *login;
    static char     site[40];
    static char     banner[MAX_STRING];
	   char    *pBan = banner;

    if (panel_hidden(pBanner) == PANEL_HIDDEN)
	return;

    if (connect_name[0])
	sprintf(site, "%s %d", connect_name, settings->port);
    else
	sprintf(site, "Not connected");

    login = trig_lookup(NULL, TRG_LOGIN);
    pBan += sprintf(banner, "MUDix v"VERSION" # %-10s (%s)",   
	    			login? login->out: "M.Boomstra", site);

    while ((pBan-banner) < LEN_COL) {
	*pBan++ = ' ';
	if (fPrintTime && ((LEN_COL-24) <= (pBan-banner))) {
	    sprintf(pBan, "%24s", ctime(&current_time)); 
            break;
	}
    } 
    
    mvwprintw(wBanner, 0, 0, "%s", banner); 
    return;
}

void print_cmd_line(void)
{
    werase(wInput);
    if (pCursor >= (LINE_LENGTH + inbuf)) {
    	mvwaddnstr(wInput, 0, 0, pCursor-LINE_LENGTH, LINE_LENGTH); 
    }
    else
	mvwaddnstr(wInput, 0, 0, inbuf, pEndIn-inbuf);

    return;
}

void move_cursor(WINDOW *win, int direction, int value) {
    int x, y;

    getyx(win, y, x);
    switch(direction) {
        case UP:
	    y -= value;
	    if (y < 0)
		y = 0;	
            break;
        case DOWN:
	    y += value;
	    if (y > (LEN_ROW-2))
		y = (LEN_ROW-2);
            break;
        case LEFT:
	    x -= value;
	    if (x < 0)
		x = 0;
            break;
        case RIGHT:
	    x += value;
	    if (x > LINE_LENGTH)
		x = LINE_LENGTH;
            break;
        default:
            break;
    }

    wmove(win, y, x);
    return;
}

void print_to_eol(void)
{
    waddnstr(wInput, pCursor, LINE_LENGTH - (pCursor - inbuf));
    return;
}

void backspace(void)
{
    move_cursor(wInput, LEFT, 1);
    wdelch(wInput);
    return;
}

void put_in_scroll(char *pBegin, char *pEnd, int attr)
{
    char *pTmp = pBegin;
    int   i;

    while (pTmp != pEnd && *pTmp) {
        if (isprint(*pTmp)) {
       	    scrollbuf[current_line].data[pos] = *pTmp;
            scrollbuf[current_line].attr[pos] = attr;
	    pos++;
        }
	else if (*pTmp == TAB) {
	    for (i=0; i<TAB_LEN; i++) {
       	        scrollbuf[current_line].data[pos] = ' ';
                scrollbuf[current_line].attr[pos] = attr;
	        pos++;
		if (pos >= LEN_COL || !(pos%TAB_LEN))
		    break;
	    }
	}

	if (pos >= LEN_COL || *pTmp == '\n') {
	    scrollbuf[current_line].len = pos;
	    pos = 0;
	    if (current_line++ == MAX_LINES-1)
	    	current_line = 0;
	    if (current_line == first_line)
		first_line = -1;
	}
	pTmp++;
    }

    write_log(pBegin, pTmp);
 
    return;
}

void show_scroll(int direction, int scroll_size)
{
    static int  pline;
    	   int  i=0, j, x;

    if (panel_hidden(pScroll) == PANEL_HIDDEN)
	pline = current_line;

    switch (direction) {
	case UP:
	    while (i++ < scroll_size) {
		if (pline == first_line)
		    break;

                if (pline == 0)
                    pline = MAX_LINES;
		pline--;

		if (pline == current_line) {
		    if (++pline == MAX_LINES) {
			pline = 0;
			break;
		    }
		}
            } 

	    werase(wScroll);
            for (i=pline, j=0; j<SCROLL_SIZE; j++, i++) {
		if (i == MAX_LINES)
		    i = 0;

	    	for (x=0; x < scrollbuf[i].len; x++) {
		    wattrset(wScroll, scrollbuf[i].attr[x]);
		    mvwaddch(wScroll, j, x, scrollbuf[i].data[x]);
		}
	    }

            wattrset(wScroll, A_BOLD|COLOR_PAIR(COL_SCRL_BANNER));
	    mvwhline(wScroll, SCROLL_SIZE, 0, ACS_HLINE, LEN_COL); 
	    mvwaddstr(wScroll, SCROLL_SIZE, 1, "Scrollback buffer (Page Up/Down and Arrow Up/Down to move, ESC to go back)"); 
            wattrset(wScroll, A_NORMAL|COLOR_PAIR(0));
	    show_panel(pScroll);
	    break;
	case DOWN:
    	    if (panel_hidden(pScroll) == PANEL_HIDDEN)
		break;

	    i = pline+scroll_size;
	    if (i >= MAX_LINES)
		i -= MAX_LINES;

	    pline = i;
	    for (j=0; j<SCROLL_SIZE; j++, i++) {
		if (i == MAX_LINES)
		    i = 0;

		if (i==current_line) {
		    /* backup pline with SCROLL_SIZE-j */
		    for (i=0; i<(SCROLL_SIZE-j); i++, pline--) {
			if (pline == first_line)
		    	    break;

			if (pline == 0)
			    pline = MAX_LINES-1;
		    }
		    break;
		}    
	    }
 
	    werase(wScroll);
            for (i=pline, j=0; j<SCROLL_SIZE; j++, i++) {
		if (i == MAX_LINES)
		    i = 0;

		for (x=0; x<scrollbuf[i].len; x++) {
		    wattrset(wScroll, scrollbuf[i].attr[x]);
		    mvwaddch(wScroll, j, x, scrollbuf[i].data[x]);
		}
	    }

            wattrset(wScroll, A_BOLD|COLOR_PAIR(COL_SCRL_BANNER));
	    mvwhline(wScroll, SCROLL_SIZE, 0, ACS_HLINE, LEN_COL); 
	    mvwaddstr(wScroll, SCROLL_SIZE, 1, "Scrollback buffer (Page Up/Down and Arrow Up/Down to move, ESC to go back)"); 
            wattrset(wScroll, A_NORMAL|COLOR_PAIR(0));
	    show_panel(pScroll);
	    break;
	default:
	    break;
    }

    return;
}

void dialog(char *string)
{
    werase(wDialog);
    mvwaddstr(wDialog, 1, (LEN_COL-strlen(string))/2, string);
    draw_border(wDialog);
    show_panel(pDialog);
 
    return;
}

void do_help(void)
{
    wresize(wMsg, 21, LEN_COL-16);
    werase(wMsg);
    move_panel(pMsg, 1, 8);
    if (panel_hidden(pMsg) == PANEL_HIDDEN) {
    	mvwprintw(wMsg,  1, 1, "Alt+a Toggle status reports");
    	mvwprintw(wMsg,  2, 1, "Alt+c Create user settings");
    	mvwprintw(wMsg,  3, 1, "Alt+h This help window (press Alt+h to see #-commands)");          
    	mvwprintw(wMsg,  4, 1, "Alt+i Toggle input echo");
    	mvwprintw(wMsg,  5, 1, "Alt+k Toggle keypad walking");     
    	mvwprintw(wMsg,  6, 1, "Alt+m Toggle character mode");     
    	mvwprintw(wMsg,  7, 1, "Alt+o Toggle output echo");
    	mvwprintw(wMsg,  8, 1, "Alt+p Toggle time display");
    	mvwprintw(wMsg,  9, 1, "Alt+q Quit MUDix");
    	mvwprintw(wMsg, 10, 1, "Alt+r Reconnect");
    	mvwprintw(wMsg, 11, 1, "Alt+s Show user settings");
    	mvwprintw(wMsg, 12, 1, "Alt+t Toggle a trigger (enable/disable)");
    	mvwprintw(wMsg, 13, 1, "Alt+1 Show triggers");
    	mvwprintw(wMsg, 14, 1, "Alt+2 Show name aliases");
    	mvwprintw(wMsg, 15, 1, "Alt+3 Show paths");
    	mvwprintw(wMsg, 16, 1, "Alt+4 Show tab completions");
    	mvwprintw(wMsg, 17, 1, "Alt+5 Show variables");
    	mvwprintw(wMsg, 18, 1, "      Page  UP/DOWN, scroll through scroll-log");
    	mvwprintw(wMsg, 19, 1, "      Arrow UP/DOWN, scroll through command history");
    }
    else {
        int i = 0;
	extern struct cmd_table_type cmd_table[];

	while (cmd_table[i].cmd) {
	    mvwprintw(wMsg, i+1, 1, "#%-15s %s", cmd_table[i].cmd, 
						 cmd_table[i].help+8); 
	    i++;
	}
    }

    draw_border(wMsg);
    mvwaddstr(wMsg, 0, 3, "MUDix Help -- MUDix "VERSION" by M. Boomstra");
    mvwaddstr(wMsg, 20, 3, "ESC: close window, Alt+h: show #-commands");
    show_panel(pMsg);

    return;
} 


syntax highlighted by Code2HTML, v. 0.9.1