/*
	ARTemis (Graphic Editor for FM-TOWNS)
	(c) MATSUUCHI Ryosuke 1992

	artemis.c
*/

// #define DEBUG

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <egb.h>
#include <mos.h>
#include <stdarg.h>
#include <fmcfrb.h>

#define	MODULE_MAIN
#include "ge.h"
#include "plt16.h"
#include "imageman.h"
#include "dispman.h"
#include "mask.h"
#include "mainmenu.h"

/*--------------------------------------------------------*/
/*                        変数宣言                        */
/*--------------------------------------------------------*/


int		mode;				// MODE16, MODE32K
int		white = 32767;		// 画面モード scrmode での「白」色を表す色コード
int		minzoomrate = 1;	// 拡大率の最小値

int		pltnum;
				// 現在選択しているパレットの番号(0..15)
				// 16色編集時は、これがそのまま描画色になるが、
				// ３万色編集時には、plt[pltnum] が描画色である。

MSDAT	ms = {0,0,0,0,OFF,OFF};
				// マウスの状態（座標・ボタン）をあらわす。
				// ms_get により設定される。

int		mixrate = 256;			// 描画濃度
int		blkop = DrawNORMAL;		// コピー／矩形描画時の演算
bool	blkop_edge = YES;		// ３万色編集でのコピー時の黒透過境界補正スイッチ
bool	areaadj = NO;			// 範囲指定時に、座標を大格子上に限定するスイッチ
int		blot_depth = 16;		// にじみペン手続きの再帰回数
int		goshi_para = 128;		// こすりペンのこすれやすさ(0..256)
int		spray_r = 8;			// スプレー半径
int		spray_t = 1;			// スプレー種別 0:ドット, 1:ペン先
int		colmodel = MODEL_RGB;	// 色選びの方法 (MODEL_RGB / MODEL_HLS)
int		csrcol;					// カーソルの色
int		whiteback = NO;			// 起動時の背景色(YES:白  NO:黒)
bool	use_partsave = YES;		// 部分セーブ機能を使うかどうか
bool	use_loadmove = YES;		// ロード位置指定機能を使うかどうか
int		forecol, backcol;
int		font12seg;				// 12dot font が存在するセグメント
char	debugmsg[128];			// デバッグメッセージの出力バッファ


bool	ryosuke = NO;			// 作者専用オプションが指定されたかどうか
bool	ryosuke_pat = NO;		// 作者専用オプション２が指定されたかどうか

bool	debug = NO;				// デバッグスイッチ


static	int		_editxlen,_editylen;
static	bool	_lat1disp,_lat2disp;
static	bool	_lat2xlen,_lat2ylen;
static	int		_zoomrate;


/*--------------------------------------------------------*/
/*               デバッグ用メッセージの出力               */
/*--------------------------------------------------------*/


void debug_msg_dummy(char *format, ...)
{
  return;
}

void debug_msg(char *format, ...)
{
  extern void colspc_debugmsg(char *buf);
  char sbuf[200];
  if (!debug)
    return;
  va_list ap;
  va_start(ap, format);
  FILE *fp;
  fp = fopen("msg","a");
  if (fp!=NULL)
    {
      vfprintf(fp,format, ap);
      fclose(fp);
    }
  va_end(ap);
}


void msgout_abs(char *msg)
{
	FILE *fp;
	fp = fopen("msg","a");
	if (fp!=NULL)
	{
		fprintf(fp,"%s\n",msg);
		fclose(fp);
	}
}


void msgout(char *msg)
{
	if (debug)
		msgout_abs(msg);
}

/*--------------------------------------------------------*/
/*                 変数の初期化・チェック                 */
/*--------------------------------------------------------*/


static int initVar()
{
	int i;
	mode = MODE32K;
	pltnum=PLTNUM-1;
	white = 32767;
	colmodel = MODEL_RGB;
	csrcol = COL_cursorLight;
	_editxlen = 512, _editylen = 480;
	_lat1disp = _lat2disp = NO;
	_lat2xlen = _lat2ylen = 16;
	_zoomrate = 2;
	mixrate = 256;
	extern int mma_allocSeg(char* segname);
	font12seg = mma_allocSeg("FONT");
	return 0;
}



static void checkPara()	// 動作状態設定に矛盾があれば直す
{
	minzoomrate = 1;
	if (mode == MODE32K)
	{
		if (_editxlen < 320)
			_editxlen = 320;
		else if (_editylen < 240)
			_editylen = 240;
		if (_editxlen < 512 || _editylen < 480)
			minzoomrate = 2;
	}
	if (_zoomrate < minzoomrate)
		_zoomrate = minzoomrate;
}



static int initIO()
{
	static	int		_plt32K[] =
		{ 0, 0, GRB(21, 0, 0), GRB(31,20,10),
		  GRB( 0, 0,31), GRB(13, 5,31), GRB( 0,22, 0), GRB(23, 3,31),
		  GRB( 6,31, 0), GRB(16,31, 5), GRB(31,31, 0), GRB(23,31,19),
		  GRB(10, 0, 0), GRB( 0,31,31), GRB(14,14,14), GRB(31,31,31) };
	static	int		_plt16[] =
		{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };

	DMnew(0);
	key_init();
	minit();
	MOS_resolution(0,(DMgetifonepage() ? 17 : 3));
	MOS_writePage(0);

	int_init();
	plt_init();
	if (!DMgetifonepage())
	{
		page_edit();
		#if 0
		if (mode == MODE32K)
			memcpy(plt, _plt32K, sizeof(int)*16);
		else if (mode == MODE16)
		{
			memcpy(plt, _plt16, sizeof(int)*16);
			if (plt16_init() != 0)	exit(0);
		}
		#endif
		page_menu();
	}
	else
	{
		#if 0
		if (mode == MODE32K)
			memcpy(plt, _plt32K, sizeof(int)*16);
		else if (mode == MODE32K)
		{
			memcpy(plt, _plt16, sizeof(int)*16);
			if (plt16_init() != 0)	exit(0);
		}
		#endif
	}
	return 0;
}


/*--------------------------------------------------------*/
/*                     画面の初期描画                     */
/*--------------------------------------------------------*/


static void iniScr()
{
	DEBUG_MSG("iniScr begin");
	if (whiteback)
	{
		EIMrboxfill(0,0,EIMgetxsize(),EIMgetysize(),white,DrawNORMAL);
		forecol = 0,  backcol = white;
	}
	else
		forecol = white,  backcol = 0;
	DEBUG_MSG("(iniScr) --- A");
	DMimage_setzoomrate(_zoomrate);
	DMimage_setlatticeswitch(_lat1disp,_lat2disp);
	DMimage_setlatticesize(_lat2xlen,_lat2ylen);
	DEBUG_MSG("(iniScr) --- B");
	DEBUG_MSG("iniScr end");
}


/*--------------------------------------------------------*/
/*                 設定ファイルの読み書き                 */
/*--------------------------------------------------------*/


#define	CFG_NAME	"artemis.cfg"
static char config_fname[128] = {0};


static void loadConfig()
{
	_searchenv(CFG_NAME, "PATH", config_fname);
	if (config_fname[0] == 0)
	{
		_searchenv(CFG_NAME, "PATH386", config_fname);
		if (config_fname[0] == 0)
			return; // ファイルが存在しない
	}
	FILE *fp;
	if ((fp = fopen(config_fname, "r")) == NULL)
		return;		// たぶんありえない
	char linbuf[256];
	while (fgets(linbuf, 256, fp) != NULL)
	{
		static char limits[] = " \t\n.,:;=";
		char *p;
		if ((p = strtok(linbuf,limits)) == NULL)
			continue;
		if (strcmp(p, "zoomrate") == 0)
			_zoomrate = atoi(strtok(NULL,limits));
		else if (strcmp(p, "lattice1") == 0)
			_lat1disp = (strcmp(strtok(NULL,limits),"on") == 0 ? YES : NO);
		else if (strcmp(p, "lattice2") == 0)
			_lat2disp = (strcmp(strtok(NULL,limits),"on") == 0 ? YES : NO);
		else if (strcmp(p, "lat2size") == 0)
		{
			_lat2xlen = atoi(strtok(NULL,limits));
			_lat2ylen = atoi(strtok(NULL,limits));
		}
		else if (strcmp(p, "mixrate") == 0)
			mixrate = atoi(strtok(NULL,limits));
		else if (strcmp(p, "blkop") == 0)
			blkop = atoi(strtok(NULL,limits));
		else if (strcmp(p, "blkop_edge") == 0)
			blkop_edge = (strcmp(strtok(NULL,limits),"on") == 0 ? YES : NO);
		else if (strcmp(p, "areaadj") == 0)
			areaadj = (strcmp(strtok(NULL,limits),"on") == 0 ? YES : NO);
		else if (strcmp(p, "blot_para") == 0)
			blot_depth = atoi(strtok(NULL,limits));
		else if (strcmp(p, "goshi_para") == 0)
			goshi_para = atoi(strtok(NULL,limits));
		else if (strcmp(p, "spray_r") == 0)
			spray_r = atoi(strtok(NULL,limits));
		else if (strcmp(p, "spray_t") == 0)
			spray_t = atoi(strtok(NULL,limits));
		else if (strcmp(p, "colmodel") == 0)
			colmodel = atoi(strtok(NULL,limits));
		else if (strcmp(p, "csrcol") == 0)
			csrcol = atoi(strtok(NULL,limits));
		else if (strcmp(p, "backcol") == 0)
			whiteback = (strcmp(strtok(NULL,limits),"white") == 0 ? YES : NO);
		else if (strcmp(p, "partsave") == 0)
			use_partsave = (strcmp(strtok(NULL,limits),"YES") == 0 ? YES:NO);
		else if (strcmp(p, "loadmove") == 0)
			use_loadmove = (strcmp(strtok(NULL,limits),"YES") == 0 ? YES:NO);
	}
	fclose(fp);
}


static void saveConfig()
{
	if (config_fname[0] == 0)
		strcpy(config_fname,CFG_NAME);
	if (fexist(config_fname))
	{
		if (resetfattr(config_fname) != 0)
			return;
	}
	FILE *fp;
	if ((fp = fopen(config_fname,"w")) == NULL)
		return;
	fprintf(fp, "zoomrate   %d\n", DMimage_getzoomrate());
	bool f1,f2;
	int t1,t2;
	DMimage_getlatticeswitch(&f1,&f2);
	fprintf(fp, "lattice1   %s\n", (f1 ? "on":"off"));
	fprintf(fp, "lattice2   %s\n", (f2 ? "on":"off"));
	DMimage_getlatticesize(&t1,&t2);
	fprintf(fp, "lat2size   %d %d\n", t1, t2);
	fprintf(fp, "mixrate    %d\n", mixrate);
	fprintf(fp, "blkop      %d\n", blkop);
	fprintf(fp, "blkop_edge %s\n", (blkop_edge ? "on":"off"));
	fprintf(fp, "areaadj    %s\n", (areaadj ? "on":"off"));
	fprintf(fp, "blot_para  %d\n", blot_depth);
	fprintf(fp, "goshi_para %d\n", goshi_para);
	fprintf(fp, "spray_r    %d\n", spray_r);
	fprintf(fp, "spray_t    %d\n", spray_t);
	fprintf(fp, "colmodel   %d\n", colmodel);
	fprintf(fp, "csrcol     %d\n", csrcol);
	fprintf(fp, "backcol    %s\n", (whiteback ? "white":"black"));
	fprintf(fp, "partsave   %s\n", (use_partsave ? "YES" : "NO"));
	fprintf(fp, "loadmove   %s\n", (use_loadmove ? "YES" : "NO"));
	fclose(fp);
}


/*--------------------------------------------------------*/
/*                    オプション読込                      */
/*--------------------------------------------------------*/


static void getOption(int argc, char *argv[])
{
#define	error_exit(msg)  { printf("%s\n",(msg)); exit(0); }
	char c;
	int i,n;
	char *p;
	for (i=1; i<argc; i++)
	{
		p = argv[i];
		if (*p == '-')
		{
			p++;
			c = tolower(*p);
			switch (c)
			{
			case '0'..'9':
				n = atoi(p);
				switch (n)
				{
				case 16:		// 16 色モード
					// scrmode = 3;
					white = 15;
					// editXlen = 640, editYlen = 480;
					break;
				case 32:		// ３万色モード
					mode = MODE32K;
					white = 32767;
					_editxlen = 320, _editylen = 240;
					break;
				case 3232:		// ３万色モード、高解像度編集
					mode = MODE32K;
					white = 32767;
					_editxlen = 512, _editylen = 480;
					// menumode = 1;
					break;
				case 1616:		// 16色モード、2048×2048ドット編集
					// scrmode = 3;
					white = 15;
					// editXlen = 2048, editYlen = 2048;
					break;
				default:
					error_exit("無効な画面モードです。");
				}
				break;
			case 'x':
				n = atoi(p+1);
				if (n < 1)
					error_exit("編集範囲のＸ方向長の指定が小さすぎます。");
				_editxlen = n;
				break;
			case 'y':
				n = atoi(p+1);
				if (n < 1)
					error_exit("編集範囲のＹ方向長の指定が小さすぎます。");
				_editylen = n;
				break;
			case 'd':
				debug = YES;
				break;
			case 'r':
				if (strncmp(p, "rio2", 4) == 0)
					ryosuke_pat = YES;
				else if (strncmp(p, "rio", 3) == 0)
					ryosuke = YES;
				break;
			case 'm':	// メニューモード
				// menumode = atoi(p+1);
				break;
			case 'h':
			case '?':
				printf("\
ARTemis version 1.2  (C)1993 MATSUUCHI Ryosuke\n\
起動方法: run386 artemis [オプション]\n\
オプション:\n\
    -x<n>    画像の横方向のドット数\n\
    -y<n>    画像の縦方向のドット数\n\
    -h / -?  このメッセージの表示\n\
");
				exit(0);
			}
		}
	}
#undef error_exit
}


/*--------------------------------------------------------*/
/*              オプション設定に従った初期化              */
/*--------------------------------------------------------*/


static int setupAsPara()
{
	pltnum = (whiteback ? 0 : PLTNUM-1);
	if (_editxlen >= 512 && _editylen >= 480 && _zoomrate == 2)
		_zoomrate = 1;
	if (EIMnew(0,_editxlen,_editylen) != 0)
		return -1;
	return 0;
}


/*--------------------------------------------------------*/
/*                         メイン                         */
/*--------------------------------------------------------*/


int main(int argc, char *argv[])
{
  if (initVar() != 0)
    {
      printf("メモリが不足しています(1)\n");
      exit(0);
    }
  loadConfig();
  getOption(argc, argv);
  checkPara();
  if (setupAsPara() != 0)
    {
      printf("メモリが不足しています(2)\n");
      exit(0);
    }
  DEBUG_MSG("-------- ARTemis start --------");
  if (cbuf_init() != 0 ||
      TIFFinitwork() != 0 || area_init() != 0 || filemenu_init() != 0 ||
      mask_init() != 0 || spray_init() != 0 || mathtbl_init() != 0 ||
      pen_init() != 0)
    {
      printf("メモリが不足しています(3)\n");
      exit(0);
    }
  loadPenData();
  menu_init();
  DEBUG_MSG("menu_init 終了");
  if (initIO() != 0)
    {
      printf("メモリが不足しています(4)\n");
      exit(0);
    }
  DEBUG_MSG("initIO 終了");
  iniScr();
  DEBUG_MSG("iniScr 終了");
  ARTsetintvector();
  DEBUG_MSG(debugmsg);
  
  do_mainmenu();
  
  saveConfig();
  int_end();
  mend();
  DMdelete();
  filemenu_end();
  menu_end();
  pen_end();
  ARTresetintvector();
  mma_freeSeg(font12seg);
  KYB_clic(1);	/* キークリック音オフ */
  return 0;
}

/* end of artemis.c */
