/*
	ARTemis (Graphic Editor for FM-TOWNS)
	(c) MATSUUCHI Ryosuke 1992,1993

	saveload.c
*/


#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <malloc.h>
#include <mos.h>
#include <egb.h>
#include <stdlib.h>

#include "ge.h"
#include <direct.h>
#include "plt16.h"
#include "dispman.h"
#include "imageman.h"
#include "mask.h"


static TIFFinfo	tiffinfo;		// ロードするTIFFファイルに関する情報
static int loadtype;  // 読み込み方式

enum {SAVE_ALL, SAVE_PART};
static	int		savetype;
static 	int		savex1,savey1,savex2,savey2;
static	int		loadx,loady;
static	int		loadxlen,loadylen;

/*--------------------------------------------------------*/
/*                ファイルに関する補助処理                */
/*--------------------------------------------------------*/


static bool fexist(char *fname)
{
	FILE *fp;
	if ((fp = fopen(fname,"r")) == NULL)
		return NO;
	fclose(fp);
	return YES;
}


static int checkFileFormat(char *filename)
// ★ファイルのフォーマットの判断
// -1: ファイルがオープンできない
// 0 : TIFF
// 2 : ベタ
// 3 : MAG
{
	char buf[100];
	FILE *fp;
	if ((fp = fopen(filename,"rb")) == NULL)
		return -1;
	fread(buf, 1,100, fp);
	fclose(fp);
	static char headTIFF[] = {0x49,0x49,0x2a,0x00};
	static char headMAG[] = {'M','A','K','I','0','2',' ',' '};
	if (memcmp(buf,headTIFF,4) == 0)
		return 0;
	else if (memcmp(buf,headMAG,8) == 0)
		return 3;
	else
		return 2;
}


/*--------------------------------------------------------*/
/*                ファイルのセーブ･ロード                 */
/*--------------------------------------------------------*/


#define	DISKBUF	50000	/* グラフィックデータを格納するバッファのサイズ */


// ● ベタ形式でのセーブ･ロード


static void BETASave(char *fname)
{
	FILE *fp;  char *savebuf;  int y,yu;
	if ((savebuf = malloc(DISKBUF)) == NULL)
		{ PRINT("ベタ形式セーブ用ワーク　確保失敗\n"); return; }
	else
		PRINT("ベタ形式セーブ用ワーク　確保成功\n");
	if ((fp = fopen(fname, "wb")) == NULL)
		return;
	int x0,y0,xlen,ylen;
	if (savetype == SAVE_ALL)
		x0=y0=0,xlen=EIMgetxsize(),ylen=EIMgetysize();
	else
		x0=savex1,y0=savey1,xlen=savex2-savex1+1,ylen=savey2-savey1+1;
	yu = DISKBUF / (xlen*2);		// 一回に転送するライン数
	for (y = 0;  y < ylen;  y += yu)
	{
		int yl;	// 今回のループ内処理でセーブする領域のライン数
		yl = _min(yu, ylen-y);
		EIMgetblock(savebuf, x0, y0+y, xlen, yl);
		fwrite(savebuf, 1, xlen*yl*2, fp);
	}
	fclose(fp);
	free(savebuf);
}


static void BETALoad(char *fname)
{
	FILE *fp;  char *loadbuf;  int y,yu;
	if ((loadbuf = malloc(DISKBUF)) == NULL)
	{
		DEBUG_MSG("ベタ形式ロード用ワーク　確保失敗");
		return;
	}
	else
		DEBUG_MSG("ベタ形式ロード用ワーク　確保成功");
	if ((fp = fopen(fname, "rb")) == NULL)
		return;
	yu = DISKBUF / (EIMgetxsize()*2);
	for (y = 0;  y < EIMgetysize();  y += yu)
	{
		int yl;  // 今回のループ内処理でロードする領域のライン数
		yl = _min(yu, EIMgetysize()-y);
		fread(loadbuf, 1, EIMgetxsize()*yl*2, fp);
		EIMputblock(0, y, EIMgetxsize(), yl, loadbuf, DrawNORMAL);
	}
	fclose(fp);
	free(loadbuf);
}


static int readEditBuf(char *buf, int yofs, int ylen)
{
	if (savetype == SAVE_ALL)
		EIMgetblock(buf, 0,yofs, EIMgetxsize(), ylen);
	else
		EIMgetblock(buf, savex1,savey1+yofs, savex2-savex1+1, ylen);
	return 0;
}


static int writeEditBuf(char *buf, int yofs, int ylen)
{
	int mosdisp = MOS_getDisp(NULL,NULL) & 0xff;
	if (mosdisp)
		MOS_disp(0);
	if (loadtype == 0)
		{ MOFF;
		  EIMputblock(loadx,loady+yofs,loadxlen,ylen, buf,DrawNORMAL);
		  MON; }
	else
		matte_putblock(loadx,loady+yofs,loadxlen,ylen, buf,blkop);
	if (mosdisp)
		MOS_disp(1);
	return 0;
}


// ● 種々の形式でセーブ･ロードする


static void SaveScreen(char *fname[], int format)
{
	int r;
	char pathbuf[_MAX_PATH];
	add_fname_ext(pathbuf, fname[0],
				  (format==0||format==1 ? "TIF" : "VRM"));
	if (fexist(pathbuf))
	{
		char strbuf[200];
		sprintf(strbuf, "ファイル\"%s\"がすでに存在します。"
						"上書きしてよいですか？", pathbuf);
		if (check_yes_no(strbuf) != 0)
			return;
	}
	switch (format)
	{
	case 0:
	case 1:
		if (!DMgetifonepage())
			mous_type(2,moscsr_timer());
		else
			{ MOS_resolution(0,17); mous_typeRom(82); }
		MOS_disp(1);
		page_edit();  // TIFFsave をダマすために必須
		TIFFsave_getimagefunc(readEditBuf);
		if (savetype == SAVE_ALL)
			r = TIFFsave( pathbuf, 0, 0, EIMgetxsize(),EIMgetysize(),
						  (format==0?YES:NO) );
		else
			r = TIFFsave( pathbuf, savex1, savey1,
						  savex2-savex1+1, savey2-savey1+1,
						  (format==0 ? YES:NO) );
		page_menu();
		MOS_disp(0);
		if (DMgetifonepage())
			MOS_resolution(0,3);
		break;
	case 2:	// ベタ
		page_edit();
		BETASave(pathbuf);
		r = 0;
		page_menu();
		break;
	}
	if ((format==0||format==1) && r!=0)
	{
		switch (r)
		{
		case -1: dispAttentionMsg("ファイル名が異常です");           break;
		case -2: dispAttentionMsg("作業のためのメモリが足りません"); break;
		case -3: dispAttentionMsg("ディスクの残り容量が足りません"); break;
		default: dispAttentionMsg("TIFFsave 関数エラー");
		}
	}
}


static void LoadScreen(char *fname[], int _loadtype)
{
	loadtype = _loadtype;
	int f;
	if ((f = checkFileFormat(fname[0])) == -1)
		{ dispAttentionMsg("ファイルがありません！");  return; }
	loadx = loady = 0;
	if (f == 0)
	{
		if (TIFFgetinfo(fname[0], &tiffinfo) == 0)
			loadxlen = tiffinfo.xlen,  loadylen = tiffinfo.ylen;
		else
			{ dispAttentionMsg("TIFFファイル形式が異常です！？");  return; }
	}
	else
		loadxlen = EIMgetxsize(),  loadylen = EIMgetysize();
	if ( f == 0 && use_loadmove &&
	     ( loadxlen <= EIMgetxsize() && loadylen <= EIMgetysize() )
	     && ! (loadxlen == EIMgetxsize() && loadylen == EIMgetysize() ) )
	{
		int lat2xlen,lat2ylen;
		DMimage_getlatticesize(&lat2xlen,&lat2ylen);
		void drawcsr(int msx,int msy)
		{
			MOFF;
			int tx=DMimage_getx(msx), ty=DMimage_gety(msy);
			if (areaadj)
				tx = tx - tx % lat2xlen, ty = ty - ty % lat2ylen;
			EIMrboxline(tx,ty,loadxlen,loadylen,white,DrawXOR);
			MON;
		}
		int zr = DMimage_getzoomrate();
		scrollForCsr(loadxlen*zr,loadylen*zr);
		for (;;)
		{
			int prex,prey;
			if (areaadj)
				DMdispcsr(ms.x,ms.y);
			drawcsr((prex=ms.x),(prey=ms.y));
			do {
				ms_get(&ms);
			} while (ms.dx==0 && ms.dy==0 && ms.btn1==OFF && ms.btn2==OFF &&
					 key_chk() == 0);
			if (areaadj)
				DMerasecsr();
			drawcsr(prex,prey);		// 消去
			scrollForCsr(loadxlen*zr,loadylen*zr);
			if (ms.btn1 == OFFON)
			{
				loadx = DMimage_getx(ms.x),  loady = DMimage_gety(ms.y);
				if (areaadj)
					loadx -= loadx % lat2xlen,  loady -= loady % lat2ylen;
				break;
			}
			if (ms.btn2 == OFFON)
				goto NOLOAD;
		}
	}
	switch(f)
	{
	case 0:
		if (!DMgetifonepage())
			mous_type(2,moscsr_timer());
		else
			{ MOS_resolution(0,17);  mous_typeRom(82); }
		MOS_disp(1);
		page_edit();
		if (TIFFgetinfo(fname[0], &tiffinfo) == 0)
			{ TIFFload_putimagefunc(writeEditBuf);
			  TIFFload(fname[0],0,0); }
		page_menu();
		MOS_disp(0);
		if (DMgetifonepage())
			MOS_resolution(0,3);
		break;
	case 2:
		page_edit();
		BETALoad(fname[0]);
		page_menu();
		break;
	case 3:
		page_edit();
		MAG_easyLoad(fname[0]);
		EIMbackup();
		page_menu();
		break;
	}
	if (mode == MODE16)
		plt16_init();
	NOLOAD:
	;
}


/*--------------------------------------------------------*/
/*                      画像のセーブ                      */
/*--------------------------------------------------------*/


#include "saveload.md"

#define	S(id)	menu_selector(&savemenu,id)
#define	B(id)	menu_scrollbar(&savemenu,id)

static void SETBAR(int id, int allsize, int dispsize)
{
	SCROLLBAR *bp = B(id);
	menu_scrollbar_setallsize(bp, allsize);
	menu_scrollbar_setdispsize(bp, dispsize);
}

void commandSave()
{
	if (!use_partsave)
	{
		savetype = SAVE_ALL;
		goto NOMENU;
	}
	int xmax,ymax;
	xmax = EIMgetxsize()-1, ymax = EIMgetysize()-1;
	SETBAR(barSAVESTARTX, xmax+(xmax/7), xmax/7);
	SETBAR(barSAVESTARTY, ymax+(ymax/7), ymax/7);
	SETBAR(barSAVEENDX, xmax+(xmax/7), xmax/7);
	SETBAR(barSAVEENDY, ymax+(ymax/7), ymax/7);
	static bool inibarvar = NO;
	if (!inibarvar)
	{
		inibarvar = YES;
		menu_scrollbar_setvar(B(barSAVESTARTX),0);
		menu_scrollbar_setvar(B(barSAVESTARTY),0);
		menu_scrollbar_setvar(B(barSAVEENDX),xmax);
		menu_scrollbar_setvar(B(barSAVEENDY),ymax);
	}
	menu_disp(&savemenu);
	for (;;)
	{
		DMdispcsr(ms.x,ms.y);
		do { ms_get(&ms); }
		while (ms.dx==0 && ms.dy==0 && ms.btn1==OFF && ms.btn2==OFF &&
			   key_chk()==0);
		DMerasecsr();
		scrollForCsr(1,1);
		if (ms.btn1 == OFFON)
		{
			int a; SCROLLBAR *sbarp; int ax,ay;
			a = menu_where(ms.x,ms.y,&savemenu, &ax,&ay,&sbarp);
			switch(a)
			{
			case itemMoveMenu:
				menu_move();
				break;
			case itemScrollBar:
				menu_touchscrollbar(sbarp, ax,ay);
				break;
			case itemSelector:
				menu_touchselector(&savemenu);
				break;
			case btnSAVEAREA:
				menu_erase();
				if (area_input(AREA_BOX) == 0)
				{
					int ax1,ay1,ax2,ay2;
					area_getboundxy(&ax1,&ay1,&ax2,&ay2);
					menu_scrollbar_setvar(B(barSAVESTARTX), ax1);
					menu_scrollbar_setvar(B(barSAVESTARTY), ay1);
					menu_scrollbar_setvar(B(barSAVEENDX), ax2);
					menu_scrollbar_setvar(B(barSAVEENDY), ay2);
				}
				menu_disp(&savemenu);
				break;
			case btnSAVEEXEC:
				menu_erase();
				goto ENDLOOP;
			case btnSAVECANCEL:
				menu_erase();
				goto NOSAVE;
			}
		}
		else if (ms.btn2 == OFFON)
		{
			menu_erase();
			goto NOSAVE;
		}
	}
	ENDLOOP:
	savetype = (menu_selector_getvar(S(selSAVETYPE))==0? SAVE_ALL: SAVE_PART);
	#define BVAR(id) menu_scrollbar_getvar(B(id))
	savex1 = BVAR(barSAVESTARTX);
	savey1 = BVAR(barSAVESTARTY);
	savex2 = BVAR(barSAVEENDX);
	savey2 = BVAR(barSAVEENDY);
	if (savex1 > savex2) swap(savex1,savex2);
	if (savey1 > savey2) swap(savey1,savey2);
	#undef BVAR
NOMENU:
	static char *xi[] =
	{
		"ファイル形式",
		"[.TIF] 圧縮TIFF",
		"[.TIF] 非圧縮TIFF",
		"[.VRM] ベタ",
		NULL
	};
	file_menu_exp("画像をディスクへ保存する", SaveScreen, xi);
	NOSAVE:
	return;
}

#undef B
#undef S


void commandLoad()
{
	static char *xi[] =
	{
		"読み込み方式",
		"通常ロード",
		"演算ロード",
		NULL
	};
	file_menu_exp("画像をディスクから読み込む", LoadScreen,xi);
}


/* end of saveload.c */
