/*
	$VER: Variator.c 2.0 (12.03.1997) Copyright 1991, 1997 by Dalibor Kezele

	First version: Monday, February 10, 1991
	Last version: Wednesday, Mart 12, 1997

	Source code compiled with Aztec C 5.0a.
	e-mail: dkezele@mia.os.carnet.hr

*/

#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

struct IntuitionBase *IntuitionBase;
struct TextAttr t8f = { (UBYTE *)"topaz.font", 8, 0, 0 };

struct IntuiText
	bit = { 1, 0, JAM1, -35, 0, &t8f, (UBYTE *)"BIN", NULL },
	oit = { 1, 0, JAM1, -35, 0, &t8f, (UBYTE *)"OCT", NULL },
	dit = { 1, 0, JAM1, -35, 0, &t8f, (UBYTE *)"DEC", NULL },
	hit = { 1, 0, JAM1, -35, 0, &t8f, (UBYTE *)"HEX", NULL },
	hgt = { 1, 0, JAM1, 16, 2, &t8f, (UBYTE *)"Help", NULL },
	agt = { 1, 0, JAM1, 12, 2, &t8f, (UBYTE *)"About", NULL },
	qgt = { 1, 0, JAM1, 16, 2, &t8f, (UBYTE *)"Quit", NULL },
	hait[13],
	hagt = { 1, 0, JAM1, 23, 2, &t8f, (UBYTE *)"OK", NULL };

UBYTE
	bms[80] = "", bus[80] = "", oms[80] = "", ous[80] = "",
	dms[80] = "", dus[80] = "", hms[80] = "", hus[80] = "";

struct StringInfo
	bsi = { bms, bus, 0, 33, 0, 0, 33, 0, 0, 0, NULL, 0, NULL },
	osi = { oms, ous, 0, 12, 0, 0, 12, 0, 0, 0, NULL, 0, NULL },
	dsi = { dms, dus, 0, 11, 0, 0, 11, 0, 0, 0, NULL, 0, NULL },
	hsi = { hms, hus, 0, 9, 0, 0, 9, 0, 0, 0, NULL, 0, NULL };

short int
	bc[10] = { 0, 0, 269, 0, 269, 11, 0, 11, 0, 0 },
	oc[10] = { 0, 0, 101, 0, 101, 11, 0, 11, 0, 0 },
	dc[10] = { 0, 0, 93, 0, 93, 11, 0, 11, 0, 0 },
	hc[10] = { 0, 0, 77, 0, 77, 11, 0, 11, 0, 0 },
	qc1[6] = { 0, 10, 0, 0, 65, 0 },
	qc[6] = { 65, 0, 65, 10, 0, 10 },
	tc[13] = { 0, 8, 16, 24, 34, 42, 50, 58, 66, 76, 84, 92, 102 },
	hagc1[6] = { 0, 10, 0, 0, 61, 0 },
	hagc[6] = { 61, 0, 61, 10, 0, 10 };

int
	htc[13] = { 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1 },
	atc[13] = { 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 1, 1 };

struct Border
	bb = { -3, -2, 3, 0, JAM1, 5, (short *)&bc, NULL },
	ob = { -3, -2, 3, 0, JAM1, 5, (short *)&oc, NULL },
	db = { -3, -2, 3, 0, JAM1, 5, (short *)&dc, NULL },
	hb = { -3, -2, 3, 0, JAM1, 5, (short *)&hc, NULL },
	qb1 = { 0, 0, 2, 0, JAM1, 3, (short *)&qc1, NULL },
	qb = { 0, 0, 1, 0, JAM1, 3, (short *)&qc, (struct Border *)&qb1 },
	hgb1 = { 0, 0, 2, 0, JAM1, 3, (short *)&hagc1, NULL },
	hgb = { 0, 0, 1, 0, JAM1, 3, (short *)&hagc, (struct Border *)&hgb1 };


struct Gadget
	bg = { (struct Gadget *)NULL, 50, 16, 267, 11, GADGHCOMP, RELVERIFY,
		STRGADGET, (APTR)&bb, NULL, &bit, NULL, (APTR)&bsi, 1, NULL },
	og = { (struct Gadget *)&bg, 50, 29, 98, 11, GADGHCOMP, RELVERIFY,
		STRGADGET, (APTR)&ob, NULL, &oit, NULL, (APTR)&osi, 2, NULL },
	dg = { (struct Gadget *)&og, 50, 42, 92, 11, GADGHCOMP, LONGINT|RELVERIFY,
		STRGADGET, (APTR)&db, NULL, &dit, NULL, (APTR)&dsi, 3, NULL },
	hg = { (struct Gadget *)&dg, 50, 55, 76, 11, GADGHCOMP, RELVERIFY,
		STRGADGET, (APTR)&hb, NULL, &hit, NULL, (APTR)&hsi, 4, NULL },
	eg = { (struct Gadget *)&hg, 200, 28, 66, 11, GADGHCOMP, GADGIMMEDIATE|RELVERIFY,
		BOOLGADGET, (APTR)&qb, NULL, &hgt, NULL, NULL, 5, NULL },
	ag = { (struct Gadget *)&eg, 200, 41, 66, 11, GADGHCOMP, GADGIMMEDIATE|RELVERIFY,
		BOOLGADGET, (APTR)&qb, NULL, &agt, NULL, NULL, 6, NULL },
	qg = { (struct Gadget *)&ag, 200, 54, 66, 11, GADGHCOMP, GADGIMMEDIATE|RELVERIFY,
		BOOLGADGET, (APTR)&qb, NULL, &qgt, NULL, NULL, 7, NULL },
	hgg = { NULL, 189, 128, 62, 11, GADGHCOMP, GADGIMMEDIATE|RELVERIFY,
		BOOLGADGET, (APTR)&hgb, NULL, &hagt, NULL, NULL, 1, NULL },
	*gd;

struct Window *mw, *hw;

struct NewWindow
	mnw = { 0, 0, 334, 70, 0, 1, CLOSEWINDOW|GADGETUP|VANILLAKEY,
		WINDOWDRAG|WINDOWCLOSE|WINDOWDEPTH|ACTIVATE|NOCAREREFRESH|SMART_REFRESH,
		(struct Gadget *)&qg, NULL, (UBYTE *)"Variator", NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN },
	nhw ={ 0, 0, 434, 142 , 0, 3, GADGETUP|VANILLAKEY,
		ACTIVATE|SMART_REFRESH|NOCAREREFRESH|WINDOWDRAG,
		(struct Gadget *)&hgg, NULL, (UBYTE *)"", NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN};

struct IntuiMessage *mm, *hm;
struct Screen *wb;

unsigned char
	version[] = "$VER: Variator 2.0 (12.03.1997) Copyright 1991, 1997 by Dalibor Kezele",
	chars[17] = "0123456789ABCDEF",
	HelpTitle[16] = "Variator Help",
	AboutTitle[16] = "About Variator",
	error[6] = "Error",

	ht[13][53] = {
		"   Variator is very simply to use. You only need to",
		"click on one of BIN, OCT, DEC and HEX gadgets, enter",
		"a number and press <CR>, and you number is convetted",
		"to other bases in a speed of light.",
		"   Keyboard shortcuts:",
		"        <B> == Bin        <C>, <DEL> == Clear",
		"        <O> == Oct        <?>, <CR>  == Help",
		"        <D> == Dec        <!>, <A>   == About",
		"        <H> == Hex        <Q>, <ESC> == Exit",
		"   Numbers are 32-bit long integers. If you enter an",
		"illegal character (like '2' in a binary number) or",
		"a number higher than 32-bit an error is displayed.",
		"   Well, why don't you click the \"about\" gadget?",
		},

	at[13][53] = {
		"   Since I started working with Amiga I haven't seen",
		"any program which just recalculates numbers from one",
		"base to another. So I made it. And it helps me now a",
		"lot. I would like you to use it.",
		"   This program is POSTCARDWARE. If you like it and",
		"use it, please send me a postcard. My address is:",
      "",
		"                 Dalibor S. Kezele",
		"                   Toplicka 127",
		"                   42204 Turcin",
		"                     Croatia",
      "",
		"     (Check Variator.DOC for more information!)     ",
		};

/* -------------------------------------------------------------------- */

int main(void)
{
ULONG class;
USHORT code;
unsigned long longbuffer;

if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L)))
	return 0;

wb = IntuitionBase -> ActiveScreen;
mnw.LeftEdge = ((wb -> Width) - (mnw.Width)) / 2;
mnw.Screen = (struct Screen *) wb;

nhw.TopEdge = ((wb -> Height) - (nhw.Height)) / 2;
nhw.LeftEdge = ((wb -> Width) - (nhw.Width)) / 2;
nhw.Screen = (struct Screen *) wb;

if(!(mw = (struct Window *)OpenWindow(&mnw))) {
	CloseLibrary(IntuitionBase);
	return 0;
	}

while(1) {
	Delay(8L);
	mm = (struct IntuiMessage *)GetMsg(mw->UserPort);
	class = mm -> Class;
	code = mm -> Code;

	if(mm == NULL) continue;

	if(class == CLOSEWINDOW)
		break;

	if(class == GADGETUP) {
		gd = (struct Gadget *) mm -> IAddress;
		if(gd -> GadgetID == 7)
			break;
		else
			switch(gd -> GadgetID) {
				case 1 :
					if(any2dec(&longbuffer, 2, (char *)bms)) {
						strcpy(oms, &error);
						strcpy(dms, &error);
						strcpy(hms, &error);
						}
					else {
						dec2any(longbuffer, 8, (char *)oms);
						dec2any(longbuffer, 10, (char *)dms);
						dec2any(longbuffer, 16, (char *)hms);
					}
					RefreshGList(&hg, mw, NULL, 4L);
					break;
				case 2 :
					if((any2dec(&longbuffer, 8, (char *)oms))
						|| (strlen(oms)==11 && oms[0]>'3')) {
							strcpy(bms, &error);
							strcpy(dms, &error);
							strcpy(hms, &error);
						}
					else {
						dec2any(longbuffer, 2, (char *)bms);
						dec2any(longbuffer, 10, (char *)dms);
						dec2any(longbuffer, 16, (char *)hms);
					}
					RefreshGList(&hg, mw, NULL, 4L);
					break;
				case 3 :
					dec2any(dsi.LongInt, 2, (char *)bms);
					dec2any(dsi.LongInt, 8, (char *)oms);
					dec2any(dsi.LongInt, 10, (char *)dms);
					dec2any(dsi.LongInt, 16, (char *)hms);
					RefreshGList(&hg, mw, NULL, 4L);
					break;
				case 4 :
					if(any2dec(&longbuffer, 16, (char *)hms)) {
						strcpy(bms, &error);
						strcpy(oms, &error);
						strcpy(dms, &error);
						}
					else {
						dec2any(longbuffer, 2, (char *)bms);
						dec2any(longbuffer, 8, (char *)oms);
						dec2any(longbuffer, 10, (char *)dms);
					}
					RefreshGList(&hg, mw, NULL, 4L);
					break;
				case 5 :
					helpabout(0);
					break;
				case 6 :
					helpabout(1);
					break;
				}
		}
	if(class == VANILLAKEY) {
		if(code == 27 || code == 'q' || code == 'Q')
			break;
		else
			switch(code) {
				case 'b' :
				case 'B' : ActivateGadget(&bg, mw, NULL); break;
				case 'o' :
				case 'O' : ActivateGadget(&og, mw, NULL); break;
				case 'd' :
				case 'D' : ActivateGadget(&dg, mw, NULL); break;
				case 'h' :
				case 'H' : ActivateGadget(&hg, mw, NULL); break;
				case 13 :
				case '?' : helpabout(0); break;
				case 'a' :
				case 'A' :
				case '!' : helpabout(1); break;
				case 127 :
				case 'c' :
				case 'C' : bms[0] = oms[0] = dms[0] = hms[0] = 0;
					RefreshGList(&hg, mw, NULL, 4L);;
			}
		}

	ReplyMsg(mm);
	}

CloseWindow(mw);
CloseLibrary(IntuitionBase);
return 0;
}

/* -------------------------------------------------------------------- */

int dec2any(unsigned long decimal, int base, char *newnumber)
{
	unsigned long number;
	int helpnumber[40];
	int letter, count, max = 0;

	while(decimal) {
		number = decimal / base;
		letter = decimal - (number * base);
		helpnumber [++max] = letter;
		if(max > 39) return 1;
		decimal = number;
		}
	for(count=max; count >=1; count--)
		newnumber[max-count] = chars[helpnumber[count]];

	newnumber[max] = 0;
	return 0;
}

/* -------------------------------------------------------------------- */

int any2dec(unsigned long *decimal, int base, char *number)
{
	unsigned long countbase = 1;
	int count, letter;
	char onechar;

	*decimal = 0;
	for(count = strlen(number) - 1; count >= 0; count--) {
		onechar = toupper(number[count]);
		if(onechar < 65)
			letter = onechar - 48;
		else
			letter = onechar - 55;
		if(letter < 0 || letter >= base) return 1;
		*decimal = *decimal + letter * countbase;
		countbase *= base;
		}
	return 0;
}

/* -------------------------------------------------------------------- */

int helpabout(short choice)
{
ULONG klass;
USHORT kode;
register short counter = 0;

while(counter<13) {
	if(choice) {
		hait[counter].FrontPen = atc[counter];
		hait[counter].IText = (UBYTE *)&at[counter][0];
		}
	else {
		hait[counter].FrontPen = htc[counter];
		hait[counter].IText = (UBYTE *)&ht[counter][0];
	}
	hait[counter].BackPen = 0;
	hait[counter].DrawMode = JAM1;
	hait[counter].LeftEdge = 0;
	hait[counter].TopEdge = tc[counter];
	hait[counter].ITextFont = &t8f;
	hait[counter++].NextText = NULL;
	}

if(choice)
	nhw.Title = (UBYTE *)&AboutTitle;
else
	nhw.Title = (UBYTE *)&HelpTitle;

if(!(hw = (struct Window *)OpenWindow(&nhw))) return 1;

counter = 0;

while(counter<13)
	PrintIText(hw -> RPort, &hait[counter++], 9, 15);

while(1) {
	Delay(8L);
	hm = (struct IntuiMessage *)GetMsg(hw->UserPort);
	if(hm == NULL) continue;
	klass = hm -> Class;
	kode = hm -> Code;
	if(klass == GADGETUP || (klass == VANILLAKEY && (kode == 27 || kode == 13)))
			break;
	}

ReplyMsg(hm);
CloseWindow(hw);
return 0;
}
