/*********************************************
	AUDIO TONE-DIALER ACCESSORY
Mark Williams C. Compiles with:
cc filename.c -o filename.acc -VGEMACC
requires ASCII file "DIAL.ASC" on root of boot
disk. File has format:

Name,123-4567(Return)
Name,1(123) 456-7890(Return), etc.
**********************************************/

#include <aesbind.h>
#include <gemdefs.h>
#include <obdefs.h>
#include <osbind.h>
#include <ctype.h>
#include <stdio.h>

#define BUFLEN		1024L		/* Length of disk buffer */
#define DS1		1		/* Index of first dialer string */
#define DONE		13		/* Index of CANCEL button */
#define DLINES		12		/* Number of dial strings */
#define LONGDLY		10		/* Tone dur. in 1/60th sec. units */ 
#define SHORTDLY	4		/* Intertone dur. as above */
#define WRITE		0x80		/* Write command for GI sound chip */
#define ENABLE		7		/* GI register 7 (enable register) */
#define AVOLUME		8		/* GI channel A volume/envelope reg. */
#define BVOLUME		9		/* GI channel B ditto */
#define APITCH		0		/* GI channel A pitch register */
#define APERLEN		1		/* GI channel A period length reg. */
#define BPITCH		2		/* GI channel B pitch register */
#define BPERLEN		3		/* GI channel B period length reg. */
#define SMRECT		0,0,0,0		/* Small rectangle */
#define BIGRECT		dial[0].ob_x,dial[0].ob_y,\
				dial[0].ob_width,dial[0].ob_height
#define delay(a)	{int i = a; while(i--) Vsync();}

char buf[BUFLEN];			/* Disk transfer buffer */
long count;				/* Character count */

char dum[] = "";			/* Dummy string */
char *ptr[] = {				/* Array of pointers to phone numbers */
dum,dum,dum,dum,dum,dum,dum,dum,dum,dum,dum,dum
};

OBJECT dial[] = {			/* Dialog box OBJECT structure array */
-1,1,14,20,0,16,0x21100L,120,16,264,288,
2,-1,-1,28,64,0,"",16,48,240,16,
3,-1,-1,28,64,0,"",16,64,240,16,
4,-1,-1,28,64,0,"",16,80,240,16,
5,-1,-1,28,64,0,"",16,96,240,16,
6,-1,-1,28,64,0,"",16,112,240,16,
7,-1,-1,28,64,0,"",16,128,240,16,
8,-1,-1,28,64,0,"",16,144,240,16,
9,-1,-1,28,64,0,"",16,160,240,16,
10,-1,-1,28,64,0,"",16,176,240,16,
11,-1,-1,28,64,0,"",16,192,240,16,
12,-1,-1,28,64,0,"",16,208,240,16,
13,-1,-1,28,64,0,"",16,224,240,16,
14,-1,-1,26,66,0,"Done",104,256,64,16,
0,-1,-1,28,32,0,"Audio Dial",96,16,80,16
};

char fname[] = "x:\\dial.asc";			/* Name of data file */

/**********************************************
	IMPORTANT STUFF STARTS HERE
***********************************************/

/* Set GI chip and generate tone pair */

tone(a,b)
int a,b;
{
/* Enable tone channels A and B (reset bits 0 and 1 of GI register 7) */

Giaccess((char) 0xFC,WRITE | ENABLE);

/* Medium volume on A and B (set bits 0-3). Avoids distortion. */

Giaccess((char) 0x0D,WRITE | AVOLUME);
Giaccess((char) 0x0D,WRITE | BVOLUME);

/* Set pitch and period length for channels A and B */

Giaccess((char) a & 0xFF,WRITE | APITCH);
Giaccess((char) (a >> 8) & 0xFF,WRITE | APERLEN);

Giaccess((char) b & 0xFF,WRITE | BPITCH);
Giaccess((char) (b >> 8) & 0xFF,WRITE | BPERLEN);

delay(LONGDLY); /* Wait */

/* Turn off tone for channels A and B */

Giaccess((char) 0x00,WRITE | 8);
Giaccess((char) 0x00,WRITE | 9);

delay(SHORTDLY); /* Wait */
}

/* Find character in string, return pointer */

char *index(s,c)
char *s;
char c;
{
while(*s != '\0'){
	if (*s == c)
		return(s);
	s++;
	}
return(NULL);
}

/* Find index of character in string */

int ind(s,c)
char *s;
char c;
{
char *p = index(s,c);

if (p != NULL)
	return((int) p - s);
return(-1);
}

/* Dial number string */

do_dial(s)
char *s;
{
int row,col,p;
static int rt[4] = {178,160,145,131};	/* Row tones */
static int ct[3] = {104,92,83};		/* Column tones */
static char kpd[] = "11112ABC3DEF4GHI5JKL6MNO7PRS8TUV9WXY****0000####";

while(*s != '\0'){
	if ((p = ind(kpd,toupper(*s++))) >= 0){  /* if char on keypad .. */
		row = (int) (p / 12);	/* 12 chars per row in keypad model */
		col = (int) ((p % 12) / 4);	/* 4 chars per key */
		tone(rt[row],ct[col]);	/* play tones */
		}
	}
}

/***********************************************
     IMPORTANT STUFF ENDS: COSMETICS BEGIN
************************************************/

/* Draw and manage dialog box */

void do_de_dial_thang()
{
int ret;

form_dial(FMD_START,SMRECT,BIGRECT);
form_dial(FMD_GROW,SMRECT,BIGRECT);
objc_draw(dial,0,MAX_DEPTH,BIGRECT);
do{
	ret = form_do(dial,0);
	if (ret != DONE)
		do_dial(ptr[ret - DS1]);
	} while (ret != DONE);
form_dial(FMD_SHRINK,SMRECT,BIGRECT);
form_dial(FMD_FINISH,SMRECT,BIGRECT);
}

/* Read data file into buffer and set pointers */

int readin()
{
int i,fhandle;
char *point,*s = buf;

if ((fhandle = Fopen(fname,0)) < 0)
	return(-1);

if ((count = Fread(fhandle,BUFLEN,buf)) < 0)
	return(-1);

Fclose(fhandle);
buf[(int) count] = '\0';

for(i = DS1;i < DONE;i++){
	if ((point = (char *) index(s,',')) == NULL)
		break;
	dial[i].ob_spec = (long) s;
	*point++ = '\0';
	s = point;
	if ((point = (char *) index(s,(char) 13)) == NULL)
		break;
	ptr[i - DS1] = s;
	*point++ = '\0';
	if (*point == (char) 10)
		*point++ = '\0';
	s = point;
	}
return(0);
}

/* Main routine */

main()
{
extern int gl_apid;
int menu_ID,mbuf[8],flag;

/* Register accessory */

appl_init();
menu_ID = menu_register(gl_apid,"  AudioDial ");
fname[0] = Dgetdrv() + 'A';
form_center(dial,
	&dial[0].ob_x,&dial[0].ob_y,&dial[0].ob_width,&dial[0].ob_height);

/* Read in file of names and numbers */

flag = readin();

/* Manage accessory */

for(;;){
	evnt_mesag(mbuf);
	if (mbuf[0] == AC_OPEN){
		if (flag)
			form_alert(3,"[1][Sorry bud. Can't find DIAL.ASC.][Darn!]");	
		else
			do_de_dial_thang();
		}
	}
}