/*************************************************************************
**   File:  funckey.c
**      contains function key menu, requestor, and library structures and
**      manipulation routines
**
**   Functions:
**	set_fkey() - manipulates function-key editing requestor - called
**		when appropriate menu item selected
**	init_fk_req() - initializes structures for function key requestor
**	sav_fklib() - saves function key definitions to disk file
**	load_fklib() - loads function key definitions from disk file
**	do_fkey(ushort,ushort) - translates function key passed to
**		corresponding string and sends it to modem
**
*************************************************************************/
#include "term.h"


extern struct Window *mywindow;

/*********************************************************************
*      Structures to define Requester and it's gadgets
*********************************************************************/
struct IntuiText l_txt1 = {
	2,0,		/* front pen, back */
	JAM1,		/* draw mode */
	2,39,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "F1 ", /* text */
	NULL		/* chain */
	};

struct IntuiText l_txt2 = {
	2,0,		/* front pen, back */
	JAM1,		/* draw mode */
	2,50,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "F2 ", /* text */
	&l_txt1		/* chain */
	};

struct IntuiText l_txt3 = {
	2,0,		/* front pen, back */
	JAM1,		/* draw mode */
	2,61,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "F3 ", /* text */
	&l_txt2		/* chain */
	};

struct IntuiText l_txt4 = {
	2,0,		/* front pen, back */
	JAM1,		/* draw mode */
	2,72,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "F4 ", /* text */
	&l_txt3		/* chain */
	};

struct IntuiText l_txt5 = {
	2,0,		/* front pen, back */
	JAM1,		/* draw mode */
	2,83,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "F5 ", /* text */
	&l_txt4		/* chain */
	};

struct IntuiText l_txt6 = {
	2,0,		/* front pen, back */
	JAM1,		/* draw mode */
	2,94,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "F6 ", /* text */
	&l_txt5		/* chain */
	};

struct IntuiText l_txt7 = {
	2,0,		/* front pen, back */
	JAM1,		/* draw mode */
	2,105,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "F7 ", /* text */
	&l_txt6		/* chain */
	};

struct IntuiText l_txt8 = {
	2,0,		/* front pen, back */
	JAM1,		/* draw mode */
	2,116,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "F8 ", /* text */
	&l_txt7		/* chain */
	};

struct IntuiText l_txt9 = {
	2,0,		/* front pen, back */
	JAM1,		/* draw mode */
	2,127,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "F9 ", /* text */
	&l_txt8		/* chain */
	};

struct IntuiText l_txt10 = {
	2,0,		/* front pen, back */
	JAM1,		/* draw mode */
	2,138,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "F10", /* text */
	&l_txt9		/* chain */
	};

struct IntuiText fk_txt3 = {
	3,1,		/* front pen, back */
	JAM1,		/* draw mode */
	140,0,		/* relative start */
	NULL,		/* font */
	(UBYTE *) " Function Key Values ", /* text */
	&l_txt10	/* chain */
	};

struct IntuiText fk_txt2 = {
	3,1,		/* front pen, back */
	JAM1,		/* draw mode */
	48,30,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "unshifted:", /* text */
	&fk_txt3	/* chain */
	};

struct IntuiText fk_txt1 = {
	3,1,		/* front pen, back */
	JAM1,		/* draw mode */
	218,30,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "SHIFTED:", /* text */
	&fk_txt2	/* chain */
	};

struct IntuiText fk_l_txt = {
	2,3,		/* front pen, back */
	JAM1,		/* draw mode */
	2,1,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "Load", /* text */
	NULL		/* chain */
	};

struct IntuiText fk_s_txt = {
	2,3,		/* front pen, back */
	JAM1,		/* draw mode */
	2,1,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "Save", /* text */
	NULL		/* chain */
	};

struct IntuiText fk_c_txt = {
	2,3,		/* front pen, back */
	JAM1,		/* draw mode */
	2,1,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "Quit", /* text */
	NULL		/* chain */
	};


struct IntuiText fk_nm_txt = {
	2,1,		/* front pen, back */
	JAM1,		/* draw mode */
	-48,0,		/* relative start */
	NULL,		/* font */
	(UBYTE *) "File: ", /* text */
	NULL		/* chain */
	};

#define Fil_Nam_Sz 128
#define Fk_Ent_Sz 64
#define MAX_NUM 20

UBYTE fk_fil_nam[Fil_Nam_Sz] = "Term.Key";
extern UBYTE undo_buf[];		/* defined in term2.c */
UBYTE func_key[MAX_NUM][Fk_Ent_Sz];

struct StringInfo fk_nm_buf = {
	fk_fil_nam,	/* buffer */
	undo_buf,	/* undo buffer */
	0,		/* buf pos */
	Fil_Nam_Sz,	/* Max chars */
	0,		/* first disp pos */
	0,		/* Undo pos */
	13,		/*  current char count */
	0,0,0,
	NULL,NULL
	};

struct StringInfo func_key_s [MAX_NUM];

SHORT fk_bord_cords[] = 
	{0,0,35,0,35,10,0,10,0,0};

struct Border fk_bord = {
	0,-1,		/* left, top */
	2,1,JAM1,
	5,fk_bord_cords,
	NULL
	};

/*   Macros for identifying gadgets   */

#define FK_C_GAD		200
#define FK_S_GAD		201
#define FK_L_GAD		202
#define FK_NM_GAD	203

#define UP_FK_C_GAD (gad->GadgetID == FK_C_GAD)
#define UP_FK_S_GAD (gad->GadgetID == FK_S_GAD)
#define UP_FK_L_GAD (gad->GadgetID == FK_L_GAD)
#define UP_FK_NM_GAD (gad->GadgetID == FK_NM_GAD)
#define UP_KEY_GAD (gad->GadgetID > FK_NM_GAD)

#define GAD_KEY (gad->GadgetID - FK_NM_GAD - 1)


struct Gadget key_gad [MAX_NUM];

struct Gadget fk_c_gad = {
	&key_gad[0],	/* chain to next */
	330,10,		/* left, top */
	35,11,		/* width, height */
	GADGHCOMP,	/* flags */
	RELVERIFY |
	ENDGADGET,
	REQGADGET |
	BOOLGADGET,	/* gadget type */
	(APTR)&fk_bord, NULL,	/* render ptrs */
	&fk_c_txt,		/* gadget label */
	NULL,		/* exclude */
	NULL,
	FK_C_GAD,		/* gadget id */
	NULL		/* user data */
	};

struct Gadget fk_s_gad = {
	&fk_c_gad,		/* chain to next */
	288,10,		/* left, top */
	35,11,		/* width, height */
	GADGHCOMP,	/* flags */
	RELVERIFY,	/* activation */
	REQGADGET |
	BOOLGADGET,	/* gadget type */
	(APTR)&fk_bord, NULL,	/* render ptrs */
	&fk_s_txt,		/* gadget label */
	NULL,		/* exclude */
	NULL,
	FK_S_GAD,		/* gadget id */
	NULL		/* user data */
	};

struct Gadget fk_l_gad = {
	&fk_s_gad,		/* chain to next */
	245,10,		/* left, top */
	35,11,		/* width, height */
	GADGHCOMP,	/* flags */
	RELVERIFY,	/* activation */
	REQGADGET |
	BOOLGADGET,	/* gadget type */
	(APTR)&fk_bord, NULL,	/* render ptrs */
	&fk_l_txt,		/* gadget label */
	NULL,		/* exclude */
	NULL,
	FK_L_GAD,		/* gadget id */
	NULL		/* user data */
	};

struct Gadget fk_nm_gad = {
	&fk_l_gad,		/* chain to next */
	60,10,		/* left, top */
	160,11,		/* width, height */
	GADGHCOMP,	/* flags */
	RELVERIFY,
	REQGADGET |
	STRGADGET,	/* gadget type */
	NULL, NULL,	/* render ptrs */
	&fk_nm_txt,	/* gadget label */
	NULL,		/* exclude */
	(APTR)&fk_nm_buf,	/* string buffers */
	FK_NM_GAD,		/* gadget id */
	NULL		/* user data */
	};

struct Requester fk_req = {
	NULL,		/* backwards chain */
	30,10,		/* left, top */
	400,160,	/* width, height */
	NULL,NULL,	/* pointer relatives */
	&fk_nm_gad,	/* first gadget */
	NULL,		/* border */
	&fk_txt1,	/* Requester text */
	NULL,		/* flags */
	1,		/* backfill */
	NULL,		/* clip req */
	NULL,		/*  bit map */
	NULL		/* bit map */
	};


/********************************************************************
*   Function to handle PhoneLib Requester                           *
********************************************************************/

set_fkey()
{
	static short init_ok = 0;

	int looping = TRUE;
	struct IntuiMessage *mes;
	struct Gadget *gad;
	ULONG class;

	if (!init_ok) {
		init_fk_req();
		init_ok = 1;
	}

	if (Request(&fk_req,mywindow) != 1) {
		emits("Requester Failed\n");
		return(0);
	}
	while (looping) {
		if ((mes = (struct IntuiMessage *)GetMsg(mywindow->UserPort)) == 0) {
			(VOID) Wait(1<<mywindow->UserPort->mp_SigBit);
			continue;
		}
		class = mes->Class;
		gad = (struct Gadget *)mes->IAddress;
		(VOID) ReplyMsg(mes);
		if (class!=GADGETUP) continue;
		if UP_FK_C_GAD {
			looping = FALSE;
			continue;
		}
		if UP_FK_S_GAD {
			if (sav_fklib() == 1) {
				EndRequest(&fk_req,mywindow);
				emits("Save of Function Keys failed\n");
				looping = FALSE;
			}
			continue;
		}
		if UP_FK_L_GAD {
			load_fklib();
			RefreshGadgets(&fk_nm_gad,mywindow,&fk_req);
			continue;
		}
		if UP_FK_NM_GAD {
			continue;
		}
		if UP_KEY_GAD {
			continue;
		}
	}   /*  end while */

	return(0);
}

init_fk_req()
{
	int i;
	USHORT g_num = 0;

	for (i = 0;i < MAX_NUM;i++) {
		key_gad[i].NextGadget = &key_gad[i]+1;
		key_gad[i].LeftEdge = (i>9?210:40);
		key_gad[i].TopEdge = (39 + (11 * (i>9?i-10:i)));
		key_gad[i].Width = 160;
		key_gad[i].Height = 11;
		key_gad[i].Flags = GADGHCOMP;
		key_gad[i].Activation = RELVERIFY;
		key_gad[i].GadgetType = REQGADGET | STRGADGET;
		key_gad[i].GadgetRender = NULL;
		key_gad[i].SelectRender = NULL;
		key_gad[i].GadgetText = NULL;
		key_gad[i].MutualExclude = NULL;
		key_gad[i].SpecialInfo = (APTR)&func_key_s[i];
		key_gad[i].GadgetID = g_num++;
		key_gad[i].UserData = NULL;
		func_key_s[i].Buffer = (UBYTE *)&func_key[i];
		func_key_s[i].UndoBuffer = undo_buf;
		func_key_s[i].BufferPos = 0;
		func_key_s[i].MaxChars = Fk_Ent_Sz-1;
		func_key_s[i].DispPos = 0;
		func_key_s[i].UndoPos = 0;
		func_key_s[i].NumChars = 0;
		func_key_s[i].DispCount = 0;
		func_key_s[i].CLeft = 0;
		func_key_s[i].CTop = 0;
		func_key_s[i].LayerPtr = NULL;
		func_key_s[i].LongInt = 0;
		func_key_s[i].AltKeyMap = NULL;
	}
	key_gad[MAX_NUM-1].NextGadget = NULL;
	return(0);
}

sav_fklib()
{
	int i,j;
	FILE *fptr;


	if ((fptr = fopen(fk_fil_nam,"w")) == NULL)
		return(1);	/*  NOTE: file cannot open */

	for (i = 0;i<MAX_NUM;i++) {
		for (j=0;func_key[i][j];j++) {
			if (fputc(func_key[i][j],fptr) == EOF) {
				fclose(fptr);
				return(1);
			}
		}
		if (fputc('\0',fptr) == EOF) {
			fclose(fptr);
			return(1);
		}
	}
	fclose(fptr);
	return(0);
}
		

load_fklib()
{
	int c, i, j;
	int error = 0;
	FILE *fptr;

	for (i = 0;i < MAX_NUM;i++) {
		func_key[i][0] = '\0';
	}

	if ((fptr = fopen(fk_fil_nam,"r")) == NULL) {
		error = 1;
	}

	if (!error) {
		i = j = 0;
		while ((c = fgetc(fptr)) != EOF) {
			func_key[i][j++] = (UBYTE) c;
			if (!c) {
				i++;
				j = 0;
				if (i > (MAX_NUM -1))
					break;
			}
		}
		func_key[i][j] = '\0';
		fclose(fptr);
	}
	return(0);
}

do_fkey(code,qual)
	USHORT code, qual;
{
	int ix,i;
	
	if ((code > '\x4f') && (code < '\x5a')) {
		ix = code - '\x50';
		if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT ))
			ix += 10;
		for (i=0;func_key[ix][i];i++) {
			if (func_key[ix][i] == '\n')
				sendchar('\r');
			else
				sendchar(func_key[ix][i]);
		}	
		return(0);
	}
	if (code == '\x5f')
		do_help();
	return(0);
}

