/* bootpackのメイン */
#include "bootpack.h"
//#include "splash.h"
#include <stdio.h>

struct TASK *clocktask;
struct TASK *menutask;
struct TASK *imetask;
struct TASK *beeptask;

extern struct SHEET *sht_ime;

struct MEMMAN *mem;	/* メモリ管理用 */

unsigned int mdata[4];

struct SHEET *sht_back;
struct SHEET *key_win;
struct SHTCTL *shtctl;

struct TASK *fdc, *inout;
void fdc_task(void);

char cpath[256], epath[1024];

#define KEYCMD_LED		0xed

void close_console(struct SHEET *sht);
void close_constask(struct TASK *task);

void inout_task(struct SHEET *sht_back);

void HariMain(void)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
	unsigned char s[40];
	struct FIFO32 fifo, keycmd;
	int fifobuf[128], keycmd_buf[32];
	unsigned int memtotal;
	struct MOUSE_DEC mdec;
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	mem = (struct MEMMAN *) MEMMAN_ADDR;
	unsigned int *buf_back, buf_mouse[256];
	unsigned int *buf_ssgl;
	struct SHEET *sht_mouse;
	struct SHEET *sht_ssgl;
	struct TASK *task_a, *task;
	static char keytable0[0x80] = {
		0,   0,   '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '^', 0x08, 0,
		'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '@', '[', 0x0a, 0, 'A', 'S',
		'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', ':', 0,   0,   ']', 'Z', 'X', 'C', 'V',
		'B', 'N', 'M', ',', '.', '/', 0,   '*', 0,   ' ', 0,   0,   0,   0,   0,   0,
		0,   0,   0,   0,   0,   0,   0,   '7', '8', '9', '-', '4', '5', '6', '+', '1',
		'2', '3', '0', '.', 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
		0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
		0,   0,   0,   0x5c, 0,  0,   0,   0,   0,   0x02,   0,   0,   0x02,   0x5c, 0,  0
	};
	static char keytable1[0x80] = {
		0,   0,   '!', 0x22, '#', '$', '%', '&', 0x27, '(', ')', '~', '=', '~', 0x08, 0,
		'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '`', '{', 0x0a, 0, 'A', 'S',
		'D', 'F', 'G', 'H', 'J', 'K', 'L', '+', '*', 0,   0,   '}', 'Z', 'X', 'C', 'V',
		'B', 'N', 'M', '<', '>', '?', 0,   '*', 0, ' ',   0,   0,   0,   0,   0,   0,
		0,   0,   0,   0,   0,   0,   0,   0,0xa0,   0, '-',0xfd,   0,0xfe, '+',   0,
		0xff, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
		0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
		0,   0,   0,   '_', 0,   0,   0,   0,   0,   0x02,   0,   0,   0x02,   '|', 0,   0
	};
	int key_shift = 0, key_leds = (binfo->leds >> 4) & 7, keycmd_wait = -1;
	int j, x, y, mmx = -1, mmy = -1, mmx2 = 0;
	int mx, my, i, new_mx = -1, new_my = 0, new_wx = 0x7fffffff, new_wy = 0;
	struct SHEET *sht = 0, *sht2;
	int *fat;
	unsigned char *sjis;
	struct FILEINFO *finfo;
	extern char ascii[4096];
	int key_ime = 0;
	char imebuf[2];
	char *ime_buf;
	int u_fat[2880];
	int x2, y2;
	unsigned char logo[9216];
	int prog;

	init_gdtidt();
	init_pic();
	io_sti(); /* IDT/PICの初期化が終わったのでCPUの割り込み禁止を解除 */
	fifo32_init(&fifo, 128, fifobuf, 0);
	*((int *) 0x0fec) = (int) &fifo;
	init_pit();
	init_keyboard(&fifo, 256);
	enable_mouse(&fifo, 512, &mdec);
	io_out8(PIC0_IMR, 0xb8); /* PITとPIC1とキーボードを許可(10111000) */
	io_out8(PIC1_IMR, 0xef); /* マウスを許可(11101111) */
	fifo32_init(&keycmd, 32, keycmd_buf, 0);

	init_palette();

	/* PATHの初期化 */
	strcpy(cpath, "/root/apps/");
	strcpy(epath, "/root/apps/");

	/* FATの展開、テーブル初期化 */
	file_readfat(u_fat, (unsigned char *) (ADR_DISKIMG + 0x000200));
	file_inittbl();

	finfo = file_search2("/usr/share/splash/splash.img", (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224, fat);
	if (finfo != 0) {
		file_loadfile(finfo->clustno, finfo->size, logo, u_fat, (char *) (ADR_DISKIMG + 0x003e00));
		putblock8_fb(binfo->vram, logo, (binfo->scrnx / 2) - (384 / 2), (binfo->scrny / 2) - (192 / 2), 384, 192);
	}
	
	prog = 0;
	boxfill8_fb(binfo->vram, 0x0000ff, (binfo->scrnx / 2) - (384 / 2) + 64, (binfo->scrny / 2) - (192 / 2) + 128, 
		(binfo->scrnx / 2) - (384 / 2) + 64 + ((prog / 1024) * 256), (binfo->scrny / 2) - (192 / 2) + 128 + 8);

	memtotal = memtest(0x00400000, 0xbfffffff);
	*((int *) 0x268000) = memtotal;
	memman_init(memman);
	memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 0x0009efff */
	memman_free(memman, 0x00400000, memtotal - 0x00400000);
	prog = 384;
	boxfill8_fb(binfo->vram, 0x0000ff, (binfo->scrnx / 2) - (384 / 2) + 64, (binfo->scrny / 2) - (192 / 2) + 128, 
		(binfo->scrnx / 2) - (384 / 2) + 64 + ((prog / 1024) * 256), (binfo->scrny / 2) - (192 / 2) + 128 + 8);

	shtctl = shtctl_init(memman, binfo->vram, binfo->scrnx, binfo->scrny);
	task_a = task_init(memman);
	fifo.task = task_a;
	task_a->langmode = 1;
	task_a->langbyte1 = 0;
	strcpy(task_a->taskname, "task_a");
	task_run(task_a, 0, 2);
	*((int *) 0x0fe4) = (int) shtctl;
	
	prog = 768;
	boxfill8_fb(binfo->vram, 0x0000ff, (binfo->scrnx / 2) - (384 / 2) + 64, (binfo->scrny / 2) - (192 / 2) + 128, 
		(binfo->scrnx / 2) - (384 / 2) + 64 + ((prog / 1024) * 256), (binfo->scrny / 2) - (192 / 2) + 128 + 8);
	
	/* sjis.fntの読み込み */
	fat = (int *) memman_alloc_4k(memman, 4 * 2880);
	file_readfat(fat, (unsigned char *) (ADR_DISKIMG + 0x000200));
	task_a->fat = fat;
	
	finfo = file_search2("/usr/share/fonts/sjis.fnt", (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224, fat);
	if (finfo != 0) {
		i = finfo->size;
		sjis = file_loadfile2(finfo->clustno, &i, fat);
	} else {
		sjis = (unsigned char *) memman_alloc_4k(memman, 16 * 256 + 32 * 94 * 47);
		for (i = 0; i < 16 * 256; i++) {
			sjis[i] = ascii[i]; /* フォントがなかったので半角部分をコピー */
		}
		for (i = 16 * 256; i < 16 * 256 + 32 * 94 * 47; i++) {
			sjis[i] = 0xff; /* フォントがなかったので全角部分を0xffで埋め尽くす */
		}
	}
	*((int *) 0x0fe8) = (int) sjis;
	//memman_free_4k(memman, (int) fat, 4 * 2880);
	prog = 1024;
	boxfill8_fb(binfo->vram, 0x0000ff, (binfo->scrnx / 2) - (384 / 2) + 64, (binfo->scrny / 2) - (192 / 2) + 128, 
		(binfo->scrnx / 2) - (384 / 2) + 64 + ((prog / 1024) * 256), (binfo->scrny / 2) - (192 / 2) + 128 + 8);

	/* sht_back */
	sht_back  = sheet_alloc(shtctl);
	sht_back->flag2 = 1;
	buf_back  = (unsigned int *) memman_alloc_4k(memman, (binfo->scrnx * binfo->scrny) * 4);
	sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny, -1); /* 透明色なし */
	init_screen8(buf_back, binfo->scrnx, binfo->scrny);

	/* sht_cons */
	key_win = open_console(shtctl, memtotal);

	sht_mouse = sheet_alloc(shtctl);
	sheet_setbuf(sht_mouse, buf_mouse, 16, 16, 99);
	init_mouse_cursor8(buf_mouse, 99);
	mx = (binfo->scrnx - 16) / 2; /* 画面中央になるように座標計算 */
	my = (binfo->scrny - 28 - 16) / 2;

	sheet_slide(sht_back,  0,  0);
	//sheet_slide(sht_ssgl, 0, 0);
	sheet_slide(key_win,   32, 4);
	sheet_slide(sht_mouse, mx, my);
	sheet_updown(sht_back,  0);
	//sheet_updown(sht_ssgl,  1);
	sheet_updown(key_win,   2);
	sheet_updown(sht_mouse, 3);
	keywin_on(key_win);

	/* 最初にキーボード状態との食い違いがないように、設定しておくことにする */
	fifo32_put(&keycmd, KEYCMD_LED);
	fifo32_put(&keycmd, key_leds);

	clocktask = task_alloc();
	int *clock_fifo = (int *) memman_alloc_4k(memman, 128 * 4);
	clocktask->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024 - 8;
	clocktask->tss.eip = (int) &clock_task;
	clocktask->tss.es = 1 * 8;
	clocktask->tss.cs = 2 * 8;
	clocktask->tss.ss = 1 * 8;
	clocktask->tss.ds = 1 * 8;
	clocktask->tss.fs = 1 * 8;
	clocktask->tss.gs = 1 * 8;
	*((int *) (clocktask->tss.esp + 4)) = (int) sht_back;
	task_run(clocktask, 4, 2);
	fifo32_init(&clocktask->fifo, 128, clock_fifo, clocktask);
	strcpy(clocktask->taskname, "clock");

	menutask = task_alloc();
	int *menu_fifo = (int *) memman_alloc_4k(memman, 128 * 4);
	menutask->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024 - 8;
	menutask->tss.eip = (int) &menu_task;
	menutask->tss.es = 1 * 8;
	menutask->tss.cs = 2 * 8;
	menutask->tss.ss = 1 * 8;
	menutask->tss.ds = 1 * 8;
	menutask->tss.fs = 1 * 8;
	menutask->tss.gs = 1 * 8;
	*((int *) (menutask->tss.esp + 4)) = (int) memman_total(memman);
	task_run(menutask, 4, 2);
	fifo32_init(&menutask->fifo, 128, menu_fifo, menutask);
	strcpy(menutask->taskname, "menu");
	
	/*beeptask = task_alloc();
	int *beep_fifo = (int *) memman_alloc_4k(memman, 128 * 4);
	beeptask->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024;
	beeptask->tss.eip = (int) &beep_task;
	beeptask->tss.es = 1 * 8;
	beeptask->tss.cs = 2 * 8;
	beeptask->tss.ss = 1 * 8;
	beeptask->tss.ds = 1 * 8;
	beeptask->tss.fs = 1 * 8;
	beeptask->tss.gs = 1 * 8;
	task_run(beeptask, 2, 2);
	fifo32_init(&beeptask->fifo, 128, beep_fifo, beeptask);
	strcpy(beeptask->taskname, "beep");*/
	
	imetask = task_alloc();
	int *ime_fifo = (int *) memman_alloc_4k(memman, 128 * 4);
	imetask->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024;
	imetask->tss.eip = (int) &ime_task;
	imetask->tss.es = 1 * 8;
	imetask->tss.cs = 2 * 8;
	imetask->tss.ss = 1 * 8;
	imetask->tss.ds = 1 * 8;
	imetask->tss.fs = 1 * 8;
	imetask->tss.gs = 1 * 8;
	task_run(imetask, 2, 1);
	fifo32_init(&imetask->fifo, 128, ime_fifo, imetask);
	strcpy(imetask->taskname, "ime");
	
	/*fdc = task_alloc();
	int *fdc_fifo = (int *) memman_alloc_4k(memman, 2880 * 4 * 4);
	fdc->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024;
	fdc->tss.eip = (int) &fdc_task;
	fdc->tss.es = 1 * 8;
	fdc->tss.cs = 2 * 8;
	fdc->tss.ss = 1 * 8;
	fdc->tss.ds = 1 * 8;
	fdc->tss.fs = 1 * 8;
	fdc->tss.gs = 1 * 8;
	strcpy(fdc->taskname, "fdc");
	task_run(fdc, 1, 2);
	fifo32_init(&fdc->fifo, 2880 * 4, fdc_fifo, fdc);

	inout = task_alloc();
	int *inout_fifo = (int *) memman_alloc_4k(memman, 128 * 4);
	inout->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024 - 8;
	inout->tss.eip = (int) &inout_task;
	inout->tss.es = 1 * 8;
	inout->tss.cs = 2 * 8;
	inout->tss.ss = 1 * 8;
	inout->tss.ds = 1 * 8;
	inout->tss.fs = 1 * 8;
	inout->tss.gs = 1 * 8;
	strcpy(inout->taskname, "ioctrl");
	*((int *) (inout->tss.esp + 4)) = (int) sht_back;
	task_run(inout, 1, 2);
	fifo32_init(&inout->fifo, 128, inout_fifo, inout);*/
	
	/*struct BEEP_REQ beep[3];
	
	beep[0].freq = 2000 * 1000;
	beep[1].freq = 1000 * 1000;
	beep[2].freq = 0;
	beep[0].time = 18;
	beep[1].time = 18;
	beep[2].time = 1;
	
	fifo32_put(&beeptask->fifo, 3);
	fifo32_put(&beeptask->fifo, (int) beep);
	fifo32_put(&beeptask->fifo, 512 + 2);
	fifo32_put(&beeptask->fifo, 256 + 1);*/
	
	//play_beep(400);
	
	for (;;) {
		if((memman_total(memman) / 1024) <= 1024) {
			io_cli();
			boxfill8(sht_back->buf, binfo->scrnx, COL8_000084, 0, 0, binfo->scrnx, binfo->scrny);
			putfonts8_asc(sht_back->buf, binfo->scrnx, 8, 8, COL8_FFFFFF, " STOP (0x00000001)\n\n MEMORY_OVER_FROW\n\n メモリが不足しています。システムは停止しました");
			sheet_updown(sht_back, 0);
			for(;;) {}
		}
		if (fifo32_status(&keycmd) > 0 && keycmd_wait < 0) {
			/* キーボードコントローラに送るデータがあれば、送る */
			keycmd_wait = fifo32_get(&keycmd);
			wait_KBC_sendready();
			io_out8(PORT_KEYDAT, keycmd_wait);
		}
		io_cli();
		if (fifo32_status(&fifo) == 0) {
			/* FIFOがからっぽになったので、保留している描画があれば実行する */
			if (new_mx >= 0) {
				io_sti();
				sheet_slide(sht_mouse, new_mx, new_my);
				new_mx = -1;
			} else if (new_wx != 0x7fffffff) {
				io_sti();
				sheet_slide(sht, new_wx, new_wy);
				new_wx = 0x7fffffff;
			} else {
				task_sleep(task_a);
				io_sti();
			}
		} else {
			i = fifo32_get(&fifo);
			io_sti();
			if (key_win != 0 && key_win->flags == 0) {	/* ウィンドウが閉じられた */
				if (shtctl->top == 1) {	/* もうマウスと背景しかない */
					key_win = 0;
				} else {
					key_win = shtctl->sheets[shtctl->top - 1];
					keywin_on(key_win);
				}
			}
			if (256 <= i && i <= 511 || i == 0xfc || i == 0xfd || i == 0xfe || i == 0xff) { /* キーボードデータ */
				if (i < 0x80 + 256) { /* キーコードを文字コードに変換 */
					if (key_shift == 0) {
						s[0] = keytable0[i - 256];
					} else {
						s[0] = keytable1[i - 256];
					}
				} else {
					s[0] = 0;
				}
				if ('A' <= s[0] && s[0] <= 'Z') {	/* 入力文字がアルファベット */
					if (((key_leds & 4) == 0 && key_shift == 0) ||
							((key_leds & 4) != 0 && key_shift != 0)) {
						s[0] += 0x20;	/* 大文字を小文字に変換 */
					}
				}
				if (s[0] != 0 && key_win != 0) { /* 通常文字、バックスペース、Enter */
					if(key_ime == 0) fifo32_put(&key_win->task->fifo, s[0] + 256);
					else fifo32_put(&imetask->fifo, s[0] + 256);
				}
				if (i == 0x01 + 256) {
					fifo32_put(&key_win->task->fifo, 1 + 256);
				}
				if (i == 256 + 0x0f && key_win != 0) {	/* Tab */
					keywin_off(key_win);
					j = key_win->height - 1;
					if (j == 0) {
						j = shtctl->top - 1;
					}
					key_win = shtctl->sheets[j];
					if(key_win->act == 0) keywin_on(key_win);
				}
				if (i == 256 + 0x2a) {	/* 左シフト ON */
					key_shift |= 1;
				}
				if (i == 256 + 0x36) {	/* 右シフト ON */
					key_shift |= 2;
				}
				if (i == 256 + 0xaa) {	/* 左シフト OFF */
					key_shift &= ~1;
				}
				if (i == 256 + 0xb6) {	/* 右シフト OFF */
					key_shift &= ~2;
				}
				if (i == 256 + 0x3a) {	/* CapsLock */
					key_leds ^= 4;
					fifo32_put(&keycmd, KEYCMD_LED);
					fifo32_put(&keycmd, key_leds);
				}
				if (i == 256 + 0x45) {	/* NumLock */
					key_leds ^= 2;
					fifo32_put(&keycmd, KEYCMD_LED);
					fifo32_put(&keycmd, key_leds);
				}
				if (i == 256 + 0x46) {	/* ScrollLock */
					key_leds ^= 1;
					fifo32_put(&keycmd, KEYCMD_LED);
					fifo32_put(&keycmd, key_leds);
				}
				if (i == 256 + 0x29) {	/* 半角/全角 */
					key_ime ^= 1;
					fifo32_put(&imetask->fifo, key_ime + 1);
				}
				if (i == 256 + 0x7b) {	/* 無変換 */
					fifo32_put(&imetask->fifo, 0xff + 256);
				}
				if (i == 256 + 0x3b && key_shift != 0 && key_win != 0) {	/* Shift+F1 */
					task = key_win->task;
					if (task != 0 && task->tss.ss0 != 0) {
						io_cli();	/* 強制終了処理中にタスクが変わると困るから */
						task->tss.eax = (int) &(task->tss.esp0);
						task->tss.eip = (int) asm_end_app;
						io_sti();
						task_run(task, -1, 0);	/* 終了処理を確実にやらせるために、寝ていたら起こす */
					}
				}
				if (i == 256 + 0x3c && key_shift != 0) {	/* Shift+F2 */
					/* 新しく作ったコンソールを入力選択状態にする（そのほうが親切だよね？） */
					//asm_int0d();
					if (key_win != 0) {
						if(key_win->act == 1) keywin_off(key_win);
					}
					key_win = open_console(shtctl, memtotal);
					if(key_win->act == 0) keywin_on(key_win);
					sheet_slide(key_win, 32, 4);
					sheet_updown(key_win, shtctl->top);
				}
				if (i == 256 + 0x57) {	/* F11 */
					sheet_updown(shtctl->sheets[1], shtctl->top - 1);
				}
				if (i == 256 + 0xfa) {	/* キーボードがデータを無事に受け取った */
					keycmd_wait = -1;
				}
				if (i == 256 + 0xfe) {	/* キーボードがデータを無事に受け取れなかった */
					wait_KBC_sendready();
					io_out8(PORT_KEYDAT, keycmd_wait);
				}
			} else if (512 <= i && i <= 767) { /* マウスデータ */
				if (mouse_decode(&mdec, i - 512) != 0) {
					/* マウスカーソルの移動 */
					mx += mdec.x;
					my += mdec.y;
					if (mx < 0) {
						mx = 0;
					}
					if (my < 0) {
						my = 0;
					}
					if (mx > binfo->scrnx - 1) {
						mx = binfo->scrnx - 1;
					}
					if (my > binfo->scrny - 1) {
						my = binfo->scrny - 1;
					}
					
					mdata[0] = mx;
					mdata[1] = my;
					new_mx = mx;
					new_my = my;
					if ((mdec.btn & 0x01) != 0) {
						/* 左ボタンを押している */
						mdata[2] = 1;
						fifo32_put(&menutask->fifo, '!');
						if (mmx < 0) {
							/* 通常モードの場合 */
							/* 上の下じきから順番にマウスが指している下じきを探す */
							for (j = shtctl->top - 1; j > 0; j--) {
								sht = shtctl->sheets[j];
								x = mx - sht->vx0;
								y = my - sht->vy0;
								if (0 <= x && x < sht->bxsize && 0 <= y && y < sht->bysize) {
									if (sht->buf[y * sht->bxsize + x] != sht->col_inv && sht->flag2 == 0) {
										sheet_updown(sht, shtctl->top - 1);
										if (sht != key_win && sht != sht_ime) {
											if(key_win->act == 1) keywin_off(key_win);
											key_win = sht;
											if(key_win->act == 0) keywin_on(key_win);
										}
										if ((3 <= x && x < sht->bxsize - 3 && 3 <= y && y < 21) && sht->flag2 == 0) {
											mmx = mx;	/* ウィンドウ移動モードへ */
											mmy = my;
											mmx2 = sht->vx0;
											new_wy = sht->vy0;
										}
										if (4 <= x && x < 19 && 5 <= y && y < 19 && (sht->buf[y * sht->bxsize + x] == COL8_FF7F27 || sht->buf[y * sht->bxsize + x] == COL8_000000)) {
												/* 「×」ボタンクリック */
											if ((sht->flags & 0x10) != 0) {		/* アプリが作ったウィンドウか？ */
												task = sht->task;
												io_cli();	/* 強制終了処理中にタスクが変わると困るから */
												task->tss.eax = (int) &(task->tss.esp0);
												task->tss.eip = (int) asm_end_app;
												io_sti();
												task_run(task, -1, 0);
											} else {	/* コンソールなど */
												task = sht->task;
												sheet_updown(sht, -1); /* とりあえず非表示にしておく */
												keywin_off(key_win);
												key_win = shtctl->sheets[shtctl->top - 1];
												keywin_on(key_win);
												io_cli();
												fifo32_put(&task->fifo, 4);
												io_sti();
											}
										}
										break;
									}
								}
							}
						} else {
							/* ウィンドウ移動モードの場合 */
							mdata[2] = 0;
							x = mx - mmx;	/* マウスの移動量を計算 */
							y = my - mmy;
							new_wx = (mmx2 + x + 2) & ~3;
							new_wy = new_wy + y;
							mmy = my;	/* 移動後の座標に更新 */
						}
					} else if (mdec.btn & 0x02) {
						/* 右ボタン */
						mdata[3] = 1;
					} else {
						/* 左ボタンを押していない */
						mdata[2] = 0;
						mdata[3] = 0;
						mmx = -1;	/* 通常モードへ */
						if (new_wx != 0x7fffffff) {
							sheet_slide(sht, new_wx, new_wy);	/* 一度確定させる */
							new_wx = 0x7fffffff;
						}
					}
				}
			} else if (768 <= i && i <= 1023) {	/* コンソール終了処理 */
				close_console(shtctl->sheets0 + (i - 768));
			} else if (1024 <= i && i <= 2023) {
				close_constask(taskctl->tasks0 + (i - 1024));
			} else if (2024 <= i && i <= 2279) {	/* コンソールだけを閉じる */
				sht2 = shtctl->sheets0 + (i - 2024);
				memman_free_4k(memman, (int) sht2->buf, 256 * 165);
				sheet_free(sht2);
			} else if (i == 8) {
				fifo32_put(&key_win->task->fifo, 0x05);
			}
		}
	}
}

void keywin_off(struct SHEET *key_win)
{
	change_wtitle8(key_win, 0);
	if ((key_win->flags & 0x20) != 0) {
		fifo32_put(&key_win->task->fifo, 3); /* コンソールのカーソルOFF */
	}
	key_win->act = 0;
	return;
}

void keywin_on(struct SHEET *key_win)
{
	change_wtitle8(key_win, 1);
	if ((key_win->flags & 0x20) != 0) {
		fifo32_put(&key_win->task->fifo, 2); /* コンソールのカーソルON */
	}
	key_win->act = 1;
	return;
}

struct TASK *open_constask(struct SHEET *sht, unsigned int memtotal)
{
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	struct TASK *task = task_alloc();
	int *cons_fifo = (int *) memman_alloc_4k(memman, 128 * 4);
	task->cons_stack = memman_alloc_4k(memman, 64 * 1024);
	task->tss.esp = task->cons_stack + 64 * 1024 - 12;
	task->tss.eip = (int) &console_task;
	task->tss.es = 1 * 8;
	task->tss.cs = 2 * 8;
	task->tss.ss = 1 * 8;
	task->tss.ds = 1 * 8;
	task->tss.fs = 1 * 8;
	task->tss.gs = 1 * 8;
	*((int *) (task->tss.esp + 4)) = (int) sht;
	*((int *) (task->tss.esp + 8)) = memtotal;
	task_run(task, 1, 2); /* level=1, priority=2 */
	fifo32_init(&task->fifo, 128, cons_fifo, task);
	task->langbyte1 = 0x00;
	strcpy(task->taskname, "console");
	return task;
}

struct SHEET *open_console(struct SHTCTL *shtctl, unsigned int memtotal)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	struct SHEET *sht = sheet_alloc(shtctl);
	struct TASK *task;
	unsigned int *buf;
	buf = (unsigned int *) memman_alloc_4k(memman, (640 * 480) * 4);
	sht->task = open_constask(sht, memtotal);
	sheet_setbuf(sht, buf, 640, 480, -1); /* 透明色なし */
	make_window8(buf, 640, 480, "tuOS Console", 1);
	make_textbox8(sht, 8, 28, 640 - 16, 480 - 20 - 16, COL8_000000);
	sht->act = 1;
	sht->flag2 = 0;
	sht->flags |= 0x20;	/* カーソルあり */
	key_win = sht;
	return sht;
}

void close_constask(struct TASK *task)
{
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	task_sleep(task);
	memman_free_4k(memman, task->cons_stack, 64 * 1024);
	memman_free_4k(memman, (int) task->fifo.buf, 128 * 4);
	io_cli();                                               /* ココから */
    task->flags = 0; /* task_free(task); の代わり */
    if (taskctl->task_fpu == task) {
        taskctl->task_fpu = 0;
    }
    io_sti();                                               /* ココまで */
	task->flags = 0; /* task_free(task); の代わり */
	return;
}

void close_console(struct SHEET *sht)
{
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	struct TASK *task = sht->task;
	memman_free_4k(memman, (int) sht->buf, 640 * 480);
	sheet_free(sht);
	close_constask(task);
	return;
}
