#include <sys/indirect.h>
#include <sys/bios.h>
#include "tscreen.h"

extern unsigned *il_get_ds();
extern void far *il_to_far(void near *p);
extern TScreenIL tscreenIL;
typedef struct {
  int curx;
  int cury;
  int stdout_flag; 
  /*
   * Set when getscr is called,
   * unset when initscr is called. 
   * Also, set_stdout_flag is available. 
   * Used to determine whether or not to clear the screen
   * after the child process exited.
   */
} TScreenData;

static ILinfo tscreen_info = {
   "TScreen", 
     "tscreen", 
     "0.0",
     "Text screen IL",
     (char far* far*)0,
};
static int font_blank[8] = {
   0, 0, 0, 0, 0, 0, 0, 0
};

ILinfo far* far tscreen_get_info(){
  return (ILinfo far*) il_to_far(&tscreen_info);
}


void far hide_cursor() {
  TScreenData far *p;
  p = sys_get_my_iram();
  screen_fill_attr(SCREEN1, p->curx, p->cury, 1, 1, 0, ~0x200);
}
void far show_cursor() {
  TScreenData far *p;
  p = sys_get_my_iram();
  screen_fill_attr(SCREEN1, p->curx, p->cury, 1, 1, 0x200, ~0x200);
}

void far move(int y, int x) {
  TScreenData far *p;

  hide_cursor();
  p = sys_get_my_iram();
  p->curx = x;
  p->cury = y;
  show_cursor();
}

int far getcurx() {
  TScreenData far *p;
  p = sys_get_my_iram();
  return p->curx;
}

int far getcury() {
  TScreenData far *p;
  p = sys_get_my_iram();
  return p->cury;
}

void far draw_char_to_font(int dstcode, int code) {
  char font[8];
  int ds;

  ds = _DS;
  _DS = _SS;
  text_get_fontdata(code, font);
  font_set_monodata(dstcode, 1, font);
  _DS = ds;
}

void far draw_char(int x, int y, int c) {
  draw_char_to_font(screen_get_char1(SCREEN1, x, y), c);
}

void far addch(int c) {
  int i;
  TScreenData far *p;

  hide_cursor();
  p = sys_get_my_iram();
  draw_char(p->curx, p->cury, c);
  p->curx ++;
  if (p->curx >= SCREEN_W) {
    if (p->cury < SCREEN_H-1) {
      p->curx = 0;
      p->cury ++;
    } else {
      p->curx --;
    }
  }
  show_cursor();
}

void far insch(int c) {
  int i;
  int chars[SCREEN_W], char_save;
  TScreenData far *p;
  int ds;

  hide_cursor();
  p = sys_get_my_iram();

  ds = _DS;
  _DS = _SS;
  screen_get_char(SCREEN1, 0, p->cury, SCREEN_W, 1, chars);
  char_save = chars[SCREEN_W-1];
  for(i=SCREEN_W-1; i > (p->curx); i--)
    chars[i] = chars[i-1];
  chars[p->curx] = char_save;
  draw_char_to_font(char_save, c);
  screen_set_char(SCREEN1, 0, p->cury, SCREEN_W, 1, chars);
  _DS = ds;

  show_cursor();
}

void far delch() {
  int i;
  int chars[SCREEN_W], char_save;
  TScreenData far *p;
  int ds;

  hide_cursor();
  p = sys_get_my_iram();

  ds = _DS;
  _DS = _SS;
  screen_get_char(SCREEN1, 0, p->cury, SCREEN_W, 1, (int far*)chars);
  char_save = chars[p->curx];
  for(i=p->curx; i < SCREEN_W-1; i++)
    chars[i] = chars[i+1];
  chars[SCREEN_W-1] = char_save;
  draw_char_to_font(char_save, 0);
  screen_set_char(SCREEN1, 0, p->cury, SCREEN_W, 1, (int far*)chars);
  _DS = ds;

  show_cursor();
}

void far addstr(const unsigned char far *string) {
   int i;
   int c1, c2;

   i=0;
   while((c1 = string[i])) {
      i++;
      if (c1 & 0x80) {
	 c2 = string[i];
	 i++;
	 if (c2 == 0)
	   break;
	 addch((c1<<8) + c2);
      } else {
	 addch(c1);
      }
   }
}

void far insertln() {
  TScreenData far *p;
  int i, j;
  int chars[SCREEN_W], chars_save[SCREEN_W];
  int ds;

  hide_cursor();

  p = sys_get_my_iram();

  ds = _DS;
  _DS = _SS;
  screen_get_char(SCREEN1, 0, SCREEN_H-1, SCREEN_W, 1, chars_save);
  for(i=SCREEN_H-1; i>(p->cury); i--) {
    screen_get_char(SCREEN1, 0, i-1, SCREEN_W, 1, chars);
    screen_set_char(SCREEN1, 0, i, SCREEN_W, 1, chars);
  }
  for(i=0; i<SCREEN_W; i++) 
    draw_char_to_font(chars_save[i], 0);
  screen_set_char(SCREEN1, 0, p->cury, SCREEN_W, 1, chars_save);
  _DS = ds;

  show_cursor();
}

void far deleteln() {
  TScreenData far *p;
  int i, j;
  int chars[SCREEN_W], chars_save[SCREEN_W];
  int ds;

  hide_cursor();

  ds = _DS;
  _DS = _SS;
  p = sys_get_my_iram();
  screen_get_char(SCREEN1, 0, p->cury, SCREEN_W, 1, chars_save);
  for(i=p->cury; i < SCREEN_H-1; i++) {
    screen_get_char(SCREEN1, 0, i+1, SCREEN_W, 1, chars);
    screen_set_char(SCREEN1, 0, i, SCREEN_W, 1, chars);
  }
  for(i=0; i<SCREEN_W; i++) 
    draw_char_to_font(chars_save[i], 0);
  screen_set_char(SCREEN1, 0, SCREEN_H-1, SCREEN_W, 1, chars_save);
  _DS = ds;

  show_cursor();
}

int far init_get_scr(int init_all) {
  int i, j;
  TScreenData far *p;
  int initchars[SCREEN_W];
  char initfont[8];
  int ds;

  if (!(p = sys_get_my_iram())) {
    p = sys_alloc_iram(0, sizeof(TScreenData));
  }
  p->curx = 0;
  p->cury = 0;

  if (init_all) {
    ds=_DS;
    _DS=_SS;
    for(i=0; i<8; i++)
      initfont[i] = 0;
    for(j=0; j<SCREEN_H; j++) {
      for(i=0; i<SCREEN_W; i++) {
	initchars[i] = i+j*SCREEN_W;
	font_set_monodata(initchars[i], 1, initfont);
      }
      screen_set_char(SCREEN1, 0, j, SCREEN_W, 1, initchars);
    }
    _DS=ds;
    p->stdout_flag = 0;
  } else {
    p->stdout_flag = 1;
  }

  display_control(0x01);
  lcd_set_color(0x6420, 0xfca8);
  palette_set_color(0, 0x7530);
  palette_set_color(1, 0x0357);
  show_cursor();
  return 0;
}

int far initscr() {
  return init_get_scr(1);
}
int far getscr() {
  return init_get_scr(0);
}

void far endwin() {
}

void far set_stdout_flag(int flag) {
  TScreenData far *p;
  p = sys_get_my_iram();
  p->stdout_flag = flag;
}

int far get_stdout_flag() {
  TScreenData far *p;
  p = sys_get_my_iram();
  return p->stdout_flag; 
}

