/*
 * This file is part of the M-Edit program (Copyright 1996 by Vincenzo Morello)
 * Permission to use is hereby granted for any purpose.
 *
 * Contains Object attribute settings utility functions.
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#include "mgui.h"

#define N_FONTS	8

struct {
	char	*name;
	MTFont	font;
} oa_fonts[N_FONTS] = {
	{"SMALL_FONT", SMALL_FONT},
	{"MEDIUM_FONT", MEDIUM_FONT},
	{"DEFAULT_FONT", DEFAULT_FONT},
	{"LARGE_FONT", LARGE_FONT},
	{"TIMES_N_FONT", TIMES_N_FONT},
	{"TIMES_L_FONT", TIMES_L_FONT},
	{"HELV_N_FONT", HELV_N_FONT},
	{"HELV_L_FONT", HELV_L_FONT}
};

void RefreshColPickCB(MOBJECT p, void *s, void *v);
void ChangeColorCellCB(MOBJECT o, MVALUE s, void *v);
void AssignForegroundCB(MOBJECT o, void *s, void *v);
void AssignBackgroundCB(MOBJECT o, void *s, void *v);
void CellExposeCB(MOBJECT o, MEvent *pe, void *a_data);
void CellResizeCB(MOBJECT o, DRAWAREA_PREF *pref, void *a_data);
void ColorMapExposeCB(MOBJECT o, MEvent *pexp, void *a_data);
void ColorMapInputCB(MOBJECT o, MEvent *pe, void *a_data);
void ColorMapResizeCB(MOBJECT o, DRAWAREA_PREF *pref, void *a_data);

static MOBJECT r_sbar, g_sbar, b_sbar, sample;
static MOBJECT r_label, g_label, b_label, drawa, cell_drawa;
static MTColor cell_color;
static int sel_cell, sel_x, sel_y, r_c, g_c, b_c;

static MTColor drawarea_bgc;
static long NColors;

static void CloseCB(MOBJECT obj, void *s, void *v)
{
	MFreeColor(drawarea_bgc);
	MFreeCell(cell_color);

	MShellDestroy(obj);
}

static void ApplyCB(MOBJECT obj, void *s, void *adata)
{
	MTColor bgc, fgc;

	bgc = MObjectBackgroundColor(sample);
	fgc = MObjectForegroundColor(sample);
	MObjectSetColor((MOBJECT)adata, bgc, fgc);
	MObjectSetFont((MOBJECT)adata, MObjectGetFont(sample), False);
	MFreeColor(drawarea_bgc);
	MFreeCell(cell_color);

	MShellDestroy(obj);
}

static char *FontIdToName(MTFont fid)
{
	int ii;

	for (ii=0; ii < N_FONTS; ii++)
		if (fid == oa_fonts[ii].font)
			return oa_fonts[ii].name;
	return "DEFAULT_FONT";
}

MTFont FontNameToId(char *name)
{
	int ii;

	for (ii=0; ii < N_FONTS; ii++)
		if (!strcmp(oa_fonts[ii].name, name))
			return oa_fonts[ii].font;
	return DEFAULT_FONT;
}

static void NewFontCB(MOBJECT obj, char *newtext, void *ad)
{
	MTFont font;

	font = FontNameToId(newtext);
	MObjectSetFont(sample, font, False);
}

void ObjAttrPick(MOBJECT obj)
{
	MOBJECT	shell, form, pb, form2, label, list, opt_font;
	int		r, g, b, ii;
	MTColor	bgc, fgc;
	char	*font_name;

	bgc = MObjectBackgroundColor(obj);
	fgc = MObjectForegroundColor(obj);

	MGetDefaultBackgroundRGB(&r, &g, &b);
	drawarea_bgc = MAllocColor(r, g, b);
	NColors = MGetNColors();

	shell = MCreateShell("Object Attributes", SF_MODAL);
	MShellSetWMCloseCallback(shell, CloseCB, NULL);

	form2 = MCreateColForm(shell);

	MFormSetSpacing(form2, 0);

	form = MCreateRowForm(form2);

	sample = MCreateLabel(form, "Sample", MObjectGetFont(obj));
	MObjectSetShadow(sample, WS_ETCHED_IN, 1, 1);
	MObjectSetColor(sample, bgc, fgc);

	pb = MCreatePButton(form, "Assign Foreground", TIMES_L_FONT);
	MPButtonSetCallback(pb, AssignForegroundCB, sample);
	pb = MCreatePButton(form, "Assign Background", TIMES_L_FONT);
	MPButtonSetCallback(pb, AssignBackgroundCB, sample);

	font_name = FontIdToName(MObjectGetFont(obj));
	opt_font = MCreateOptionEdit(form, font_name, 12, 12, 7, DEFAULT_FONT);
	MEditSetNewValueCallback(opt_font, NewFontCB, NULL);
	MObjectSetUnsensitive(opt_font);
	list = MOptionEditGetList(opt_font);
	for (ii=0; ii < N_FONTS; ii++)
		MSListAddItem(list, oa_fonts[ii].name, (void *)oa_fonts[ii].font);

	if (MPaletteMode()) {
		form = MCreateRowForm(form2);
		MFormSetFocusHighlight(form, True);
		drawa = MCreateDrawArea(form, 208, 208);
		MObjectSetResize(drawa, True, True);
		MDrawAreaSetExposeCallback(drawa, ColorMapExposeCB, 0L);
		MDrawAreaSetInputCallback(drawa, ColorMapInputCB, 0L);
		MDrawAreaSetResizeCallback(drawa, ColorMapResizeCB, 0L);
	}

	form = MCreateRowForm(shell);
	cell_drawa = MCreateDrawArea(form, 256, 30);
	MDrawAreaSetExposeCallback(cell_drawa, CellExposeCB, 0L);
	MObjectSetResize(cell_drawa, True, False);
	r_c = g_c = b_c = 0;
	cell_color = MAllocCell(0, 0, 0);

	form2 = MCreateRowForm(form);
	MFormSetPrefAtt(form2, F_PREF_ATT_COL);
	label = MCreateLabel(form2, "Red:   ", DEFAULT_FONT);
	r_label = MCreateLabel(form2, "00", DEFAULT_FONT);
	MObjectSetResize(label, False, False);
	MObjectSetResize(r_label, False, False);
	r_sbar = MCreateScrollBar(form2, SBT_HOR, (long)32, (long)255+32);
	MScrollBarSetPosCallback(r_sbar, ChangeColorCellCB, 0L);

	form2 = MCreateRowForm(form);
	MFormSetPrefAtt(form2, F_PREF_ATT_COL);
	label = MCreateLabel(form2, "Green: ", DEFAULT_FONT);
	g_label = MCreateLabel(form2, "00", DEFAULT_FONT);
	MObjectSetResize(label, False, False);
	MObjectSetResize(g_label, False, False);
	g_sbar = MCreateScrollBar(form2, SBT_HOR, (long)32, (long)255+32);
	MScrollBarSetPosCallback(g_sbar, ChangeColorCellCB, (void *)1);

	form2 = MCreateRowForm(form);
	MFormSetPrefAtt(form2, F_PREF_ATT_COL);
	label = MCreateLabel(form2, "Blue:  ", DEFAULT_FONT);
	b_label = MCreateLabel(form2, "00", DEFAULT_FONT);
	MObjectSetResize(label, False, False);
	MObjectSetResize(b_label, False, False);
	b_sbar = MCreateScrollBar(form2, SBT_HOR, (long)32, (long)255+32);
	MScrollBarSetPosCallback(b_sbar, ChangeColorCellCB, (void *)2);

	form = MCreateColForm(shell);

	pb = MCreatePButton(form, "Apply", TIMES_L_FONT);
	MPButtonSetCallback(pb, ApplyCB, obj);

	pb = MCreatePButton(form, "Cancel", TIMES_L_FONT);
	MPButtonSetCallback(pb, CloseCB, NULL);

	sel_cell = sel_x = sel_y = 0;
	MShellRealize(shell);
}

void ChangeColorCellCB(MOBJECT o, MVALUE o_data, void *a_data)
{
	char str[16];

	switch ((int)a_data) {
		case 0:
			r_c = (int)o_data;
			sprintf(str, "%02x", r_c);
			MObjectSetText(r_label, str);
			break;
		case 1:
			g_c = (int)o_data;
			sprintf(str, "%02x", g_c);
			MObjectSetText(g_label, str);
			break;
		case 2:
			b_c = (int)o_data;
			sprintf(str, "%02x", b_c);
			MObjectSetText(b_label, str);
			break;
	}
	if (MPaletteMode())
		MSetCellColor(cell_color, r_c, g_c, b_c);
	else
		MObjectSetBackgroundRGB(cell_drawa, r_c, g_c, b_c);
}

void AssignBackgroundCB(MOBJECT o, void *o_data, void *a_data)
{
	MObjectSetBackgroundRGB((MOBJECT )a_data, r_c, g_c, b_c);

#ifdef WINDOWS
/*
 *   Windows palette is indirect, so it is
 *   necessary to redraw rectangles with a new color
 */
	if (MPaletteMode())
		ColorMapExposeCB(drawa, NULL, 0L);
#endif
}

void AssignForegroundCB(MOBJECT o, void *o_data, void *a_data)
{
	MObjectSetForegroundRGB((MOBJECT )a_data, r_c, g_c, b_c);

#ifdef WINDOWS
/*
 *   Windows palette is indirect, so it is
 *   necessary to redraw rectangles with a new color
 */
	if (MPaletteMode())
		ColorMapExposeCB(drawa, NULL, 0L);
#endif
}

void ColorPickCB(MOBJECT o, void *o_data, void *a_data)
{
	MOBJECT p = (MOBJECT )a_data;
	int r, g, b;

	MQueryColor(MObjectBackgroundColor(p), &r, &g, &b);
	MScrollBarSetPos(r_sbar, (long)r);
	MScrollBarSetPos(g_sbar, (long)g);
	MScrollBarSetPos(b_sbar, (long)b);
}

void CellExposeCB(MOBJECT obj, MEvent *pexp, void *a_data)
{
	int hsize, wsize;

	wsize = MObjectWidth(obj);
	hsize = MObjectHeight(obj);
	if (MPaletteMode())
		MDrawFilledBox(obj, 0, 0, wsize, hsize, cell_color);
}

void ColorMapExposeCB(MOBJECT obj, MEvent *pexp, void *a_data)
{
	int n, hsize, wsize, i, j;

	n = (NColors == 16 ? 4 : 16);
	wsize = MObjectWidth(obj)/n;
	hsize = MObjectHeight(obj)/n;
	for (i=0; i<n; i++)
		for (j=0; j<n; j++)
			MDrawFilledBox(obj, wsize*j+1, hsize*i+1, wsize-2, hsize-2, i*n+j);
	MDrawBox(obj, sel_x, sel_y, wsize, hsize, MWhiteColor());
}

void ColorMapResizeCB(MOBJECT obj, DRAWAREA_PREF *pref, void *a_data)
{
	int n, new_hsize, new_wsize, old_hsize, old_wsize;

	n = (NColors == 16 ? 4 : 16);
	old_wsize = pref->old_w/n;
	old_hsize = pref->old_h/n;
	new_wsize = pref->new_w/n;
	new_hsize = pref->new_h/n;
	sel_x = (sel_x*new_wsize)/old_wsize;
	sel_y = (sel_y*new_hsize)/old_hsize;
	pref->new_w = new_wsize*n;
	pref->new_h = new_hsize*n;
}

void ColorMapInputCB(MOBJECT obj, MEvent *pe, void *a_data)
{
	int n, hsize, wsize;
	int r, g, b, old_x, old_y;
					      
	n = (NColors == 16 ? 4 : 16);
	wsize = MObjectWidth(obj)/n;
	hsize = MObjectHeight(obj)/n;
	old_x = sel_x;
	old_y = sel_y;
	if (pe->type == E_KEY_PRESS) {
		switch (pe->key.keycode) {
			case U_A:
				sel_cell -= n;
				if (sel_cell < 0)
					sel_cell += (int)NColors;
				break;
			case D_A:
				sel_cell += n;
				if (sel_cell > NColors)
					sel_cell -= (int)NColors;
				break;
			case R_A:
				if (++sel_cell >= (int)NColors)
					sel_cell = 0;
				break;
			case L_A:
				if (--sel_cell < 0)
					sel_cell = (int)NColors-1;
				break;
			default:
				return;
		}
		sel_x = (sel_cell % n)*wsize;
		sel_y = (sel_cell / n)*hsize;
	}
	else if (pe->type == E_BUTTON_PRESS) {
		sel_x = (pe->mouse.x/wsize)*wsize;
		sel_y = (pe->mouse.y/hsize)*hsize;
		sel_cell = sel_x/wsize+sel_y/hsize*n;
	}
	else
        	return;
	MDrawBox(obj, old_x, old_y, wsize, hsize, drawarea_bgc);
	MDrawBox(obj, sel_x, sel_y, wsize, hsize, MWhiteColor());
	MQueryColor(sel_cell, &r, &g, &b);
	MScrollBarSetPos(r_sbar, (long)r);
	MScrollBarSetPos(g_sbar, (long)g);
	MScrollBarSetPos(b_sbar, (long)b);
}
