/*
	○NegitoroOSのブーティング メインシステム○

	・変更履歴詳細
	2/12 0.0.1 タスク管理システムであるtaskmanの起動が導入。 by is2os
	3/5 0.0.4a clockタスク導入。 by is2os
	3/10 0.0.5a clockとnegimanの不具合を修正。 by is2os
	3/13 0.0.5b exitコマンドの不具合を修正。
				shutdownが起動できる。 by is2os
	3/17 0.0.5c	CtrlやAlt等のキーコードをリテラルにした。
				幾つか変数や関数の名前を変えた。 by is2os
	3/17 0.0.6a シェルの出てくる位置を少し変えた。 by is2os
	3/18 0.0.6b シート判断フラグの値をリテラルに変えた。
				背景が変わったときにアイコンの名前の文字の色が反転するようになった。 by is2os
	3/19 0.0.6c 一応、固定ファイル名もリテラルにした by is2os
	3/29 0.0.6d スタートメニューが表示されるようになった by is2os

*/

#include "bootpack.h"
#include "../pictlib.h"
#include <string.h>
#include <stdio.h>

#define KEYCMD_LED		0xed

int atoi(char *s);

void KeyDataSend_Off(struct SHEET *KeyDataSendTo);
void KeyDataSend_On(struct SHEET *KeyDataSendTo);
void close_console(struct SHEET *sht, unsigned long mem);
void close_constask(struct TASK *task);

/* 固定ファイル名 */
#define GUIDE_FILE		"guide.txt"
#define ICON_FILE		"data.icd"
#define LOGO_FILE		"logo0.jpg"
#define FONT_FILE		"nihongo.fnt"

void HariMain(void)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
	struct SHTCTL *shtctl;
	char s[40], s2[40];
	struct FIFO32 fifo, keycmd, timer_fifo;
	int fifobuf[128], keycmd_buf[32];
	int mx, my, i, new_mx = -1, new_my = 0, new_wx = 0x7fffffff, new_wy = 0;
	unsigned int memtotal;
	struct MOUSE_DEC mdec;
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	unsigned char *buf_back, buf_mouse[256];
	struct SHEET *sht_back, *sht_mouse;
	struct TASK *task_a, *task, *clock;
	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,   0,   0,   0,   0,   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,   '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,   '_', 0,   0,   0,   0,   0,   0,   0,   0,   0,   '|', 0,   0
	};
	int key_shift = 0, key_leds = (binfo->leds >> 4) & 7, keycmd_wait = -1;
	int j, x = 0, y = 0, mmx = -1, mmy = -1, mmx2 = 0;
	struct SHEET *sht = 0, *KeyDataSendTo, *sht2, *startmenu_sheet = 0;
	int *fat;
	unsigned char *nihongo;
	struct FILEINFO *finfo;
	extern char hankaku[4096];
	char wallbuf[40];
	struct TIMER *timer;
	int wall_flag, timerbuf[32], guide_on = 0,
		icon_on = 0, caption_color = COL8_000000, startm_flag = 0;

	/****************************************

       割り込みPIC/IDT＆マウス＆キーボード

	****************************************/
	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, 0xf8); /* PITとPIC1とキーボードを許可(11111000) */
	io_out8(PIC1_IMR, 0xef); /* マウスを許可(11101111) */
	fifo32_init(&keycmd, 32, keycmd_buf, 0);

	/*************************************

	          メモリーの初期設定

	*************************************/
	memtotal = memtest(0x00400000, 0xbfffffff);
	memman_init(memman);
	memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 0x0009efff */
	memman_free(memman, 0x00400000, memtotal - 0x00400000);

	/*********************************************

      パレットの初期化＆シートコントロール初期化

	*********************************************/
	init_palette();
	shtctl = shtctl_init(memman, binfo->vram, binfo->scrnx, binfo->scrny);
	task_a = task_init(memman);
	fifo.task = task_a;
	task_run(task_a, 1, 2, "SYSTEM");
	*((int *) 0x0fe4) = (int) shtctl;
	task_a->langmode = 0;

	/**********************************************

               背景初期設定＆背景設定
	                   sht_back

	**********************************************/
	fat = (int *)memman_alloc_4k(memman, 4 * 2880);
	file_readfat(fat, (unsigned char *) (ADR_DISKIMG + 0x000200));
	sht_back  = sheet_alloc(shtctl);
	buf_back  = (unsigned char *) memman_alloc_4k(memman, binfo->scrnx * binfo->scrny);
	sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny, -1); /* 透明色なし */
	sht_back->flags |= SHEET_BACK_FLAGS;

	/* 起動時のメッセージ */
	start_screen(buf_back, binfo, fat, LOGO_FILE);
	sheet_slide(sht_back,  0,  0);
	sheet_updown(sht_back,  0);

	fifo32_init(&timer_fifo, 32, timerbuf, 0);
	timer = timer_alloc();
	timer_init(timer, &timer_fifo, 1);
	timer_settime(timer, 300);
	for (;;) {
		if (fifo32_get(&timer_fifo) == 1)
			break;
	}
	timer_free(timer);

	/* 800x600以上はdefault.jpgで、それ以下はnegiwall.jpg */
	strcpy(wallbuf, "negiwall.jpg");
	if (binfo->scrnx > 800 && binfo->scrny > 600)
		strcpy(wallbuf, "default.jpg");
	init_screen8(buf_back, binfo, fat, wallbuf);
	wall_flag = 1;

	/************************************

		   その他もろもろの処理

	************************************/
	taskctl->debug_mode = 0;
	if (set_system32icon(shtctl, ICON_FILE) == 0) {
		icon_on = 1;
		drawicon_sheet(shtctl, buf_back, 47, 20, "Negi Shell", NULL, fat, COL8_000000);
		if (file_search(GUIDE_FILE, (struct FILEINFO *)(ADR_DISKIMG + 0x002600), 224) != 0) {
			drawicon_sheet(shtctl, buf_back, 47, 110, GUIDE_FILE, NULL, fat, COL8_000000);
			guide_on = 1;
		}
	}
	sheet_refresh(sht_back, 0, 0, binfo->scrnx, binfo->scrny);

	/**************************************

             ** シェル＆時計起動 **
	               sht_cons

	**************************************/
	KeyDataSendTo = open_console(shtctl, memtotal);
	clock = open_clocktask(sht_back, buf_back);

	/**************************************

	           ** マウス描写 **
                  sht_mouse

	**************************************/
	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;

	/*************************************

	          ** 描写順序設定 **
	一番下：背景(sht_back)
	二番目：ウィンドウ系(KeyDataSendTo)
	三番目：マウス(sht_mouse)

	※背景の順序はstart_screen関数内で設定
	  されているので、設定する必要なし

	**************************************/
	sheet_slide(sht_back, 0, 0);
	sheet_slide(KeyDataSendTo, 130, 40);
	sheet_slide(sht_mouse, mx, my);
	sheet_updown(sht_back, 0);
	sheet_updown(KeyDataSendTo, 1);
	sheet_updown(sht_mouse, 2);
	KeyDataSend_On(KeyDataSendTo);

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

	/*************************************

		 フォントファイルの読み込み
				nihongo.fnt

	*************************************/
	fat = (int *) memman_alloc_4k(memman, 4 * 2880);
	file_readfat(fat, (unsigned char *) (ADR_DISKIMG + 0x000200));

	finfo = file_search(FONT_FILE, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
	if (finfo != 0) {
		i = finfo->size;
		nihongo = file_loadfile2(finfo->clustno, &i, fat);
	} else {
		nihongo = (unsigned char *) memman_alloc_4k(memman, 16 * 256 + 32 * 94 * 47);
		for (i = 0; i < 16 * 256; i++) {
			nihongo[i] = hankaku[i]; /* フォントがなかったので半角部分をコピー */
		}
		for (i = 16 * 256; i < 16 * 256 + 32 * 94 * 47; i++) {
			nihongo[i] = 0xff; /* フォントがなかったので全角部分を0xffで埋め尽くす */
		}
	}
	*((int *) 0x0fe8) = (int) nihongo;
	memman_free_4k(memman, (int) fat, 4 * 2880);

	/************************************

		  キーボード＆マウス処理

	************************************/
	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 (KeyDataSendTo != 0 && KeyDataSendTo->flags == 0) {	/* ウィンドウが閉じられた */
				if (shtctl->top == 1) {	/* もうマウスと背景しかない */
					KeyDataSendTo = 0;
				} else {
					KeyDataSendTo = shtctl->sheets[shtctl->top - 1];
					KeyDataSend_On(KeyDataSendTo);
				}
			}
			if (ADD_KEYDATA <= i && i <= 511) { /* キーボードデータ */
				if (i < 0x80 + ADD_KEYDATA) { /* キーコードを文字コードに変換 */
					if (key_shift == 0) {
						s[0] = keytable0[i - ADD_KEYDATA];
					} else {
						s[0] = keytable1[i - ADD_KEYDATA];
					}
				} 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 && KeyDataSendTo != 0) { /* 通常文字、バックスペース、Enter */
					fifo32_put(&KeyDataSendTo->task->fifo, s[0] + ADD_KEYDATA);
				}
				if (i == ADD_KEYDATA + 0x0f && KeyDataSendTo != 0 && key_shift != 0) {	/* Tab+Shift */
					KeyDataSend_Off(KeyDataSendTo);
					j = KeyDataSendTo->height - 1;
					if (j == 0) {
						j = shtctl->top - 1;
					}
					KeyDataSendTo = shtctl->sheets[j];
					KeyDataSend_On(KeyDataSendTo);
				}
				if (i == ADD_KEYDATA + LEFT_SHIFT_ON) {	/* 左シフト ON */
					key_shift |= 1;
				}
				if (i == ADD_KEYDATA + RIGHT_SHIFT_ON) {	/* 右シフト ON */
					key_shift |= 2;
				}
				if (i == ADD_KEYDATA + LEFT_SHIFT_OFF) {	/* 左シフト OFF */
					key_shift &= ~1;
				}
				if (i == ADD_KEYDATA + RIGHT_SHIFT_OFF) {	/* 右シフト OFF */
					key_shift &= ~2;
				}
				if (i == ADD_KEYDATA + CAPSLOCK_ON) {	/* CapsLock */
					key_leds ^= 4;
					fifo32_put(&keycmd, KEYCMD_LED);
					fifo32_put(&keycmd, key_leds);
				}
				if (i == ADD_KEYDATA + NUMLOCK_ON) {	/* NumLock */
					key_leds ^= 2;
					fifo32_put(&keycmd, KEYCMD_LED);
					fifo32_put(&keycmd, key_leds);
				}
				if (i == ADD_KEYDATA + SCRLLOCK_ON) {	/* ScrollLock */
					key_leds ^= 1;
					fifo32_put(&keycmd, KEYCMD_LED);
					fifo32_put(&keycmd, key_leds);
				}
				if (i == ADD_KEYDATA + KEYCODE_F1 && key_shift != 0 && KeyDataSendTo != 0) {	/* Shift+F1 */
					task = KeyDataSendTo->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, task->tasknm);	/* 終了処理を確実にやらせるために、寝ていたら起こす */
					}
				}
				if (i == ADD_KEYDATA + KEYCODE_F2 && key_shift != 0) {	/* Shift+F2 */
					/* 新しく作ったコンソールを入力選択状態にする（そのほうが親切だよね？） */
					if (KeyDataSendTo != 0) {
						KeyDataSend_Off(KeyDataSendTo);
					}
					KeyDataSendTo = open_console(shtctl, memtotal);
					sheet_slide(KeyDataSendTo, 130, 40);
					sheet_updown(KeyDataSendTo, shtctl->top);
					KeyDataSend_On(KeyDataSendTo);
				}
				if (i == ADD_KEYDATA + KEYCODE_F11) {	/* F11 */
					sheet_updown(shtctl->sheets[1], shtctl->top - 1);
				}
				if (i == ADD_KEYDATA + KEYCODE_F12 && key_shift != 0) {	/* F12+Shift */
					/* タスクマンを起動する処理 */
					if (KeyDataSendTo != 0) {
						KeyDataSend_Off(KeyDataSendTo);
					}
					KeyDataSendTo = open_taskman(shtctl, memtotal);
					sheet_slide(KeyDataSendTo, 50, 30);
					sheet_updown(KeyDataSendTo, shtctl->top);
					KeyDataSend_On(KeyDataSendTo);
				}
				if (i == ADD_KEYDATA + KEYCODE_F7 && key_shift != 0) {	/* F7+Shift */
					/* 壁紙表示のON/OFF */
					if (wall_flag) {
						init_screen8(buf_back, binfo, fat, 0);
						wall_flag = 0;
					} else {
						strcpy(wallbuf, "negiwall.jpg");
						if (binfo->scrnx > 800 && binfo->scrny > 600)
							strcpy(wallbuf, "default.jpg");
						init_screen8(buf_back, binfo, fat, wallbuf);
						wall_flag = 1;
					}
					if (icon_on) {
						if (wall_flag) { caption_color = COL8_000000; }
						else  { caption_color = COL8_FFFFFF; }
						drawicon_sheet(shtctl, buf_back, 47, 20, "Negi Shell", NULL, fat, caption_color);
						if (file_search(GUIDE_FILE, (struct FILEINFO *)(ADR_DISKIMG + 0x002600), 224) != 0) {
							drawicon_sheet(shtctl, buf_back, 47, 110, GUIDE_FILE, NULL, fat, caption_color);
							guide_on = 1;
						} else guide_on = 0;
					}
					sheet_refresh(sht_back, 0, 0, binfo->scrnx, binfo->scrny);
				}
				if (i == ADD_KEYDATA + KEYCODE_F3 && key_shift != 0) {	/* Shift + F3 */
					if (!startm_flag) {
						/* スタートメニュー表示 */
						startmenu_sheet = open_startmenu_task(shtctl);
						sheet_slide(startmenu_sheet, 0, binfo->scrny - 244);
						sheet_updown(startmenu_sheet, shtctl->top);
						KeyDataSend_On(startmenu_sheet);
						startm_flag = 1;
					} else {
						sheet_updown(startmenu_sheet, -1);
						close_startmenu_task(startmenu_sheet->task, startmenu_sheet, 300 * 200);
						startm_flag = 0;
					}
					fifo32_put(&fifo, ADD_KEYDATA + RIGHT_SHIFT_OFF);
				}
				if (i == ADD_KEYDATA + KBDATA_SUCCESS) {	/* キーボードがデータを無事に受け取った */
					keycmd_wait = -1;
				}
				if (i == ADD_KEYDATA + KBDATA_FAILES) {	/* キーボードがデータを無事に受け取れなかった */
					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;
					}
					new_mx = mx;
					new_my = my;
					if ((mdec.btn & 0x01) != 0) {
						/* 左ボタンを押している */
						if (mmx < 0) {
							put_debugmessage32("clicked by mouse...", 3);
							/* 通常モードの場合 */
							/* 上の下じきから順番にマウスが指している下じきを探す */
							sprintf(s, "window count %d", shtctl->top - 1);
							put_debugmessage32(s, 6);
							if (0 == shtctl->top - 1) {		/* メニュー表示命令を送信 */
								if (79 >= (int)mx && binfo->scrny - 24 <= (int)my) {
									put_debugmessage32("Clicked start menu!!", 5);
									fifo32_put(&fifo, ADD_KEYDATA + RIGHT_SHIFT_ON);
									fifo32_put(&fifo, ADD_KEYDATA + KEYCODE_F3);
									continue;
								}
							}
							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) {
									put_debugmessage32("clicked any window.", 2);
									KeyDataSend_On(KeyDataSendTo);
									if (sht->buf[y * sht->bxsize + x] != sht->col_inv) {
										sheet_updown(sht, shtctl->top - 1);
										if (sht != KeyDataSendTo) {
											KeyDataSend_Off(KeyDataSendTo);
											KeyDataSendTo = sht;
											KeyDataSend_On(KeyDataSendTo);
										}									
										if (3 <= x && x < sht->bxsize - 3 && 3 <= y && y < 21 
													&& (sht->flags & SHEET_STARTMENU_FLAGS) == 0) {
											mmx = mx;	/* ウィンドウ移動モードへ */
											mmy = my;
											mmx2 = sht->vx0;
											new_wy = sht->vy0;
										}
										if (sht->bxsize - 21 <= x && x < sht->bxsize - 5 && 5 <= y && y < 19 
																&& (sht->flags & SHEET_STARTMENU_FLAGS) == 0) {
											/* 「×」ボタンクリック */
											if ((sht->flags & SHEET_APP_FLAGS) != 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, task->tasknm);
												put_debugmessage32("close application by clicked.", 2);
											} else if ((sht->flags & SHEET_CONSOLE_FLAGS) != 0) {	/* シェル */
												task = sht->task;
												sheet_updown(sht, -1); /* とりあえず非表示にしておく */
												KeyDataSend_Off(KeyDataSendTo);
												KeyDataSendTo = shtctl->sheets[shtctl->top - 1];
												KeyDataSend_On(KeyDataSendTo);
												io_cli();
												fifo32_put(&task->fifo, 4);
												io_sti();
												put_debugmessage32("close shell by clicked.", 2);
											} else if ((sht->flags & SHEET_SHTDWN_FLAGS) != 0) {	/* シャットダウン画面 */
												task = sht->task;
												close_shutdown(sht, task, 120 * 315);
												put_debugmessage32("cancel shutdown by clicked.", 2);
											} else if ((sht->flags & SHEET_NEGIMAN_FLAGS) != 0) {		/* negiman */
												task = sht->task; 
												close_taskman(sht, task, 260 * 280);
												put_debugmessage32("close negiman by clicked.", 2);
											} else {
												put_debugmessage32("close any window by clicked.", 2);
											}
										}
										/* メニューアイテムのクリック処理 */
										if ((sht->flags & SHEET_STARTMENU_FLAGS) != 0) {
											if (x >= 0 && x <= 200) {
												if (y >= 25 && y <= 55) {	/* Negitoro Shell */
													put_debugmessage32("clicked item is Negitoro Shell in menu..", 2);
													fifo32_put(&fifo, ADD_KEYDATA + RIGHT_SHIFT_ON);
													fifo32_put(&fifo, ADD_KEYDATA + KEYCODE_F2);	
												} else if (y >= 55 && y <= 80) {		/* Negitoro Maneger */
													put_debugmessage32("clicked item is Negitoro Maneger in menu..", 2);
													fifo32_put(&fifo, ADD_KEYDATA + RIGHT_SHIFT_ON);
													fifo32_put(&fifo, ADD_KEYDATA + KEYCODE_F12);														
												} else if (y >= 80 && y <= 105) {		/* SystemInfo */
													put_debugmessage32("clicked item is SystemInfo in menu..", 2);
												} else if (y >= 105 && y <= 130) {		/* Invader */
													put_debugmessage32("clicked item is Invader in menu..", 2);
												} else if (y >= 130 && y <= 155) { 	/* Simple Timer */
													put_debugmessage32("clicked item is Simple Timer in menu..", 2);
												} else if (y >= 155 && y <= 180) {		/* Simple Editer */
													put_debugmessage32("clicked item is Simple Editer in menu..", 2);
												} else if (y >= 190 && y <= 210) {		/* APM Shutdown */
													put_debugmessage32("clicked item is APM Shutdown in menu..", 2);
													/* シャットダウン画面を開く */
													if (KeyDataSendTo != 0) {
														KeyDataSend_Off(KeyDataSendTo);
													}
													KeyDataSendTo = open_shutdown(shtctl, buf_back, sht_back, task_a, clock);
													sheet_slide(KeyDataSendTo, (binfo->scrnx - 300) / 2, (binfo->scrny - 28 - 150) / 2);
													sheet_updown(KeyDataSendTo, shtctl->top);
													KeyDataSend_On(KeyDataSendTo);												
												}
											}
											fifo32_put(&fifo, ADD_KEYDATA + RIGHT_SHIFT_ON);
											fifo32_put(&fifo, ADD_KEYDATA + KEYCODE_F3);	
										}
										break;
									}
								}							
								/* デスクトップメニューのクリック処理 */
								if ((sht->flags & SHEET_BACK_FLAGS) != 0) {
									put_debugmessage32("Desktop clicked!", 2);		/* 処理を確かめたい！ */									
									if (79 >= (int)mx && binfo->scrny - 24 <= (int)my) {
										put_debugmessage32("Clicked start menu!!", 5);
										fifo32_put(&fifo, ADD_KEYDATA + RIGHT_SHIFT_ON);
										fifo32_put(&fifo, ADD_KEYDATA + KEYCODE_F3);
										break;
									}	
								}								
							}					
						} else {
							/* ウィンドウ移動モードの場合 */
							x = mx - mmx;	/* マウスの移動量を計算 */
							y = my - mmy;
							new_wx = (mmx2 + x + 2) & ~3;
							new_wy = new_wy + y;
							mmy = my;	/* 移動後の座標に更新 */
						}						
					} else {
						/* 左ボタンを押していない */
						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), 300 * 400);
			} 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, 300 * 400);
				sheet_free(sht2);
			}
		}
		put_debugmessage32("Got message of PS/2 Keyboard or Mouse.", 0);
		sprintf(s, "mx = %3d, my = %3d", (int)mx, (int)my);
		put_debugmessage32(s, 1);

		/* テスト */
		sprintf(s, "%3d", (int)sht_mouse->vy0);
		sprintf(s2, "%d", atoi(s));
		put_debugmessage32(s2, 4);
	}
}

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

void KeyDataSend_On(struct SHEET *KeyDataSendTo)
{
	if ((KeyDataSendTo->flags & SHEET_STARTMENU_FLAGS) == 0) { 
		change_wtitle8(KeyDataSendTo, 1);
	}
	if ((KeyDataSendTo->flags & 0x20) != 0) {
		fifo32_put(&KeyDataSendTo->task->fifo, 2); /* コンソールのカーソルON */
	}
	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, 2, 2, "nshell"); /* level=2, priority=2 */
	fifo32_init(&task->fifo, 128, cons_fifo, task);
	return task;
}

struct SHEET *open_console(struct SHTCTL *shtctl, unsigned int memtotal)
{
	const int console_w = 400;		/* コンソール幅 */
	const int console_h = 300;		/* コンソール高さ */

	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	struct SHEET *sht = sheet_alloc(shtctl);
	unsigned char *buf = (unsigned char *) memman_alloc_4k(memman, console_w * console_h);
	sheet_setbuf(sht, buf, console_w, console_h, -1); /* 透明色なし */
	make_window8(buf, console_w, console_h, "Negitoro Shell", 0);
	make_textbox8(sht, 8, 28, 384, 263, COL8_000000);
	sht->task = open_constask(sht, memtotal);
	sht->flags |= SHEET_CONSOLE_FLAGS;	/* カーソルあり */
	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);
	task->flags = 0; /* task_free(task); の代わり */
	return;
}

void close_console(struct SHEET *sht, unsigned long mem)
{
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	struct TASK *task = sht->task;
	task_sleep(sht->task);
	sht->task->flags = 0;
	close_constask(task);
	memman_free_4k(memman, (int)sht->buf, mem);
	sheet_free(sht);
	return;
}
