/*-
 * Copyright (c) 2001
 * Tatsuya Kudoh(CDR/TK),ROYALPANDA.    All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include<stdlib.h>
#include<sys/bios.h>
#include<fcntl.h>
#include"ks.h"
#include"regg.h"
#include"malloc.h"

#pragma noregalo


#define DIC_FILE	"/rom0/urp_dic"
#define UDIC_FILE	"/ram0/regg.dat"

#define TEXT_FILE	"/ram0/ksnote.txt"


static KSTextArea *Text;

static int EditMode = 0;
	
static unsigned char FilenameBuf[128];
static unsigned char *Filename;

static unsigned *CutBuffer = NULL;

#define CMD_CANCEL	0
#define CMD_PASTE	1
#define CMD_REGION	2
#define CMD_SAVE	3
#define CMD_QUIT	4
#define CMD_SAVE_QUIT	5
#define CMD_FORCE_QUIT	6

#define CMD_COPY	7
#define CMD_CUT		8
#define CMD_DELETE	9


static void check_save( void );

static int menuhandler( KSMsg *msg )
{
	if( msg->type == KS_MSG_MENU ){
		switch( (int)msg->menu.call_data ){
		case CMD_CANCEL:
			KSTextAreaResetMark(Text);
			EditMode = 0;
			break;

		case CMD_PASTE:
			KSTextAreaResetMark(Text);
			KSTextAreaInsert(Text,CutBuffer);
			EditMode = 0;
			break;
			
		case CMD_REGION:
			KSTextAreaSetMark(Text);
			EditMode = 1;
			break;

		case CMD_SAVE:
			KSTextAreaWriteFile(Text,Filename);
			break;

		case CMD_QUIT:
			if( Text->update_flag )
				check_save();
			else
				KSSetExitFlag();
			break;

		case CMD_SAVE_QUIT:
			if( KSTextAreaWriteFile(Text,Filename) < 0 )
				key_wait();
			KSSetExitFlag();
			break;

		case CMD_FORCE_QUIT:
			KSSetExitFlag();
			break;

		case CMD_COPY:
			KSFree(CutBuffer);
			CutBuffer = KSTextAreaCopyRegion(Text);
			KSTextAreaResetMark(Text);
			EditMode = 0;
			break;

		case CMD_CUT:
			KSFree(CutBuffer);
			CutBuffer = KSTextAreaCopyRegion(Text);
			if( CutBuffer != NULL )
				KSTextAreaDeleteRegion(Text);
			KSTextAreaResetMark(Text);
			EditMode = 0;
			break;

		case CMD_DELETE:
			KSTextAreaDeleteRegion(Text);
			KSTextAreaResetMark(Text);
			EditMode = 0;
			break;
		}
	}
	return 0;
}


static void check_save( void )
{
	KSMenuCreate("ファイルは更新されています",NULL,NULL);
	KSMenuAddItem("保存して終了",menuhandler,(void*)CMD_SAVE_QUIT);
	KSMenuAddItem("編集内容を破棄して終了",menuhandler,(void*)CMD_FORCE_QUIT);
	KSMenuStart();
}


static void edit( void )
{
	if( EditMode == 0  ){
		KSMenuCreate("メニュー",NULL,NULL);
		if( CutBuffer )
			KSMenuAddItem("貼り付け",menuhandler,(void*)CMD_PASTE);
		else
			KSMenuAddItem("貼り付け",NULL,NULL);
		KSMenuAddItem("範囲指定",menuhandler,(void*)CMD_REGION);
		KSMenuAddItem("保存",menuhandler,(void*)CMD_SAVE);
		KSMenuAddItem("終了",menuhandler,(void*)CMD_QUIT);
		KSMenuStart();
	}else{
		KSMenuCreate("領域編集",menuhandler,(void*)CMD_CANCEL);
		KSMenuAddItem("コピー",menuhandler,(void*)CMD_COPY);
		KSMenuAddItem("切り取り",menuhandler,(void*)CMD_CUT);
		KSMenuAddItem("削除",menuhandler,(void*)CMD_DELETE);
		KSMenuStart();
	}
}


static int handler( KSMsg *msg )
{
	KSTextArea *p;
	unsigned *str;

	p = msg->null.call_data;

	if( msg->type == KS_MSG_STRING ){
		str = msg->string.str;
	}else if( msg->type == KS_MSG_TEXT ){
		str = msg->text.text;
	}else{
		return 0;
	}
	switch( *str ){
	case KEYCODE_UP:
		KSTextAreaPrevLine(p);
		break;
	case KEYCODE_DOWN:
		KSTextAreaNextLine(p);
		break;
	case KEYCODE_LEFT:
		KSTextAreaBackward(p);
		break;
	case KEYCODE_RIGHT:
		KSTextAreaForward(p);
		break;
	case KEYCODE_RETURN:
	case KEYCODE_TAB:
		KSTextAreaInsert(p,str);
		break;
	case KEYCODE_BACKSPACE:
		KSTextAreaDeleteBackward(p,1);
		break;
	case KEYCODE_PRIOR:
		KSTextAreaPageUp(p);
		break;
	case KEYCODE_NEXT:
		KSTextAreaPageDown(p);
		break;
	case KEYCODE_HOME:
		KSTextAreaLineHead(p);
		break;
	case KEYCODE_END:
		KSTextAreaLineEnd(p);
		break;
	case KEYCODE_OPTION:
		edit();
		break;

	default:
		if( *str != 127 && *str >= 32 ){
			KSTextAreaInsert(p,str);
		}
		break;
	}
	return 0;
}


static unsigned atou( char far *s )
{
	unsigned u;

	u = 0;
	while( *s == ' ' || *s == '\t' )
		s++;
	while( *s >= '0' && *s <= '9' )
		u = u * 10 + *s++ - '0';
	return u;
}


static void unpack_string( unsigned far *dst, unsigned char far *src  )
{
	unsigned code;

	while( *src ){
		code = *src++;
		if( code & 0x80 ){
			code = code << 8 | *src++;
			if( (code & 0xff) == 0 )
				break;
		}
		*dst++ = code;
	}
	*dst = 0;
}

static void pack_string( unsigned char far *dst, unsigned far *src  )
{
	unsigned code;

	while( *src ){
		code = *src++;
		if( code & 0x8000 ){
			*dst++ = code >> 8;
			*dst++ = code & 0xff;
		}else{
			*dst++ = code;
		}
	}
	*dst = 0;
}

static int start( KSMsg *msg )
{
	if( msg->type != KS_MSG_TEXT || msg->text.len == 0 ){
		KSSetExitFlag();
		return 0;
	}
	pack_string(FilenameBuf,msg->text.text);
	Filename = FilenameBuf;
	Text = KSTextAreaOpenFile(1,0,24,11,FilenameBuf);
	if( Text == NULL ){
		KSWriteStringToConsole("OpenError\n");
		key_wait();
		KSSetExitFlag();
		return 1;
	}

	KSRegistWindow(&Text->win);
	KSTextAreaShowCursor(Text);
	KSStartReggFEP(handler,Text);

	return 0;
}


int main( int argc, char **argv )
{
	unsigned char far *Dic;
	int size;
	unsigned buf[20];

	KSInitialize();
	Dic = mmap(DIC_FILE);
	REGG_set_dictionary(Dic);
	REGG_init_udic(UDIC_FILE);

	KSStartReggFEP(handler,NULL);

	KSEnableCursor(1);


	if( argc > 1 ){
		Filename = argv[1];
		if( argc > 2 ){
			size = atou(argv[2]);
			if( size < 1 )
				size = 1;
			KSTextAreaSetNewFileSize(size);
		}
		Filename = argv[1];
		Text = KSTextAreaOpenFile(1,0,24,11,Filename);
		if( Text == NULL ){
			KSWriteStringToConsole("OpenError\n");
			key_wait();
			return 1;
		}

		KSRegistWindow(&Text->win);
		KSTextAreaShowCursor(Text);
		KSStartReggFEP(handler,Text);
	}else{
		unpack_string(buf,TEXT_FILE);
		KSLineInput("開くファイル名の入力",buf,start,NULL);
	}

	KSMainLoop();

	REGG_save(UDIC_FILE);

	return 0;
}
