/***********************************************************/
/*                PhoneDir V1.0 by Ric Kalton              */
/***********************************************************/
/* This source should be compiled so that the gadget data  */
/* is placed in CHIP ram, therefore if you have a compiler */
/* which supports a 'chip' keyword, use it in the gadget   */
/* data declarations. Otherwise compile or link with a     */
/* some sort of a CHIP option. eg use the CHIP keyword     */
/* with BLink.                                             */
/***********************************************************/

#include <exec/types.h>
#include <exec/exec.h>
#include <exec/memory.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>
#include <libraries/dos.h>
#include <devices/audio.h>
#include <intuition/intuition.h>
#include <stdio.h>

#define STRLENGTH 50

#define L_CHAN     0
#define R_CHAN     1
#define ADD        2
#define START      3
#define DEL        4
#define LEFT       5
#define DIAL       6    /* Gadget IDs...*/
#define RIGHT      7
#define FIND       8
#define END        9
#define QUIT      10
#define SAVE      11  
#define NAME      12
#define PHON      13

#define SOUNDPRI      76  /* Priority assigned to our channels. */
#define CLOCK    3546895  /* PAL only, NTSC has different frequency. */
#define LEFT1          1  /* Channel IDs...*/
#define RIGHT1         2
#define RIGHT2         4
#define LEFT2          8
#define WAVESIZE       2  /* Length of square wave (must be even). */
#define VOLUME        64  /* Max Volume. */

int CXBRK()               /* Disable Lattice C's Ctrl C handling. */
{                         /* Remove for other compilers.          */
   return 0;
}

struct book_entry {          /* My own structure for storing each */
   struct book_entry *next;  /* name and number.                  */
   struct book_entry *last;
   char name[STRLENGTH];
   char phon[STRLENGTH];
};

struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct Window *Window;
struct RastPort *rastport;
struct book_entry *current = NULL, *new = NULL,
       *start = NULL, *end = NULL;

UBYTE name_buff[STRLENGTH];  /* String Gadget buffers... */
UBYTE phon_buff[STRLENGTH];
UBYTE undo_buff[STRLENGTH];

SHORT lines[] = {            /* Declare and initialize necessary */
   0, 0,                     /* structures.                      */
   169, 0,
   169, 11,
   0, 11,
   0, 0
};

USHORT add_data[] = {
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xfff1, 0xc387, 0xff80, 
0xffee, 0xddbb, 0xff80, 
0xffee, 0xddbb, 0xff80, 
0xffe0, 0xddbb, 0xff80, 
0xffee, 0xddbb, 0xff80, 
0xffee, 0xddbb, 0xff80, 
0xffee, 0xc387, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 

0x0,    0x0,    0x0,    
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x0,    0x0,    0x0,    
};

struct Image add_image = {
   0, 0,
   41, 13, 2,
   add_data,
   3, 0,
   NULL
};

USHORT start_data[] = {
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xf8e0, 0xe387, 0x780,  
0xf77b, 0xddbb, 0xdf80, 
0xf7fb, 0xddbb, 0xdf80, 
0xf8fb, 0xc187, 0xdf80, 
0xff7b, 0xddbb, 0xdf80, 
0xf77b, 0xddbb, 0xdf80, 
0xf8fb, 0xddbb, 0xdf80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 

0x0,    0x0,    0x0,    
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x0,    0x0,    0x0,    
};

struct Image start_image = {
   0, 0,
   41, 13, 2,
   start_data,
   3, 0,
   NULL
};

USHORT del_data[] = {
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffe1, 0xc1bf, 0xff80, 
0xffee, 0xdfbf, 0xff80, 
0xffee, 0xdfbf, 0xff80, 
0xffee, 0xc3bf, 0xff80, 
0xffee, 0xdfbf, 0xff80, 
0xffee, 0xdfbf, 0xff80, 
0xffe1, 0xc183, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 

0x0,    0x0,    0x0,    
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x0,    0x0,    0x0,    
};

struct Image del_image = {
   0, 0,
   41, 13, 2,
   del_data,
   3, 0,
   NULL
};

USHORT left_data[] = {
0x8,    0x0,    
0x38,   0x0,    
0xf8,   0x0,    
0x3ff,  0xfe00, 
0xfff,  0xfe00, 
0x3fff, 0xfe00, 
0xffff, 0xfe00, 
0x3fff, 0xfe00, 
0xfff,  0xfe00, 
0x3ff,  0xfe00, 
0xf8,   0x0,    
0x38,   0x0,    
0x8,    0x0,    

0x0,    0x0,    
0x0,    0x0,    
0x30,   0x0,    
0xf0,   0x0,    
0x3ff,  0xfc00, 
0xfff,  0xfc00, 
0x3fff, 0xfc00, 
0xfff,  0xfc00, 
0x3ff,  0xfc00, 
0xf0,   0x0,    
0x30,   0x0,    
0x0,    0x0,    
0x0,    0x0,    
};

struct Image left_image = {
   0, 0,
   23, 13, 2,
   left_data,
   3, 0,
   NULL
};

USHORT dial_data[] = {
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffc3, 0xb8ef, 0xff80, 
0xffdd, 0xb76f, 0xff80, 
0xffdd, 0xb76f, 0xff80, 
0xffdd, 0xb06f, 0xff80, 
0xffdd, 0xb76f, 0xff80, 
0xffdd, 0xb76f, 0xff80, 
0xffc3, 0xb760, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 

0x0,    0x0,    0x0,    
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x0,    0x0,    0x0,    
};

struct Image dial_image = {
   0, 0,
   41, 13, 2,
   dial_data,
   3, 0,
   NULL
};

USHORT right_data[] = {
0x20,   0x0,    
0x38,   0x0,    
0x3e,   0x0,    
0xffff, 0x8000, 
0xffff, 0xe000, 
0xffff, 0xf800, 
0xffff, 0xfe00, 
0xffff, 0xf800, 
0xffff, 0xe000, 
0xffff, 0x8000, 
0x3e,   0x0,    
0x38,   0x0,    
0x20,   0x0,    

0x0,    0x0,    
0x0,    0x0,    
0x18,   0x0,    
0x1e,   0x0,    
0x7fff, 0x8000, 
0x7fff, 0xe000, 
0x7fff, 0xf800, 
0x7fff, 0xe000, 
0x7fff, 0x8000, 
0x1e,   0x0,    
0x18,   0x0,    
0x0,    0x0,    
0x0,    0x0,    
};

struct Image right_image = {
   0, 0,
   23, 13, 2,
   right_data,
   3, 0,
   NULL
};

USHORT find_data[] = {
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xff83, 0x6ec3, 0xff80, 
0xffbf, 0x6edd, 0xff80, 
0xffbf, 0x66dd, 0xff80, 
0xff87, 0x6add, 0xff80, 
0xffbf, 0x6cdd, 0xff80, 
0xffbf, 0x6edd, 0xff80, 
0xffbf, 0x6ec3, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 

0x0,    0x0,    0x0,    
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x0,    0x0,    0x0,    
};

struct Image find_image = {
   0, 0,
   41, 13, 2,
   find_data,
   3, 0,
   NULL
};

USHORT end_data[] = {
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffe0, 0xdd87, 0xff80, 
0xffef, 0xddbb, 0xff80, 
0xffef, 0xcdbb, 0xff80, 
0xffe1, 0xd5bb, 0xff80, 
0xffef, 0xd9bb, 0xff80, 
0xffef, 0xddbb, 0xff80, 
0xffe0, 0xdd87, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 

0x0,    0x0,    0x0,    
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x0,    0x0,    0x0,    
};

struct Image end_image = {
   0, 0,
   41, 13, 2,
   end_data,
   3, 0,
   NULL
};

USHORT quit_data[] = {
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffc7, 0x76c1, 0xff80, 
0xffbb, 0x76f7, 0xff80, 
0xffbb, 0x76f7, 0xff80, 
0xffbb, 0x76f7, 0xff80, 
0xffbb, 0x76f7, 0xff80, 
0xffab, 0x76f7, 0xff80, 
0xffc7, 0x8ef7, 0xff80, 
0xfffb, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 

0x0,    0x0,    0x0,    
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x0,    0x0,    0x0,    
};

struct Image quit_image = {
   0, 0,
   41, 13, 2,
   quit_data,
   3, 0,
   NULL
};

USHORT save_data[] = {
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xff1e, 0x3bb0, 0x7f80, 
0xfeed, 0xdbb7, 0xff80, 
0xfefd, 0xdbb7, 0xff80, 
0xff1c, 0x1bb0, 0xff80, 
0xffed, 0xdbb7, 0xff80, 
0xfeed, 0xdd77, 0xff80, 
0xff1d, 0xdef0, 0x7f80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 
0xffff, 0xffff, 0xff80, 

0x0,    0x0,    0x0,    
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x3fff, 0xffff, 0xfe00, 
0x0,    0x0,    0x0,    
};

struct Image save_image = {
   0, 0,
   41, 13, 2,
   save_data,
   3, 0,
   NULL
};

USHORT L_data[] = {
0xffff, 0xe000, 
0xffff, 0xe000, 
0xffff, 0xe000, 
0xff7f, 0xe000, 
0xff7f, 0xe000, 
0xff7f, 0xe000, 
0xff7f, 0xe000, 
0xff7f, 0xe000, 
0xff7f, 0xe000, 
0xff07, 0xe000, 
0xffff, 0xe000, 
0xffff, 0xe000, 
0xffff, 0xe000, 

0x0,    0x0,    
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x0,    0x0,    
};

struct Image L_image = {
   0, 0,
   19, 13, 2,
   L_data,
   3, 0,
   NULL
};

USHORT R_data[] = {
0xffff, 0xe000, 
0xffff, 0xe000, 
0xffff, 0xe000, 
0xfe1f, 0xe000, 
0xfeef, 0xe000, 
0xfeef, 0xe000, 
0xfe1f, 0xe000, 
0xfeef, 0xe000, 
0xfeef, 0xe000, 
0xfeef, 0xe000, 
0xffff, 0xe000, 
0xffff, 0xe000, 
0xffff, 0xe000, 

0x0,    0x0,    
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x3fff, 0x8000, 
0x0,    0x0,    
};

struct Image R_image = {
   0, 0,
   19, 13, 2,
   R_data,
   3, 0,
   NULL
};

struct Border str_bdr = {
   -3, -2,
   1, 0,
   JAM1,
   5, lines,
   NULL
};


struct StringInfo name_str_info = {
   name_buff, undo_buff,
   0,
   STRLENGTH,
   0, 0,
   0,
   0, 0, 0,
   NULL,
   0,
   NULL
};

struct StringInfo phon_str_info = {
   phon_buff, undo_buff,
   0,
   STRLENGTH,
   0, 0,
   0,
   0, 0, 0,
   NULL,
   0,
   NULL
};

struct Gadget name_gadget = {
   NULL,
   60, 35,
   166, 8,
   GADGHCOMP,
   RELVERIFY,
   STRGADGET,
   (APTR)&str_bdr,
   NULL,
   NULL,
   0,
   (APTR)&name_str_info,
   NAME,
   NULL
};

struct Gadget phon_gadget = {
   &name_gadget,
   60, 58,
   166, 8,
   GADGHCOMP,
   RELVERIFY,
   STRGADGET,
   (APTR)&str_bdr,
   NULL,
   NULL,
   0,
   (APTR)&phon_str_info,
   PHON,
   NULL
};

struct Gadget add_gadget = {
   &phon_gadget,
   250, 28,
   41, 13,
   GADGIMAGE|GADGHCOMP,
   RELVERIFY,
   BOOLGADGET,
   (APTR)&add_image,
   NULL,
   NULL,
   0,
   NULL,
   ADD,
   NULL
};

struct Gadget start_gadget = {
   &add_gadget,
   297, 28,
   41, 13,
   GADGIMAGE|GADGHCOMP,
   RELVERIFY,
   BOOLGADGET,
   (APTR)&start_image,
   NULL,
   NULL,
   0,
   NULL,
   START,
   NULL
};

struct Gadget del_gadget = {
   &start_gadget,
   344, 28,
   41, 13,
   GADGIMAGE|GADGHCOMP,
   RELVERIFY,
   BOOLGADGET,
   (APTR)&del_image,
   NULL,
   NULL,
   0,
   NULL,
   DEL,
   NULL
};

struct Gadget left_gadget = {
   &del_gadget,
   268, 44,
   23, 13,
   GADGIMAGE|GADGHCOMP,
   RELVERIFY,
   BOOLGADGET,
   (APTR)&left_image,
   NULL,
   NULL,
   0,
   NULL,
   LEFT,
   NULL
};

struct Gadget dial_gadget = {
   &left_gadget,
   297, 44,
   41, 13,
   GADGIMAGE|GADGHCOMP,
   RELVERIFY,
   BOOLGADGET,
   (APTR)&dial_image,
   NULL,
   NULL,
   0,
   NULL,
   DIAL,
   NULL
};

struct Gadget right_gadget = {
   &dial_gadget,
   344, 44,
   23, 13,
   GADGIMAGE|GADGHCOMP,
   RELVERIFY,
   BOOLGADGET,
   (APTR)&right_image,
   NULL,
   NULL,
   0,
   NULL,
   RIGHT,
   NULL
};

struct Gadget find_gadget = {
   &right_gadget,
   250, 60,
   41, 13,
   GADGIMAGE|GADGHCOMP,
   RELVERIFY,
   BOOLGADGET,
   (APTR)&find_image,
   NULL,
   NULL,
   0,
   NULL,
   FIND,
   NULL
};

struct Gadget end_gadget = {
   &find_gadget,
   297, 60,
   41, 13,
   GADGIMAGE|GADGHCOMP,
   RELVERIFY,
   BOOLGADGET,
   (APTR)&end_image,
   NULL,
   NULL,
   0,
   NULL,
   END,
   NULL
};

struct Gadget quit_gadget = {
   &end_gadget,
   344, 60,
   41, 13,
   GADGIMAGE|GADGHCOMP,
   RELVERIFY,
   BOOLGADGET,
   (APTR)&quit_image,
   NULL,
   NULL,
   0,
   NULL,
   QUIT,
   NULL
};

struct Gadget save_gadget = {
   &quit_gadget,
   297, 12,
   41, 13,
   GADGIMAGE|GADGHCOMP,
   RELVERIFY,
   BOOLGADGET,
   (APTR)&save_image,
   NULL,
   NULL,
   0,
   NULL,
   SAVE,
   NULL
};

struct Gadget L_gadget = {
   &save_gadget,
   297, 76,
   19, 13,
   GADGIMAGE|GADGHCOMP,
   RELVERIFY|TOGGLESELECT,
   BOOLGADGET,
   (APTR)&L_image,
   NULL,
   NULL,
   0,
   NULL,
   L_CHAN,
   NULL
};

struct Gadget R_gadget = {
   &L_gadget,
   319, 76,
   19, 13,
   GADGIMAGE|GADGHCOMP|SELECTED,
   RELVERIFY|TOGGLESELECT,
   BOOLGADGET,
   (APTR)&R_image,
   NULL,
   NULL,
   0,
   NULL,
   R_CHAN,
   NULL
};

struct NewWindow NewWindow = {
   0, 0,
   394, 92,
   0, 1,
   CLOSEWINDOW | GADGETUP | VANILLAKEY,
   WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWDRAG |
   WINDOWDEPTH | NOCAREREFRESH,
   &R_gadget, NULL,
   "PhoneDir V1.0 by Ric Kalton",
   NULL, NULL,
   394, 92,
   394, 92,
   WBENCHSCREEN
   };

extern struct MsgPort *CreatePort();
 
struct IOAudio *audio_req_A = NULL, *audio_req_B = NULL;
struct MsgPort *port_A = NULL, *port_B = NULL; 
struct Device *device = NULL;

BYTE *wave_data = NULL;

UBYTE alloc_map[2][2] = {  /* Audio channel allocation maps */
   LEFT1,
   LEFT2,
   RIGHT1,
   RIGHT2
};

UWORD freq_data_hi[] = {   /* DTMF/Touch Tone frequencies - high */
   1209, 1336, 1477
};

UWORD freq_data_lo[] = {   /* DTMF/Touch Tone frequencies - low */
   697, 770, 852, 941
};

FILE *file;

UBYTE channel = R_CHAN;  /* Initial speaker = RIGHT */

void main(), openstuff(), set_disp(), closestuff(), add(), display();
void del(), set_audio(), load_data(), dial(), find(), save();
void alloc_chan(), free_chan();
BOOL compare();

void _main()
{
   BOOL flag=TRUE;
   USHORT i,code;
   ULONG class;
   APTR iaddress;
   struct IntuiMessage *message;
   openstuff();
   set_disp();
   set_audio();
   load_data();
   display();
   while (flag) {                       /* IDCMP stuff */
      WaitPort(Window->UserPort);
      if (message=(struct IntuiMessage *)GetMsg(Window->UserPort)) {
         class=message->Class;
         code=message->Code;
         iaddress=message->IAddress;
         ReplyMsg(message);
         
         switch (class) {

            case GADGETUP:
               switch (((struct Gadget *)iaddress)->GadgetID) {

                  case ADD:
                     add();
                     break;
      
                  case START:
                     current=start;
                     display();
                     break;

                  case DEL:
                     if (current) {
                        del();
                     }
                     display();
                     break;

                  case END:
                     current=end;
                     display();
                     break;

                  case LEFT:
                     if (current->last&&current) {
                        current=current->last;
                     }
                     display();
                     break;

                  case DIAL:
                        dial();
                     break;

                  case RIGHT:
                     if (current->next&&current) {
                        current=current->next;
                     }
                     display();
                     break;

                  case FIND:
                     if (current&&current->next) {
                        find();
                        display();
                     }
                     break;

                  case QUIT:
                     flag=FALSE;
                     break;

                  case SAVE:
                     save();
                     break;

                  case L_CHAN:
                    i=RemoveGList(Window,&R_gadget,2);
                     if (channel==R_CHAN) {
                        channel=L_CHAN;
                        free_chan();
                        alloc_chan();
                        R_gadget.Flags^=SELECTED;
                     }
                     L_gadget.Flags|=SELECTED;
                     AddGList(Window,&R_gadget,i,2,NULL);
                     RefreshGadgets(&R_gadget,Window,NULL);
                     break;

                  case R_CHAN:
                    i=RemoveGList(Window,&R_gadget,2);
                     if (channel==L_CHAN) {
                        channel=R_CHAN;
                        free_chan();
                        alloc_chan();
                        L_gadget.Flags^=SELECTED;
                     }
                     R_gadget.Flags|=SELECTED;
                     AddGList(Window,&R_gadget,i,2,NULL);
                     RefreshGadgets(&R_gadget,Window,NULL);
                     break;

               }
               break;

            case VANILLAKEY:
               if (code==' ') {
                  dial();
               }
               break;

            case CLOSEWINDOW:
               flag=FALSE;
               break;
         }
      }
   }

   closestuff();
}

void openstuff()
{
   IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0);
   if (IntuitionBase==NULL) {
      exit(0);
   }

   GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0);
   if (GfxBase==NULL) {
      CloseLibrary(IntuitionBase);
      exit(0);
   }

   if ((Window=(struct Window *)OpenWindow(&NewWindow))==NULL) {
      CloseLibrary(GfxBase);
      CloseLibrary(IntuitionBase);
      exit(0);
   }
   rastport=Window->RPort;
}

void set_disp()
{
   SetAPen(rastport,1);
   Move (rastport,15,41);
   Text (rastport,"Name:",5);
   Move (rastport,7,64);
   Text (rastport,"Phone:",6);
}

void closestuff()
{
   struct book_entry *pointer,*temp;

   if (device) {
      free_chan();
   }
   if (port_A) {
      DeletePort(port_A);
   }
   if (port_B) {
      DeletePort(port_B);
   }
   if (device) {
      CloseDevice((struct IORequest *)audio_req_A);
   }
   if (audio_req_A) {
      FreeMem((char *)audio_req_A, sizeof(struct IOAudio));
   }
   if (audio_req_B) {
      FreeMem((char *)audio_req_B, sizeof(struct IOAudio));
   }
   if (wave_data) {
      FreeMem((char *)wave_data, WAVESIZE);
   }

   pointer=start;
   while (pointer) {
      temp=pointer;
      pointer=pointer->next;
      FreeMem((char *)temp,sizeof(struct book_entry));
   }
   if (Window) {
      CloseWindow(Window);
   }
   if (GfxBase) {
      CloseLibrary(GfxBase);
   }
   if (IntuitionBase) {
      CloseLibrary(IntuitionBase);
   }

}

void free_chan()
{
   audio_req_A->ioa_Request.io_Command = ADCMD_FREE;
   DoIO((struct IORequest *)audio_req_A);
   audio_req_B->ioa_Request.io_Command = ADCMD_FREE;
   DoIO((struct IORequest *)audio_req_B);
}

void add()
{
   struct book_entry *temp;
   int result;
   new=(struct book_entry *)AllocMem(sizeof(struct book_entry),
                                      MEMF_CLEAR|MEMF_PUBLIC);
   if (!new) {
      closestuff();
      exit(0);
   }
   strcpy(new->name,name_buff);
   strcpy(new->phon,phon_buff);

   if (!current){
      new->next=NULL;
      new->last=NULL;
      start=new;
      end=new;
   } else {
      temp=start;
      while ((result=strcmp(new->name,temp->name)==1)&&(temp->next)) {
         temp=temp->next;
      }
      if (!temp->next&&result==1) {
         new->next=NULL;
         new->last=temp;
         temp->next=new;
         end=new;
      }
      else if (!temp->last) {
         new->next=temp;
         new->last=NULL;
         temp->last=new;
         start=new;
      } else {
         new->next=temp;
         new->last=temp->last;
         temp->last->next=new;
         temp->last=new;
      }
   }
   current=new;
}

void del()
{
   struct book_entry *temp;

   temp=current;
   if (temp==start&&temp==end) {
      current=NULL;
      start=NULL;
      end=NULL;
   }
   else if (temp==start) {
      current=temp->next;
      start=current;
      current->last=NULL;
   }
   else if (temp==end) {
      current=temp->last;
      end=current;
      current->next=NULL;
   } else {
   current=temp->next;
   temp->last->next=current;
   current->last=temp->last;
   }

   FreeMem((char *)temp,sizeof(struct book_entry));
}

void dial() 
{
   struct Message *msg;
   int n;
   char *s;
   s=phon_buff;
   while (*s) {
      n=(int)*s++;
      if ((n<48||n>57) && n!=42 && n!=35) {
        continue;
      }
      n-=48;
      if (n==0) 
         n=11;
      if (n==-6)
         n=10;
      if (n==-13) 
         n=12;
      audio_req_A->ioa_Period = CLOCK/(freq_data_hi[(n+2)%3]*WAVESIZE);
      audio_req_A->ioa_Cycles = CLOCK/(10*CLOCK/freq_data_hi[(n+2)%3]);
      
      audio_req_B->ioa_Period = CLOCK/(freq_data_lo[(n-1)/3]*WAVESIZE);
      audio_req_B->ioa_Cycles = CLOCK/(10*CLOCK/freq_data_lo[(n-1)/3])+1;

      BeginIO((struct IORequest *)audio_req_A);
      BeginIO((struct IORequest *)audio_req_B);

      Wait(1L << port_A->mp_SigBit);          /* RKM Libs and Devs 1.3 */
      msg=(struct Message *)GetMsg(port_A);   /* says that WaitIO does */
                                              /* not always work, hence */
      Wait(1L << port_B->mp_SigBit);          /* using Wait instead.    */
      msg=(struct Message *)GetMsg(port_B);            

   Delay(5);    /* Wait 100ms approx. between tones. */
   }
}

void find()
{
   char *key=name_buff;
   struct book_entry *temp;
   temp=start;

   while (temp) {
      if (compare(key,temp->name)) {
         current=temp;
         break;
      } else {
         temp=temp->next;
      }
   }
}

BOOL compare(key,name)
char *key, *name;
{
   BOOL flag=TRUE;
   while (*key && *name) {
      if (toupper(*key)!=toupper(*name)) {
         flag=FALSE;
         break;
      } else {
         key++;
         name++;
      }
   }
   return (flag);
}

void display()
{
   if (current) {
      strcpy(name_buff,current->name);
      strcpy(phon_buff,current->phon);
   } else {
      name_buff[0]='\0';
      phon_buff[0]='\0';
   }
   RefreshGadgets(&phon_gadget,Window,NULL);
}

void set_audio()
{
   if ((audio_req_A=(struct IOAudio *)AllocMem(sizeof(struct IOAudio),
         MEMF_PUBLIC|MEMF_CLEAR))==NULL) {
            closestuff();
   }
   if ((audio_req_B=(struct IOAudio *)AllocMem(sizeof(struct IOAudio),
         MEMF_PUBLIC|MEMF_CLEAR))==NULL) {
            closestuff();
   }
   if ((wave_data=(BYTE *)AllocMem(WAVESIZE,MEMF_CHIP))==NULL) {
      closestuff();
   }
   if (OpenDevice(AUDIONAME,0,(struct IORequest *)audio_req_A,0)) {
      closestuff();
   }
   device = audio_req_A->ioa_Request.io_Device;

   audio_req_A->ioa_Request.io_Message.mn_Node.ln_Pri = SOUNDPRI;
   if ((port_A = CreatePort("sound port_A",0))==NULL) {
      closestuff();
   }
   audio_req_A->ioa_Request.io_Message.mn_ReplyPort = port_A;

   audio_req_B->ioa_Request.io_Message.mn_Node.ln_Pri = SOUNDPRI;
   if ((port_B = CreatePort("sound port_B",0))==NULL) {
      closestuff();
   }
   audio_req_B->ioa_Request.io_Message.mn_ReplyPort = port_B;   
   audio_req_B->ioa_Request.io_Device = device;
   audio_req_B->ioa_AllocKey = audio_req_A->ioa_AllocKey;
   audio_req_B->ioa_Request.io_Unit = audio_req_A->ioa_Request.io_Unit;

   alloc_chan();

   wave_data[0]=127;
   wave_data[1]=-127;
}

void load_data()
{
   char f_name[STRLENGTH];
   char f_phon[STRLENGTH];

   struct book_entry *new=NULL, *old=NULL;

   if (file=fopen("directory.data","rb")) {

      while ((fread((char *)f_name,sizeof(f_name),1,file)) &&
             (fread((char *)f_phon,sizeof(f_phon),1,file))) {

         new=(struct book_entry *)AllocMem(sizeof(struct
               book_entry),MEMF_CLEAR|MEMF_PUBLIC);

         if (!new) {
            closestuff();
            exit(0);
         }
         strcpy(new->name,f_name);
         strcpy(new->phon,f_phon);

         if (old) {
            new->last=old;
            old->next=new;
         } else {
            start=new;
         }
         end=new;
         old=new;
      }
      fclose(file);
      current=start;
   }
}

void save()
{
   struct book_entry *temp;
   if (file=fopen("directory.data","wb")) {

      temp=start;
      while(temp) {
         fwrite(temp->name,sizeof(temp->name),1,file);
         fwrite(temp->phon,sizeof(temp->phon),1,file);
         temp=temp->next;
      }
      fclose(file);
   }
}

void alloc_chan()
{
   struct Message *msg;

   audio_req_A->ioa_Request.io_Flags = ADIOF_NOWAIT;
   audio_req_A->ioa_Request.io_Command = ADCMD_ALLOCATE;
   audio_req_A->ioa_Data = &alloc_map[channel][0];
   audio_req_A->ioa_Length = sizeof(alloc_map[channel]);

   audio_req_B->ioa_Request.io_Command = ADCMD_ALLOCATE;
   audio_req_B->ioa_Request.io_Flags = ADIOF_NOWAIT;
   audio_req_B->ioa_Data = &alloc_map[channel][0];
   audio_req_B->ioa_Length = sizeof(alloc_map[channel]);

   BeginIO((struct IORequest *)audio_req_A);
   BeginIO((struct IORequest *)audio_req_B);

   Wait(1L << port_A->mp_SigBit);
   msg=(struct Message *)GetMsg(port_A);
   
   Wait(1L << port_B->mp_SigBit);
   msg=(struct Message *)GetMsg(port_B);

   audio_req_A->ioa_Request.io_Command = CMD_WRITE;
   audio_req_A->ioa_Request.io_Flags = ADIOF_PERVOL;
   audio_req_A->ioa_Data = wave_data;
   audio_req_A->ioa_Length = WAVESIZE;
   audio_req_A->ioa_Volume = VOLUME;

   audio_req_B->ioa_Request.io_Command = CMD_WRITE;
   audio_req_B->ioa_Request.io_Flags = ADIOF_PERVOL;
   audio_req_B->ioa_Data = wave_data;
   audio_req_B->ioa_Length = WAVESIZE;
   audio_req_B->ioa_Volume = VOLUME-5; 
}                                       
