Logo Search packages:      
Sourcecode: hanterm-xf version File versions  Download package

chat.c

/*
   Chat mode processing

   written by Song Jaekyung
 */

#ifdef HAVE_CONFIG_H
#include <xtermcfg.h>
#endif
#include "ptyx.h"
#include "data.h"
#include "error.h"
#include <X11/keysym.h>
#include "hangul.h"
#include "xterm.h"
#include <stdio.h>
#include <stdlib.h>

#define MAXCHATBUF 1024

void init_history();
void using_history();
void add_history();
Char *previous_history ();
Char *next_history ();


int (*chat_callback) PROTO((int fd, char *str, int len));
int chat_mode;

static int chat_x;
static Char *chat_p, *chat_startp, *chat_buf = NULL, *chat_prompt;
static void chat_backspace PROTO((void));
static void chat_clear PROTO((void));
static void chat_delete_word PROTO((void));
static void chat_control PROTO((void));
static void chat_scroll_left PROTO((void));
static void chat_scroll_right PROTO((void));
static void draw_chat_buf PROTO((Char * str, int n));

/* chat_buf : 채팅 모드 문자열을 기억하는 버퍼
   chat_p : 문자열의 마지막을 가리킨다.
   chat_startp : 스크롤 됐을 때 처음을 가리킨다.
 */

void toggle_chat_mode(str)
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) + length_of_statusline();
      if (chat_buf == NULL) {
          chat_buf = (Char *) calloc(MAXCHATBUF, sizeof(Char));
          if (chat_buf == NULL) {
            fprintf(stderr, "%s: can't allocate chat buf\n", xterm_name);
            Cleanup(ERROR_SCALLOC);
          }
          init_history();
      }
      using_history();
      strcpy((char *) chat_buf, (char *) str);
      chat_startp = chat_buf;
      chat_prompt = chat_p = (Char *) strchr((char *) chat_buf, '\0');
      show_chat_buf();
    }
    ShowCursor();
}

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

    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 (keysym == XK_Up || keysym == XK_Down) {
      hist = NULL;
      hist = (keysym == XK_Up)? previous_history(): next_history();
      chat_clear();
      if(hist != NULL && *hist != 0) {
          hist_len = strlen((char *)hist);
          strcpy((char *)chat_buf, (char *)hist);
          chat_startp = org_p = chat_buf;
          chat_x = length_of_statusline();
          chat_p = chat_buf + hist_len;
      }

    } 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 0x7F:  /* delete */
#ifndef linux
                if (tmp_han)
                  chat_x += 2;
#endif
                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 = 0;

    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();
}

static void chat_control()
{
    v_write(term->screen.respond, chat_buf, 1);
    *chat_p-- = 0;
    *chat_p = 0;
}

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

static void chat_backspace()
{
    int n;

    *chat_p-- = 0;            /* 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);
}

static void 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);
}

void chat_flush(ret)
int ret;
{
    Char *p;
    int n, f;

    n = hangul_automata(-2, chat_p);
    chat_p += n;
    chat_p -= ret;
    if (*(chat_p - 1) == '\r') add_history(chat_buf, chat_p - chat_buf - 1);
    else add_history(chat_buf, chat_p - chat_buf);
    using_history();

    *chat_p = 0;
    if (*(chat_p - 1) == '\r' && (term->flags & LINEFEED))
      *chat_p++ = '\n';
    n = chat_p - chat_prompt;
    p = chat_prompt;
    f = (*chat_callback) (term->screen.respond, (char *)p, n);
    chat_clear();
    if (f < 0) {
      chat_mode = 0;
      ShowCursor();
    }
}

static void 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();
}

static void 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();
    }
}

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

    XClearArea(screen->display, TextWindow(screen),
             CursorX(screen, x),
       (screen->max_row + 1) * FontHeight(screen) + screen->border * 2,
             n * FontWidth(screen), FontHeight(screen), FALSE);
}

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

    if (temp_hangul[0]) {
      c[0] = temp_hangul[0];
      c[1] = temp_hangul[1];
      n = 2;
    } else {
      c[0] = *chat_p;
      if (!c[0])
          c[0] = ' ';
      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();
    }
    if (screen->reversecursorGC) {
      reverseGC = screen->reversecursorGC;
      reverseHGC = screen->reversecursorHGC;
    } else {
      reverseGC = ReverseGC(screen);
      reverseHGC = ReverseHGC(screen);
    }
    HDrawImageString(screen->display, TextWindow(screen), reverseGC,
                 reverseHGC, CursorX(screen, chat_x),
                 (screen->max_row + 1) * FontHeight(screen) +
                 screen->ascent + screen->border * 2, c, n);
}

void chat_hide_cursor(void)
{
    chat_clear_line(chat_x, 2);
#if 0
    TScreen *screen = &term->screen;
    int n;
    Char c[2];

    c[0] = *chat_p;
    if (c[0] == 0)
      c[0] = ' ';
    c[1] = ' ';
    n = 2;
    HDrawImageString(screen->display, TextWindow(screen), NormalGC(screen),
                 NormalHGC(screen), CursorX(screen, chat_x),
                 (screen->max_row + 1) * FontHeight(screen) +
                 screen->ascent + screen->border * 2, c, n);
#endif
}

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

    set_default_color(screen);
    HDrawImageString(screen->display, TextWindow(screen), NormalGC(screen),
                 NormalHGC(screen),
                 CursorX(screen, length_of_statusline()),
                 (screen->max_row + 1) * FontHeight(screen) +
                 screen->ascent + screen->border * 2,
                 chat_startp,
                 chat_p - chat_startp);
}

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

    set_default_color(screen);
    HDrawImageString(screen->display, TextWindow(screen), NormalGC(screen),
                 NormalHGC(screen), CursorX(screen, chat_x),
                 (screen->max_row + 1) * FontHeight(screen) +
                 screen->ascent + screen->border * 2, str, n);
}

Generated by  Doxygen 1.6.0   Back to index