#include <stdio.h>
#include <unistd.h>
#include <curses.h>
#include "../defs.h"
#include "../memory.h"

static int mode7_addr = 0x7c00;

/* modes */
#define M_NORMAL	0
#define M_DEF_TEXT	1
#define M_DEF_GRAP	2
#define M_DEF_LOGI	3
#define M_SEL_MODE	4
#define M_REPROG	5
#define M_DEF_GWIN	6
#define M_DEF_TWIN	7
#define M_G_ORIG	8
#define M_MV_CURS	9
#define M_PRN_NEXT     10
#define M_PLOT	       11

void poke_char(word addr, byte c);

void init_screen() {
    int i;
    initscr();
    noecho();
    cbreak();
    clear(); 
    refresh();

    /*
     * Add memory hooks
     */
    for (i = 0x7c00; i <= 0x8000; i++) {
	special_mem_w[i] = poke_char;
    }
}

void poke_char(word addr, byte c) {
    addr -= mode7_addr;
    mvaddch(addr / 40, addr % 40, c);
}

void write_char(char c) {
    static int bytes = 0;
    static int mode = M_NORMAL;
    static int tx = 0;
    static int ty = 0;
    static int scroll_mode = 0;

    move(ty, tx);
    if (bytes)
	bytes--;
    switch (mode) {
    case M_NORMAL:
	switch (c) {
	case 0:
	case 27:
	    break;
	case 1:
	    mode = M_PRN_NEXT;
	    break;
	case 2:
	    /* turn on printer */
	    break;
	case 3:
	    /* turn off printer */
	    break;
	case 4:
	    /* use text */
	    break;
	case 5:
	    /* use graphics */
	    break;
	case 6:
	    echo();
	    break;
	case 7:
	    write(1, &c, 1);
	    break;
	case 8:
	    tx--;
	    break;
	case 9:
	    tx++;
	    break;
	case 10:
	    ty++;
	    break;
	case 11:
	    ty--;
	    break;
	case 12:
	    clear();
	    tx = 0;
	    ty = 0;
	    break;
	case 13:
	    tx = 0;
	    break;
	case 14:
	    scroll_mode = 1;
	    break;
	case 15:
	    scroll_mode = 0;
	    break;
	case 16:
	    /* CLG */
	    break;
	case 17:
	    mode = M_DEF_TEXT;
	    bytes = 1;
	    break;
	case 18:
	    mode = M_DEF_GRAP;
	    bytes = 2;
	    break;
	case 19:
	    mode = M_DEF_LOGI;
	    bytes = 5;
	    break;
	case 20:
	    /* restore cols */
	    break;
	case 21:
	    /* control U */
	    break;
	case 22:
	    /* change mode */
	    mode = M_SEL_MODE;
	    bytes = 1;
	    break;
	case 23:
	    /* reprog chars */
	    mode = M_REPROG;
	    bytes = 1;
	    break;
	case 24:
	    /* def graph win */
	    mode = M_DEF_GWIN;
	    bytes = 8;
	    break;
	case 25:
	    /* plot */
	    mode = M_PLOT;
	    bytes = 5;
	    break;
	case 26:
	    /* reset win sizes */
	    break;
	case 28:
	    mode = M_DEF_TWIN;
	    bytes = 4;
	    break;
	case 29:
	    mode = M_G_ORIG;
	    bytes = 4;
	    break;
	case 30:
	    tx = 0;
	    ty = 0;
	    break;
	case 31:
	    /* move text curs */
	    mode = M_MV_CURS;
	    bytes = 2;
	    break;
	case 127:
	    tx--;
	    move(ty, tx);
	    addch(' ');
	    move(ty, tx);
	    break;
	default:
	    addch(c);
	    tx++;
	    if (tx > 40) {
		ty++;
		tx = 0;
		if (ty > 24) {
		    /* scroll */
		}
	    }
	    break;
	}
    case M_DEF_TEXT:
	break;
    case M_DEF_GRAP:
	break;
    case M_DEF_LOGI:
	break;
    case M_SEL_MODE:
	break;
    case M_REPROG:
	break;
    case M_DEF_GWIN:
	break;
    case M_DEF_TWIN:
	break;
    case M_G_ORIG:
	break;
    case M_MV_CURS:
	if (bytes == 1)
	    tx = c;
	else
	    ty = c;
	break;
    }
    if (!bytes)
	mode = M_NORMAL;
    refresh();
}

int read_char() {
    char c;

    read(0, &c, 1);
    return c;
}
