/*
  Chat mode processing

  written by Song Jaekyung
*/

#include "background.h"
#include "ptyx.h"
#include "data.h"
#include "error.h"
#include "hangul.h"
#include <stdio.h>
#include <X11/keysym.h>

#define MAXCHATBUF 1024
#define CHAT_START_X 19

extern void ShowCursor();
extern void HideCursor();

extern int (*converter)();
extern int convert_3_to_johab();
extern int convert_3_to_ks();

int (*chat_callback)();
int chat_mode;
static int chat_x;
static Char *chat_p, *chat_startp, *chat_buf = NULL, *chat_prompt;

/* chat_buf : Ã¤ÆÃ ¸ðµå ¹®ÀÚ¿­À» ±â¾ïÇÏ´Â ¹öÆÛ
   chat_p : ¹®ÀÚ¿­ÀÇ ¸¶Áö¸·À» °¡¸®Å²´Ù.
   chat_startp : ½ºÅ©·Ñ µÆÀ» ¶§ Ã³À½À» °¡¸®Å²´Ù.
*/

toggle_chat_mode(str)
    unsigned char *str;
{
    HideCursor();
    if (chat_mode)
	chat_flush(0);
    else
	unparseputc(-2, term->screen.respond);
    chat_mode ^= 1;
    if (chat_mode) {
	chat_x = strlen((char*)str) + CHAT_START_X;
	if (chat_buf == NULL) {
	    chat_buf = (Char *)calloc((unsigned)MAXCHATBUF, sizeof(Char));
	    if (chat_buf == NULL) {
		fprintf(stderr, "%s: can't allocate chat buf\n", xterm_name);
		Cleanup(ERROR_SCALLOC);
	    }
	}
	strcpy((char*)chat_buf, (char*)str);
	chat_startp = chat_buf;
	chat_prompt = chat_p = (Char*)strchr((char*)chat_buf, '\0');
	converter = convert_3_to_johab;
	show_chat_buf();
    } else {
	if (term->screen.code == C_WANSUNG) {
	    converter = convert_3_to_ks;
	}
    }
    ShowCursor();
}

chat_mode_input(keysym, event, string, nbytes)
    KeySym keysym;
    XKeyEvent *event;
    Char *string;
    int nbytes;
{
    Char *org_p;
    int n;
    int tmp_han;

    chat_hide_cursor();
    org_p = chat_p;
    tmp_han = temp_hangul[0];
    if (keysym == -1 || keysym == -2) {
	n = hangul_automata(keysym, chat_p);
	chat_p += n;
    }
    else if (nbytes > 0) {
	while (nbytes-- > 0) {
	    if (chat_p - chat_buf < MAXCHATBUF - 10) {
		n = hangul_automata(*string, chat_p);
		chat_p += n;
	    }
	    else
		n = 1;
	    if (n > 0)
		switch (*string) {
		case 13:	/* return */
		    chat_flush(0);
		    break;
		case 8:		/* back space */
		    chat_backspace();
		    break;
		case 0177:	/* delete */
		    if (tmp_han)
			chat_x += 2;
		    chat_backspace();
		    break;
		case 025:	/* ctrl-u */
		    chat_clear();
		    break;
		case 027:	/* ctrl-w */
		    chat_delete_word();
		    break;
		case 033:	/* escape */
		    chat_flush(1);
		    break;
		default:
		    if (chat_p - 1 == chat_buf && *string < ' ')
			chat_control();
		    break;
		}
	    string++;
	}
    }
    if (chat_p > org_p) {
	if (chat_x + (chat_p - org_p) <= term->screen.max_col)
	    draw_chat_buf(org_p, chat_p - org_p);
	chat_x += chat_p - org_p;
	if (chat_x > term->screen.max_col)
	    chat_scroll_left();
    }
    if (chat_mode) {		/* chat_flush can make chat_mode = 0 */
	chat_show_cursor();
    }
}

void input_to_chat(str, len)
    Char *str;
    int len;
{
    Char *org_p, *p, *q;
    int n;

    org_p = chat_p;

    if (chat_p < chat_buf + MAXCHATBUF - 10) {
	n = hangul_automata(-2, chat_p);
	chat_p += n;
    }

    if (chat_p + len < chat_buf + MAXCHATBUF - 10) {
	n = len;
    }
    else {
	for (p = chat_p, q = str; p < chat_buf + MAXCHATBUF - 10;) {
	    if (*q & 0x80) {
		p += 2;
		q += 2;
	    } else {
		p++;
		q++;
	    }
	    n = q - str;
	}
    }

    if (n <= 0)
	return;

    strncpy((char*)chat_p, (char*)str, n);
    chat_p += n;

    if (chat_p > org_p) {
	if (chat_x + (chat_p - org_p) <= term->screen.max_col)
	    draw_chat_buf(org_p, chat_p - org_p);
	chat_x += chat_p - org_p;
	if (chat_x > term->screen.max_col)
	    chat_scroll_left();
    }
    chat_show_cursor();
}

chat_control()
{
    unparseputc(*chat_buf, term->screen.respond);
    chat_p--;
    *chat_p = 0;
}

chat_clear()
{
    memset(chat_buf, '\0', chat_p - chat_buf);
    chat_x = CHAT_START_X;
    chat_startp = chat_p = chat_buf;
    chat_clear_line(chat_x, term->screen.max_col - chat_x + 1);
}

chat_backspace()
{
    int n;

    chat_p--;			/* bs ¸¦ Áö¿ò */
    *chat_p = 0;
    n = 0;
    if (chat_p - 1 >= chat_prompt) {
	n = adjust_hangul_string(chat_buf, chat_p - chat_buf - 1) ? 2 : 1;
	chat_p -= n;
	chat_x -= n;
	memset(chat_p, '\0', n);
	chat_scroll_right();
    }
    chat_clear_line(chat_x, n + 1);
}

chat_delete_word()
{
    Char *org_p;

    chat_p--;
    *chat_p = 0;
    org_p = chat_p;
    if (chat_p - 1 >= chat_prompt) {
	while (chat_p > chat_prompt && *(chat_p - 1) == ' ')
	    chat_p--;
	while (chat_p > chat_prompt && *(chat_p - 1) != ' ')
	    chat_p--;
	chat_x -= org_p - chat_p;
	memset(chat_p, '\0', org_p - chat_p);
	chat_scroll_right();
    }
    chat_clear_line(chat_x, org_p - chat_p + 1);
}

chat_flush(ret)
    int ret;
{
    Char *p;
    int n, f;
    Char buf[MAXCHATBUF * 4];

    n = hangul_automata(-2, chat_p);
    chat_p += n;
    chat_p -= ret;
    *chat_p = 0;
    if (*(chat_p - 1) == '\r' && (term->flags & LINEFEED))
	*chat_p++ = '\n';
    if (term->screen.code == C_WANSUNG) {
	n = convert_johab_to_ks(chat_buf, buf, chat_p - chat_buf);
	p = buf;
    } else {
	n = chat_p - chat_buf;
	p = chat_buf;
    }
    f = (*chat_callback)(term->screen.respond, p, n);
    chat_clear();
    if (f < 0) {
	chat_mode = 0;
	if (term->screen.code == C_WANSUNG) {
	    converter = convert_3_to_ks;
	}
	ShowCursor();
    }
}

chat_scroll_left()
{
    while (chat_x > term->screen.max_col) {
	if (*chat_startp & 0x80) {
	    chat_x -= 2;
	    chat_startp += 2;
	} else {
	    chat_x--;
	    chat_startp++;
	}
    }
    show_chat_buf();
}

chat_scroll_right()
{
    if (chat_startp > chat_buf && chat_x < term->screen.max_col - 1) {
	while (chat_startp > chat_buf && chat_x < term->screen.max_col - 1) {
	    if (adjust_hangul_string(chat_buf, chat_startp - chat_buf - 1)) {
		chat_x += 2;
		chat_startp -= 2;
	    } else {
		chat_x++;
		chat_startp--;
	    }
	}
	show_chat_buf();
    }
}

chat_clear_line(x, n)
    int x, n;
{
    register TScreen *screen = &term->screen;
    int	old_adjust;

/*
    old_adjust = iAdjuster;
    iAdjuster = 0;
    */
    if( background_filename==NULL || 
	    draw_box(screen->display, TextWindow(screen),
		       CursorX(screen, x),
		       (screen->max_row + 1) * FontHeight(screen)
		       + screen->border * 1,
		       n * FontWidth(screen), FontHeight(screen)))
	    XClearArea(screen->display, TextWindow(screen),
		       CursorX(screen, x),
		       (screen->max_row + 1) * FontHeight(screen) 
		       + screen->border * 1,
		       n * FontWidth(screen), FontHeight(screen), FALSE);
	    /*
    iAdjuster = old_adjust;
    */
}

chat_show_cursor()
{
    TScreen *screen = &term->screen;
    int n;
    Char c[2];

    if (temp_hangul[0]) {
	c[0] = temp_hangul[0];
	c[1] = temp_hangul[1];
	n = 2;
    }
    else {
	c[0] = *chat_p;
	n = 1;
	if (c[0] & 0x80) {
	    c[1] = *(chat_p + 1);
	    n = 2;
	}
    }
    if (chat_x == screen->max_col && n == 2) {
	if (*chat_startp & 0x80) {
	    chat_startp += 2;
	    chat_x -= 2;
	} else {
	    chat_startp++;
	    chat_x--;
	}
	show_chat_buf();
    }
	
    HDrawImageString2(screen->display, TextWindow(screen), screen->reverseGC,
		     screen->reverseHGC, CursorX(screen, chat_x),
		     (screen->max_row + 1) * FontHeight(screen) + 
		     screen->ascent + screen->border * 1, c, n, 1 );
}

chat_hide_cursor()
{
    TScreen *screen = &term->screen;
    int n;
    int	old_adjust;
    Char c[2];

    c[0] = *chat_p;
    c[1] = ' ';
    n = 2;
    /*
    old_adjust = iAdjuster;
    iAdjuster = 0;
    */
    HDrawImageString2(screen->display, TextWindow(screen), screen->normalGC,
		     screen->normalHGC, CursorX(screen, chat_x),
		     (screen->max_row + 1) * FontHeight(screen) + 
		     screen->ascent + screen->border * 1, c, n, 0 );
    /*
    iAdjuster = old_adjust;
    */
}

show_chat_buf()
{
	int	old_adjust;
    TScreen *screen = &term->screen;

/*
    old_adjust = iAdjuster;
    iAdjuster = 0;
    */
    HDrawImageString2(screen->display, TextWindow(screen), screen->normalGC,
		     screen->normalHGC,
		     CursorX(screen, CHAT_START_X),
		     (screen->max_row + 1) * FontHeight(screen) + 
		     screen->ascent + screen->border * 1,
		     chat_startp,
		     chat_p - chat_startp, 0);
    if( chat_x<=0 )	chat_x = CHAT_START_X;
    chat_clear_line(chat_x, term->screen.max_col - chat_x + 1);
    /*
    iAdjuster = old_adjust;
    */
}

draw_chat_buf(str, n)
    Char *str;
    int n;
{
	int	old_adjust;
    TScreen *screen = &term->screen;

/*
    old_adjust = iAdjuster;
    iAdjuster = 0;
    */
    HDrawImageString2(screen->display, TextWindow(screen), screen->normalGC,
		     screen->normalHGC, CursorX(screen, chat_x),
		     (screen->max_row + 1) * FontHeight(screen) + 
		     screen->ascent + screen->border * 1, str, n, 0);
    /*
    iAdjuster = old_adjust;
    */
}
