/***   [disp.c]
*
*	表示方法変更インターフェイスウィンドウ 関連		(C)ささがわ
*
*	For GNU C Compiler (GCC)   Version 1.39
*
***/

#include <stdio.h>
#include <kyb.h>
#include <mos.h>
#include "graph.h"
#include "window.h"
#include "icn.h"
#include "txwind.h"
#include "disp.h"
#include "others.h"
#include "optparse.h"

#define WH_CAN		0
#define WH_TITLE	1
#define WH_ON		2
#define WH_OTHER	-1

extern int	PAL_Back;
extern int	PAL_Black;
static int	wx, wy, pars_lgcol;
static char	pars[5];
static struct txinfo_t	txi = {
	{ 0, 0, NULL, NULL}, "", 0, 0, 0, 0, 16, 1, 0, 8, 80, 0, 4
};
static const short	table[21][5] = {
	{ 30, 101, 49, 64, 10},		{ 30, 101, 69, 84, 11},
	{ 30, 101, 110, 125, 20},	{ 30, 101, 130, 145, 21},
	{ 30, 93, 171, 186, 30},	{ 30, 93, 191, 206, 31},
	{ 102, 165, 171, 186, 32},	{ 102, 165, 191, 206, 33},
	{ 199, 262, 49, 64, 40},	{ 199, 262, 69, 84, 41},
	{ 199, 262, 89, 104, 42},	{ 271, 334, 49, 64, 43},
	{ 271, 334, 69, 84, 44},	{ 199, 334, 130, 145, 50},
	{ 199, 223, 153, 168, 51},	{ 224, 243, 151, 170, 52},
	{ 245, 272, 151, 170, 53},	{ 274, 293, 151, 170, 54},
	{ 6, 25, 6, 25, WH_CAN},	{ 27, 342, 6, 25, WH_TITLE},
	{ 252, 331, 181, 202, WH_ON}
};

static void	Draw_window(void);
static int	Where(int, int);
static void	inkey(void);
static void	disp_keta(int);
static void	OnOff(int, int);
static void	disp_onoff(void);
static void	SUB_on(int);
static void	InDe_lgcol(int);
static int	InDe_lgcol_sub(int);
static void	SUB_setlinegap(int, struct txinfo_t *);

void DSP_init(void) {
	int		i;
	short	p[5];
	
	for (i = 0; i < 5; p[i++] = -1);
	OPT_disp(p);
	
	if (p[0] >= 0)	txi.tabd = p[0];
	if (p[1] >= 0)	txi.crd = p[1];
	if (p[2] >= 0) {
		switch (p[2]) {
			case 1:
			case 2:
			case 4:		txi.tab = p[2];	break;
	  		default:	txi.tab = 8;	break;
		}
	}
	if (p[3] >= 0 && 4 >= p[3])	SUB_setlinegap(p[3], &txi);
	if (p[4] == 0)
		txi.lgcolw = 1;
	else if (20 <= p[4] && p[4] <= 500)
		txi.lgcol = p[4];
}

static void SUB_setlinegap(int n, struct txinfo_t *inf) {
	switch (n) {
		case 0:		inf->linegap = 0;	break;
		case 1:		inf->linegap = inf->fontx / 8;	break;
		case 3:		inf->linegap = inf->fontx / 2;	break;
		case 4:		inf->linegap = inf->fontx * 3 / 4;	break;
		default:	inf->linegap = inf->fontx / 4;	break;
	}
}

void DSP_change(void) {
	WIND_disp(1, &txi, 0, 0);
}

void DSP_set(struct txinfo_t *Info) {
	*Info = txi;
}

int WIND_disp(int mode, struct txinfo_t *Info, int x, int y) {
	int		ret = 0;
	struct RECT	a, b;
	struct txinfo_t	pInfo;
	
	pars[0] = Info->crd ? 0 : 1;
	pars[1] = Info->tabd ? 0 : 1;
	switch (Info->tab) {
		case 1:		pars[2] = 0;	break;
		case 2:		pars[2] = 1;	break;
		case 4:		pars[2] = 2;	break;
		default:	pars[2] = 3;	break;
	}
	if (Info->linegap == 0)	pars[3] = 0;
	else if (Info->linegap == Info->fontx / 8)	pars[3] = 1;
	else if (Info->linegap == Info->fontx / 4)	pars[3] = 2;
	else if (Info->linegap == Info->fontx / 2)	pars[3] = 3;
	else	pars[3] = 4;
	pars[4] = Info->lgcolw ? 0 : 1;
	pars_lgcol = Info->lgcol;
	
	if (mode) {
		wx = 146;
		wy = 133;
		a.x1 = 319;	a.y1 = 259;
		a.x2 = 320;	a.y2 = 260;
		b.x1 = wx;	b.y1 = wy;
		b.x2 = wx + 348;	b.y2 = wy + 214;
		afterImage(&a, &b);
	} else {
		wx = x;
		wy = y;
	}
	
	Draw_window();
	while (!ret) {
		char	mb;
		int		mx, my, wh;
		
		CLOCK(0);
		if (MOS_rdpos(&mb, &mx, &my), !(mb & 1))
			continue;
		
		if ((wh = Where(mx, my)) == WH_CAN) {
			if (Button(wx + 6, wy + 6, wx + 25, wy + 25))
				ret = -1;
		} else if (wh == WH_TITLE) {
			struct RECT	s, w;
			
			w.x1 = wx;	w.y1 = wy;
			w.x2 = wx + 348;	w.y2 = wy + 214;
			s.x1 = 0;	s.y1 = 40;	s.x2 = 639;	s.y2 = 463;
			if (dragWindow(mx, my, &w, &s, 0, 0)) {
				wx = w.x1;	wy = w.y1;
				MOS_disp(0);
				EGB_cls(0);
				MOS_disp(1);
				Draw_window();
			}
		} else if (wh == WH_ON) {
			if (Button(wx + 252, wy + 181, wx + 331, wy + 202))
				ret = 1;
		} else if (wh == WH_OTHER) {
			while (MOS_rdpos(&mb, &mx, &my), mb & 1);
		} else if (wh / 10 == 5) {
			SUB_on(wh > 50 ? 51 : 50);
			
			if (wh == 52 || wh == 54)
				InDe_lgcol(wh == 52 ? 0 : 1);
			else if (wh == 53) {
				if (Button(wx + 245, wy + 151, wx + 272, wy + 170))
					inkey();
			} else
				while (MOS_rdpos(&mb, &mx, &my), mb & 1);
		} else {
			SUB_on(wh);
			while (MOS_rdpos(&mb, &mx, &my), mb & 1);
		}
	}
	if (ret == -1)	return 0;
	
	pInfo = *Info;
	Info->crd = pars[0] ? 0 : 1;
	Info->tabd = pars[1] ? 0 : 1;
	switch (pars[2]) {
		case 0:		Info->tab = 1;	break;
		case 1:		Info->tab = 2;	break;
		case 2:		Info->tab = 4;	break;
		default:	Info->tab = 8;	break;
	}
	SUB_setlinegap(pars[3], Info);
	if (Info->lgcolw = pars[4] ? 0 : 1)	Info->col = 0;
	Info->lgcol = pars_lgcol;
	
	ret = 0;
	if (pInfo.crd != Info->crd)		ret += 1;
	if (pInfo.tabd != Info->tabd)	ret += 2;
	if (pInfo.tab != Info->tab)		ret += 4;
	if (pInfo.linegap != Info->linegap)	ret += 8;
	if (!(pInfo.lgcolw && Info->lgcolw || !pInfo.lgcolw && !Info->lgcolw && pInfo.lgcol == Info->lgcol))
		ret += 16;
	
	return ret;
}

static void Draw_window(void) {
	int		i;
	struct opnwin_t	opw;
	static const char	*str[] = {
		"◆ 改行記号の表示", "○ する", "○ しない",
		"◆ タブ記号の表示", "○ する", "○ しない",
		"◆ タブ長", "○ １    ○ ４", "○ ２    ○ ８",
		"◆ 行間隔", "○ 0     ○ 1/2", "○ 1/8   ○ 3/4", "○ 1/4",
		"◆ 横幅", "○ ｳｨﾝﾄﾞｳ幅と同じ", "○"
	};
	static const short	cord[][2] = {
		{ 14, 44}, { 30, 64}, { 30, 84},
		{ 14, 105}, { 30, 125}, { 30, 145},
		{ 14, 166}, { 30, 186}, { 30, 206},
		{ 183, 44}, { 199, 64}, { 199, 84}, { 199, 104},
		{ 183, 125}, { 199, 145}, { 199, 168}
	};
	
	opw.title = "表示方法の変更";
	opw.x1 = wx;
	opw.y1 = wy;
	opw.x2 = opw.x1 + 348;
	opw.y2 = opw.y1 + 214;
	opw.shdw = 1;
	opw.canb = 1;
	opw.nopt = 0;
	opw.wopt = NULL;
	opw.expb = 0;
	opw.ord = 0;
	MOS_disp(0);
	drawWindow(&opw);
	
	EGB_line(wx + 174, wy + 26, wx + 174, wy + 209, PAL_Black);
	EGB_line(wx + 5, wy + 87, wx + 174, wy + 87, PAL_Black);
	EGB_line(wx + 5, wy + 148, wx + 174, wy + 148, PAL_Black);
	EGB_line(wx + 174, wy + 107, wx + 343, wy + 107, PAL_Black);
	EGB_line(wx + 174, wy + 174, wx + 343, wy + 174, PAL_Black);
	
	for (i = 0; i < 16; i++)
		EGB_str2(str[i], wx + cord[i][0], wy + cord[i][1], PAL_Black);
	
	DrawButton(1, wx + 223, wy + 150, wx + 244, wy + 171);
	EGB_box(wx + 244, wy + 150, wx + 273, wy + 171, PAL_Black);
	DrawButton(1, wx + 273, wy + 150, wx + 294, wy + 171);
	EGB_str2("−", wx + 226, wy + 168, PAL_Black);
	EGB_str2("＋", wx + 276, wy + 168, PAL_Black);
	
	DrawButton(1, wx + 251, wy + 180, wx + 332, wy + 203);
	for (i = 0; i < 2; i++)
		EGB_str2(" 実    行 ", wx + 252 + i, wy + 199, PAL_Black);
	MOS_disp(1);
	disp_onoff();
	disp_keta(0);
}

static void InDe_lgcol(int id) {
	int		flpush = 1, fllast, lx, ly;
	int		mx, my;
	char	mb;
	
	lx = wx + (id ? 274 : 224);
	ly = wy + 151;
	
	EGB_rev(1, lx, ly, lx + 19, ly + 19);
	fllast = InDe_lgcol_sub(id);
	TIMER_set(20);
	
	while (MOS_rdpos(&mb, &mx, &my), mb & 1) {
		int		whres;
		
		whres = Where(mx, my) == (id ? 54 : 52);
		if (!whres && flpush || whres && !flpush) {
			EGB_rev(1, lx, ly, lx + 19, ly + 19);
			flpush = !flpush;
		}
		
		if (flpush && TIMER() && !fllast)
			fllast = InDe_lgcol_sub(id);
	}
	
	if (flpush)
		EGB_rev(1, lx, ly, lx + 19, ly + 19);
}

static int InDe_lgcol_sub(int id) {
	int		result = 1;
	
	if (id && pars_lgcol < 500 || !id && pars_lgcol > 20) {
		id ? pars_lgcol++ : pars_lgcol--;
		disp_keta(0);
		result = 0;
	}
	
	return result;
}

static int Where(int x, int y) {
	int		i, ret = WH_OTHER;
	
	x -= wx;
	y -= wy;
	for (i = 0; i < 21; i++) {
		const short	*p;
		
		p = table[i];
		if (p[0] <= x && x <= p[1] && p[2] <= y && y <= p[3]) {
			ret = p[4];
			break;
		}
	}
	
	return ret;
}

static void inkey(void) {
	int		ret = 0;
	unsigned	kadr, kcode;
	
	pars_lgcol = 0;
	disp_keta(1);
	do {
		int		mx, my;
		char	mb;
		
		kcode = KYB_read(1, &kadr);
		MOS_rdpos(&mb, &mx, &my);
		if (kcode == '\r' || (mb & 1 && Where(mx, my) != 53)) {
			ret = 1;
			break;
		} else if (kcode == 0x1b) {
			pars_lgcol = 0;
			disp_keta(1);
			continue;
		} else if (kcode < '0' || '9' < kcode || pars_lgcol > 99)
			continue;
		
		pars_lgcol *= 10;
		pars_lgcol += kcode - '0';
		disp_keta(1);
	} while (!ret);
	EGB_rev(1, wx + 245, wy + 151, wx + 272, wy + 170);
	
	if (pars_lgcol < 20) {
		pars_lgcol = 20;
		disp_keta(0);
	} else if (pars_lgcol > 500) {
		pars_lgcol = 500;
		disp_keta(0);
	}
}

static void disp_keta(int mode) {
	int		c1, c2;
	char	n[10];
	
	sprintf(n, "%3d", pars_lgcol);
	c1 = mode ? 15 : PAL_Black;
	c2 = mode ? 8 : PAL_Back;
	MOS_disp(0);
	EGB_str3(n, wx + 247, wy + 168, c1, c2);
	MOS_disp(1);
}

static void OnOff(int wh, int sw) {
	int		i, x = 0, y = 0;
	
	for (i = 0; i < 21; i++) {
		if (table[i][4] == wh) {
			x = table[i][0];
			y = table[i][3];
			break;
		}
	}
	
	EGB_str3(sw ? "●" : "○", wx + x, wy + y, PAL_Black, PAL_Back);
}

static void disp_onoff(void) {
	int		i;
	
	MOS_disp(0);
	for (i = 0; i <= 4; i++)
		OnOff((i + 1) * 10 + pars[i], 1);
	MOS_disp(1);
}

static void SUB_on(int wh) {
	int		a;
	
	a = wh / 10;
	a = a * 10 + pars[a - 1];
	if (wh == a)
		return;
	
	MOS_disp(0);
	OnOff(a, 0);
	OnOff(wh, 1);
	pars[wh / 10 - 1] = wh % 10;
	MOS_disp(1);
}
