/**********************************************************************************
 The DotDash 1.0
 Author: Gisle J. Bjoerneseth - gisle [curly a'ish thing] break {dot thing} org
 Date released: 1 Febr 2005
 
 This supplied source code is the main part of the simpletron app. for
 the Palm Pilot. The programming interface and such has changed so much over the years that
 I see no point in releasing the rest of the project files. 
 
 This sourcecode is quite a few years old, dating back to 1997/1998 and I have 
 done no development whatsoever on it since. It is actually a port from a 
 microcontroller memory keyer I once made. There is a few comments in the code
 probably a few bugs and inefficiencies. However this is as it is. Please use 
 it for whatever you like, but mention my name if you make an app or use it
 for something else where a number of people might see/use it.

 **********************************************************************************/
 
#include <Pilot.h>				// all the system toolbox headers
#include "TemplateRsc.h"			// application resource defines

#include <SysEvtMgr.h>

/***********************************************************************
 * Global defines for this module
 **********************************************************************/

#define version20	0x02000000		//PalmOS 2.0 version number
#define SpeedButtonGroup	1		//group number of morse speed  push buttons

#define appFileCreator			'GB98'
#define appPrefID					0
#define appPrefVersion				1
#define MorseManAppID		'GB98'
#define MorseManDBType	'Data'

/***********************************************************************
 * Global variables for this module
 **********************************************************************/
static UInt SoundAmp;		// default sound amplitude
static MenuBarPtr		CurrentMenu = NULL;	// P2. ptr to current menu
short Speed=0;
static UInt GVolt,GWarn,GCrit;
static SysBatteryKind GType;

EventType	LastMenuEvent;
Word LastMenuClicked;

// This is the structure of the data stored in the state file.
typedef struct {
	Boolean			ShowMorse;
	Boolean			ViewRealTime;
	Boolean			ClearInput;
	Boolean			Randomize;
	int				SpeedButton;
	short			Speed;
} MorseManPreferenceType;

/*--------------------------------------*/
/* Record structure for program database */
/*--------------------------------------*/
typedef struct {
	Char Name[20];
	Char TextFile[250];
} dbRecord;

char MorseManDBName[]="MorseManDB";
DmOpenRef	MorseManDB;

/***********************************************************************
 * Prototypes for internal functions
 **********************************************************************/
static int StartApplication(void);
static void StopApplication(void);
static void SetCurrentMenu(Word rscID);	// P2. set new current menu
static Boolean MainFormHandleEvent(EventPtr event);
static void EventLoop(void);
static void PlayNote(short Note, int duration);
static void Morsewhat(int bokstav);
static void Morseout(unsigned int letter);
static void EditDoMenuCommand (Word command);
static FieldPtr GetFocusObjectPtr (void);
static VoidPtr GetObjectPtr(Word objectID);
static int RandN(int MaxNo);
void Voltage(int Volts,Ptr RetnStr);
static Err RomVersionCompatible (DWord requiredVersion, Word launchFlags);
static void MorseRandomAbbreviation(void);
static char* RandomizeAlphabet(char *instring);
void LearnAlphabetXX(int from,  int count);
void TrainXXrandomwords(int NumberOfWords);
static Boolean OpenDataBase(void);
static void addRecord(Char FileName[20]);
static dbRecord getRecord(UInt recNum);
void LoadProgram(int ListItem);
void SaveLoadProgram(void);
static void updateRecordList(FormPtr form,int fieldID);
CharPtr makeListItem(dbRecord rec);


/* ----------------------------------------------------- */
/* RandN                                                 */
/*   This function generates a random number between 0   */
/*   and MaxNo                                           */
/* Parms                                                 */
/*   MaxNo - Maximum number to be returned               */
/* Returns                                               */
/*   A random integer                                    */
/* ----------------------------------------------------- */

int RandN(int MaxNo)
{
  return((int)(((double)SysRandom(0) * (double)MaxNo) / (double)sysRandomMax));
}



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


/*------------------------------------------------------ */
void Morseout(unsigned int letter)
{
int i,letterlength,dot,dash,frequency,shortdelay,longdelay,worddelay=0;

frequency=3;
if (Speed == 0) Speed =7;
 dot=(SysTicksPerSecond()/10)*Speed;

 dash=dot*3;
 shortdelay=dot/10;
 longdelay=dash*10;
 worddelay=dot*40;

letterlength=letter;
letterlength=letterlength >>5; //length encoded in the uppermost three bits
for(i=letterlength-1;i>=0;i--)
	{
	if((letter>>i)%2==0) 
			{	
				PlayNote(frequency,dash);
				SysTaskDelay(shortdelay);//Delay_Ms_4MHz(shortdelay);
			}
	else
		{
		PlayNote(frequency,dot);
		SysTaskDelay(shortdelay);//Delay_Ms_4MHz(shortdelay);
		}
	}
SysTaskDelay(shortdelay);//Delay_Ms_4MHz(shortdelay);
SysTaskDelay(shortdelay);//Delay_Ms_4MHz(shortdelay);
}

void Morsewhat(int bokstav)
{
	FieldPtr 	FldPtrDotDash;		//HSK
	FormPtr		frm;
	Boolean Signs;
	
			frm = FrmGetFormPtr(HSKTemplateMainForm);
			FldPtrDotDash = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, HSKTemplateMainDotDashField))));
			Signs = (CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainCBSignCheckbox)))!=0);
			

			EvtResetAutoOffTimer();		//resetter autoofftimeren  slik at piloten ikke skrur seg av under morsing....

	switch(bokstav)
		{
		
		case 'A': 

		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o -       ",10);					
//		FrmSetFocus(frm, HSKTemplateMainEdResultField);
		Morseout(66);//Morseout(0b01000010); //A 
		break;
		
		case 'B': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- o o o   ",10);					
		Morseout(135);//Morseout(0b10000111); //B 
		break;
		
		case 'C': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- o - o   ",10);					
		Morseout(133);//Morseout(0b10000101); //C
		break;

		case 'D': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- o o     ",10);					
		Morseout(99);//Morseout(0b01100011); //D
		break;

		case 'E': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o         ",10);					
		Morseout(33);//Morseout(0b00100001); //E
		break;

		case 'F': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o o - o   ",10);					
		Morseout(141);//Morseout(0b10001101); //F 
		break;

		case 'G': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- - o     ",10);					
		Morseout(97);//Morseout(0b01100001); //G 
		break;

		case 'H': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o o o o   ",10);					
		Morseout(143);//Morseout(0b10001111); //H 
		break;

		case 'I': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o o       ",10);					
		Morseout(67);//Morseout(0b01000011); //I 
		break;

		case 'J': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o - - -   ",10);					
		Morseout(136);//Morseout(0b10001000); //J 
		break;

		case 'K': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- o -     ",10);					
		Morseout(98);//Morseout(0b01100010); //K 
		break;

		case 'L': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o - o o   ",10);					
		Morseout(139);//Morseout(0b10001011); //L
		break;

		case 'M': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- -       ",10);					
		Morseout(64);//Morseout(0b01000000); //M 
		break;

		case 'N': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- o       ",10);					
		Morseout(65);//Morseout(0b01000001); //N 
		break;

		case 'O': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- - -     ",10);					
		Morseout(96);//Morseout(0b01100000); //O 
		break;

		case 'P': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o - - o   ",10);					
		Morseout(137);//Morseout(0b10001001); //P
		break;

		case 'Q': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- - o -   ",10);					
		Morseout(130);//Morseout(0b10000010); //Q
		break;

		case 'R': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o - o     ",10);					
		Morseout(101);//Morseout(0b01100101); //R 
		break;

		case 'S': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o o o     ",10);					
		Morseout(103);//Morseout(0b01100111); //S 
		break;

		case 'T': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "-         ",10);					
		Morseout(32);//Morseout(0b00100000); //T
		break;

		case 'U': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o o -     ",10);					
		Morseout(102);//Morseout(0b01100110); //U 
		break;

		case 'V': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o o o -   ",10);					
		Morseout(142);//Morseout(0b10001110); //V 
		break;

		case 'W': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o - -     ",10);					
		Morseout(100);//Morseout(0b01100100); //W 
		break;

		case 'X': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- o o -   ",10);					
		Morseout(134);//Morseout(0b10000110); //X 
		break;

		case 'Y': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- o - -   ",10);					
		Morseout(132);//Morseout(0b10000100); //Y 
		break;

		case 'Z': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- - o o   ",10);					
		Morseout(131);//Morseout(0b10000011); //Z 
		break;

/*
		case '': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		FldInsert(FldPtrDotDash, "o - o -   ",10);					
		Morseout(138);//Morseout(0b10001010);
		break;

		case '': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		FldInsert(FldPtrDotDash, "- - - o   ",10);					
		Morseout(129);//Morseout(0b10000001); // 

		break;
		case '': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		FldInsert(FldPtrDotDash, "o - - o - ",10);					
		Morseout(178);//Morseout(0b10110010); // 
		break;
*/
	
		case '1': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o - - - - ",10);					
		Morseout(176);//Morseout(0b10110000); //1 
		break;

		case '2': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o o - - - ",10);					
		Morseout(184);//Morseout(0b10111000); //2 
		break;

		case '3': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o o o - - ",10);					
		Morseout(188);//Morseout(0b10111100); //3 
		break;

 		case '4': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o o o o - ",10);					
 		Morseout(190);//Morseout(0b10111110); //4
		break;

		case '5': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "o o o o o ",10);					
		Morseout(191);//Morseout(0b10111111); //5 
		break;

		case '6': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- o o o o ",10);					
		Morseout(175);//Morseout(0b10101111); //6 
		break;

		case '7': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- - o o o ",10);					
		Morseout(167);//Morseout(0b10100111); //7 
		break;

		case '8': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- - - o o ",10);					
		Morseout(163);//Morseout(0b10100011); //8 
		break;

		case '9': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- - - - o ",10);					
		Morseout(161);//Morseout(0b10100001); //9 
		break;

		case '0': 
		FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));
		if (Signs) FldInsert(FldPtrDotDash, "- - - - - ",10);					
		Morseout(160);//Morseout(0b10100000); //0 
		break;
		
		default:SysTaskDelay((((SysTicksPerSecond()/10)*Speed)/10)*7);//Morseout(0b10101010);
		}

bokstav=0;
}


void PlayNote(short Note, int duration)
{
  SndCommandType snd;
  Word err;
//				A	H		C		D		E	F		G        A
  int Hz[24] = {440,466,494,523,554,587,622,659,698,740,784,831,880,
                932,988,1047,1109,1175,1245,1319,1397,1480,1568,1660};
//					H	C			D		E		F		G
  if (Note>=100)
    Note = Note-100;
  if (Note<0)
    return;
  if (Note>23)
    return;

  snd.cmd = (SndCmdIDType)1;
  snd.param1 = Hz[Note];
  snd.param2 = duration;
  snd.param3 = SoundAmp;		// default sound amplitude//sndMaxAmp;
  err = SndDoCmd(0,&snd,0);  
}
/***********************************************************************
 *
 * FUNCTION:    GetFocusObjectPtr
 *
 * DESCRIPTION: P4. This routine returns a pointer to the field object, in 
 *              the current form, that has the focus.
 *
 * PARAMETERS:  nothing
 *
 * RETURNED:    pointer to a field object or NULL of there is no focus
 *
 ***********************************************************************/
static FieldPtr GetFocusObjectPtr (void)
{
	FormPtr frm;
	Word focus;
	
	// get a pointer to tha active form and the index of the form object with focus
	frm = FrmGetActiveForm ();
	focus = FrmGetFocus (frm);

	// if no object has the focus return NULL pointer
	if (focus == noFocus)
		return (NULL);
		
	// return a pointer to the object with focus
	return (FrmGetObjectPtr (frm, focus));
}

/***********************************************************************
 *
 * FUNCTION:    GetObjectPtr
 *
 * DESCRIPTION: P10. This routine returns a pointer to an object in the active form.
 *
 * PARAMETERS:  objectID - id of the object
 *
 * RETURNED:    pointer to the object's data structure
 *
 ***********************************************************************/
static VoidPtr GetObjectPtr(Word objectID)
{
	FormPtr frm;
	
	frm = FrmGetActiveForm();
	return(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, objectID)));
}



/* ----------------------------------------------------- */
/* Voltage                                               */
/*   This function returns a formatted text string,      */
/*   in the format 9.99v                                 */
/* Parms                                                 */
/*   The voltage as a number of thousandths of a volt    */
/* Returns                                               */
/*   A pointer to the text string containing the         */
/*   formatted voltage.                                  */
/* ----------------------------------------------------- */

void Voltage(int Volts,Ptr RetnStr)
{
  char wrk[10];

  StrIToA(wrk,Volts/100);
  StrCopy(RetnStr,wrk);
  StrCat(RetnStr,".");
  StrIToA(wrk,(Volts/10)-((Volts/100)*10));
  StrCat(RetnStr,wrk);
  StrIToA(wrk,Volts-((Volts/10)*10));
  StrCat(RetnStr,wrk);
  StrCat(RetnStr,"v");
}

/***********************************************************************
 *
 * FUNCTION:    RomVersionCompatible
 *
 * DESCRIPTION: P4. Check that the ROM version meets your
 *              minimum requirement.  Warn if the app was switched to.
 *
 * PARAMETERS:  requiredVersion - minimum rom version required
 *                                (see sysFtrNumROMVersion in SystemMgr.h 
 *                                for format)
 *              launchFlags     - flags indicating how the application was
 *											 launched.  A warning is displayed only if
 *                                these flags indicate that the app is 
 *											 launched normally.
 *
 * RETURNED:    zero if rom is compatible else an error code
 *                             
 ***********************************************************************/
static Err RomVersionCompatible (DWord requiredVersion, Word launchFlags)
{
	DWord romVersion;
	
	
	// See if we're on in minimum required version of the ROM or later.
	// The system records the version number in a feature.  A feature is a
	// piece of information which can be looked up by a creator and feature
	// number.
	FtrGet(sysFtrCreator, sysFtrNumROMVersion, &romVersion);
	if (romVersion < requiredVersion)
		{
		// If the user launched the app from the launcher, explain
		// why the app shouldn't run.  If the app was contacted for something
		// else, like it was asked to find a string by the system find, then
		// don't bother the user with a warning dialog.  These flags tell how
		// the app was launched to decided if a warning should be displayed.
		if ((launchFlags & (sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp)) ==
			(sysAppLaunchFlagNewGlobals | sysAppLaunchFlagUIApp))
			{
			FrmAlert (RomIncompatibleAlert);
		
			// Pilot 1.0 will continuously relaunch this app unless we switch to 
			// another safe one.  The sysFileCDefaultApp is considered "safe".
			if (romVersion < 0x02000000)
				{
				Err err;
				
				AppLaunchWithCommand(sysFileCDefaultApp, sysAppLaunchCmdNormalLaunch, NULL);
				}
			}
		
		return (sysErrRomIncompatible);
		}

	return 0;
}


/***********************************************************************
 *
 * FUNCTION:    EditDoMenuCommand
 *
 * DESCRIPTION: P4. This routine performs the menu command specified.
 *
 * PARAMETERS:  command  - menu item id
 *
 * RETURNED:    nothing
 *
 ***********************************************************************/
static void EditDoMenuCommand (Word command)
{
	FieldPtr	fld;
	FormPtr	frm;
	EventType	newEvent;
	int i,j=0;
	FormPtr	MainFrm;
	FieldPtr	FldPtrOutText;

/*
	char		Buf[60], Buf2[15];
	char 		*txtptr,*txtptr2;
	char outsign=0;
	txtptr=Buf;
	txtptr2=Buf2;
*/		
	switch (command)
		{

		case MainOptionsSave:
			SaveLoadProgram();
			break;
	
		case MainOptionsLoad:
			SaveLoadProgram();
			break;

		case MainOptionsDelete:
			SaveLoadProgram();
			break;

		
		case MainOptionsNew:
			MainFrm = FrmGetFormPtr(HSKTemplateMainForm);
			FldPtrOutText	= (FieldPtr)(FrmGetObjectPtr(MainFrm, (FrmGetObjectIndex(MainFrm, HSKTemplateMainEdOutTextField))));	
			FldDelete(FldPtrOutText, 0, FldGetTextLength(FldPtrOutText));
			break;

		case MainOptionsMorse:
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler
			MemSet(&LastMenuEvent, sizeof(EventType), 0);
	   		LastMenuEvent.eType = ctlSelectEvent;
	   		LastMenuEvent.data.ctlEnter.controlID=HSKTemplateMainBtnMorseButton;
   			EvtAddEventToQueue(&LastMenuEvent);	//poster en buttonclick til eventken for  kjre knappens kodeblokk
												//slik at "Morse" ogs funker p repeat/nilevent
			break;

		case MainOptionsExit:
			MemSet(&newEvent, sizeof(EventType), 0);
	   		newEvent.eType = appStopEvent;
   			EvtAddEventToQueue(&newEvent);
			break;


		case Train1randomword:
			TrainXXrandomwords(1);
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blokka i nilevent handler
			break;


		case Train5randomwords:
			TrainXXrandomwords(5);
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler		
			break;


		case Train10randomwords:
			TrainXXrandomwords(10);
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler		
			break;

		case Train20randomwords:
			TrainXXrandomwords(20);
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler		
			break;

		case Train1randomabbreviation:
			MorseRandomAbbreviation();
	   		LastMenuClicked=Train1randomabbreviation;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler			
			break;

		case TrainQSORegversiononly:
			frm = FrmInitForm(HSKTemplateInfoForm);
			FrmDoDialog(frm);
 			FrmDeleteForm(frm);
			break;
				
		case LearnAlphabetAE:
			LearnAlphabetXX('A',5);	
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler
			break;

		case LearnAlphabetFJ:
			LearnAlphabetXX('F',5);	
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler
			break;

		case LearnAlphabetKO:
			LearnAlphabetXX('K',5);	
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler
			break;

		case LearnAlphabetPT:
			LearnAlphabetXX('P',5);	
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler
			break;

		case LearnAlphabetUZ:
			LearnAlphabetXX('U',6);	
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler
			break;

		case LearnNumbers04:
			LearnAlphabetXX('0',5);	
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler
			break;

		case LearnNumbers59:
			LearnAlphabetXX('5',5);	
	   		LastMenuClicked=command;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler
			break;

		case HelpHelp:
			FrmHelp( HelpMainHelpString );			
			break;
			
		case HelpMorseAlphabet:
			FrmHelp( HelpMorseCodeString );
			break;

		case HelpAbout:
			frm = FrmInitForm(HSKTemplateInfoForm);
/*
			PlayNote(1,150);
			PlayNote(3,150);			   		
			PlayNote(5,150);   		
			PlayNote(6,150);   		
			PlayNote(8,150);   		
			PlayNote(5,150);   		
			PlayNote(8,150);   		
			SysTaskDelay(15);
			PlayNote(9,150);   		
			PlayNote(6,150);   		
			PlayNote(9,150);
			SysTaskDelay(15);			   		
			PlayNote(8,150);   		
			PlayNote(5,150);   		
			PlayNote(8,150);   		
			SysTaskDelay(15);			   		
			PlayNote(1,150);
			PlayNote(3,150);			   		
			PlayNote(5,150);   		
			PlayNote(6,150);   		
			PlayNote(8,150);   		
			PlayNote(5,150);   		
			PlayNote(8,150);   		
			
			PlayNote(13,150);   		
			PlayNote(11,150);
			PlayNote(8,150);   		   		
			PlayNote(4,150);
			PlayNote(8,150);
			PlayNote(11,250);
			SysTaskDelay(5);			   		
			PlayNote(11,250);   		   		   		
*/
			FrmDoDialog(frm);
 			FrmDeleteForm(frm);

			for (i=1;i<23;i++)PlayNote(i,5); 
			SysTaskDelay(10);
			for (i=1;i<23;i++)PlayNote(i,5);			  		
			for (i=23;i>0;i--)PlayNote(i,5); 

			break;

		case EditCut:			// Do a cut to the clipboard if text is highlighted.
			fld = GetFocusObjectPtr();
			if (fld)
				FldCut(fld);
			break;
		
		case EditCopy:			// Copy the highlighted text to the clipboard.
			fld = GetFocusObjectPtr();
			if (fld)
				FldCopy(fld);	
			break;
		
		case EditPaste:			// Do a paste from the clipboard.
			fld = GetFocusObjectPtr();
			if (fld)
				FldPaste(fld);		
			break;
			
		case EditUndo:			// undo the last text change.
			fld = GetFocusObjectPtr();
			if (fld)
				FldUndo(fld);
			break;
		
		case EditSelectAll:	// Select all the existing text.
			fld = GetFocusObjectPtr();
			if (fld)
				FldSetSelection(fld, 0, FldGetTextLength(fld));
			break;
			
		case EditKeyboard:		// display the on screen keyboard
			SysKeyboardDialog (kbdAlpha);
			break;
			
		case EditGraffiti:		// Display the graffiti reference screen
			SysGraffitiReferenceDialog (referenceDefault);
			break;
			
		}	
}


/***********************************************************************
 *
 * FUNCTION:     StartApplication
 *
 * DESCRIPTION:  This routine sets up the initial state of the application.
 *
 * PARAMETERS:   None.
 *
 * RETURNED:     Nothing.
 *
 ***********************************************************************/
static int StartApplication(void)
{
	FormPtr	frm;
	ControlPtr	ctl;
	int controlID=0,error=0;
	Word prefsSize;
	MorseManPreferenceType prefs;
	
	// Initialize and draw the main memo pad form.
	frm = FrmInitForm(HSKTemplateMainForm);	
	FrmSetActiveForm(frm);
	FrmDrawForm(frm);

	// Get SoundAmp for the sound code.  If game sounds are desired use
	// the default sound else set the volume to zero to turn it off.
	if (PrefGetPreference(prefGameSoundLevel) != slOff)
		SndGetDefaultVolume(NULL, NULL, &SoundAmp);
	else
		SoundAmp = 0;

	SetCurrentMenu(MainFormMenuBar);		// P2. set the current menu to the main menu
	
	error = OpenDataBase();
	if(error) return error;

	//load preferences
	prefsSize = sizeof (MorseManPreferenceType);
	if (PrefGetAppPreferences (appFileCreator, appPrefID, &prefs, &prefsSize, 
		true) != noPreferenceFound)
		{
		ctl = GetObjectPtr(HSKTemplateMainCBSignCheckbox);
		CtlSetValue(ctl, prefs.ShowMorse);
		ctl = GetObjectPtr(HSKTemplateMainViewRealTimeCheckbox);
		CtlSetValue(ctl, prefs.ViewRealTime);
		ctl = GetObjectPtr(HSKTemplateMainClearInputCheckbox);
		CtlSetValue(ctl, prefs.ClearInput);
		ctl = GetObjectPtr(HSKTemplateMainRandomizeCheckbox);
		CtlSetValue(ctl, prefs.Randomize);

		FrmSetControlGroupSelection (frm, SpeedButtonGroup, prefs.SpeedButton);
		Speed=prefs.Speed;		
		}
		else
			{
			//set speedbutton 5 as default
			frm = FrmGetFormPtr(HSKTemplateMainForm);
			controlID = HSKTemplateMainSpeed5PushButton;
			FrmSetControlGroupSelection (frm, SpeedButtonGroup, controlID);
			}

			//Nagscreen
			frm = FrmInitForm(HSKTemplateInfoForm);
			FrmDoDialog(frm);
 			FrmDeleteForm(frm);
	
return 0;
}


static void StopApplication(void)
{
MorseManPreferenceType prefs;
FormPtr	frm;
Byte index;
	
	frm = FrmGetFormPtr(HSKTemplateMainForm);
	prefs.ShowMorse=(CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainCBSignCheckbox)))!=0);
	prefs.ViewRealTime=(CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainViewRealTimeCheckbox)))!=0);
	prefs.ClearInput=(CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainClearInputCheckbox)))!=0);
	prefs.Randomize=(CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainRandomizeCheckbox)))!=0);

	
	index = FrmGetControlGroupSelection (frm, SpeedButtonGroup);
	prefs.SpeedButton = FrmGetObjectId (frm, index);
	prefs.Speed=Speed;

	PrefSetAppPreferences (appFileCreator, appPrefID, appPrefVersion,&prefs, sizeof (prefs), true);

	DmCloseDatabase(MorseManDB);
}

/***********************************************************************
 *
 * FUNCTION:    SetCurrentMenu
 *
 * DESCRIPTION: P2. This routine loads the specified menu resource and makes
 *              it the current menu.  
 *
 * PARAMETERS:  rscID  - resource id of the new menu
 *
 * RETURNED:    nothing
 *
 ***********************************************************************/
static void SetCurrentMenu(Word rscID)
{
		// Dispose of an existing current menu.
	if (CurrentMenu)
		MenuDispose(CurrentMenu);
	
	// Set the current menu and remember it.
	CurrentMenu = MenuInit(rscID);
}


/***********************************************************************
 *
 * FUNCTION:		MainFormHandleEvent
 *
 * DESCRIPTION:	Handles processing of events for the main form.
 *
 * PARAMETERS:		event		- the most recent event.
 *
 * RETURNED:		True if the event is handled, false otherwise.
 *
 ***********************************************************************/
static Boolean MainFormHandleEvent(EventPtr event)
{
	Boolean		handled = false;
//	EventType	newEvent;
	FormPtr		frm;
	FieldPtr 	FldPtrResult;		//HSK
	FieldPtr 	FldPtrOut;		//HSK
	FieldPtr 	FldPtrDotDash;		//HSK
	char		Buf[8];	//HSK
	char temptxt[10];
	char 		*txtptr;
	UInt i,volt,warnlev,critlev=0;
	Boolean Clear,View,Repeat;
	SysBatteryKind btype;
	txtptr=Buf;			//setter txtptr til  peke p Buf[]. Man kan godt bruke en CharPtr eller en char[] direkte.


   if (event->eType == ctlSelectEvent)
	   {

	    if (event->data.ctlEnter.controlID == HSKTemplateMainSpeed1PushButton)
	    	{
			Speed=12;
	    	}
  	    if (event->data.ctlEnter.controlID == HSKTemplateMainSpeed2PushButton)
	    	{
			Speed=11;
	    	}
	    if (event->data.ctlEnter.controlID == HSKTemplateMainSpeed3PushButton)
	    	{
			Speed=10;
	    	}
	    if (event->data.ctlEnter.controlID == HSKTemplateMainSpeed4PushButton)
	    	{
			Speed=9;
	    	}
	    if (event->data.ctlEnter.controlID == HSKTemplateMainSpeed5PushButton)
	    	{
			Speed=8;
	    	}
	    if (event->data.ctlEnter.controlID == HSKTemplateMainSpeed6PushButton)
	    	{
			Speed=7;
	    	}
	    if (event->data.ctlEnter.controlID == HSKTemplateMainSpeed7PushButton)
	    	{
			Speed=6;
	    	}
	    if (event->data.ctlEnter.controlID == HSKTemplateMainSpeed8PushButton)
	    	{
			Speed=5;
	    	}
	    if (event->data.ctlEnter.controlID == HSKTemplateMainSpeed9PushButton)
	    	{
			Speed=4;
	    	}

	
   		if (event->data.ctlEnter.controlID==HSKTemplateMainBtnMorseButton)
		{

			frm = FrmGetFormPtr(HSKTemplateMainForm);
			FldPtrOut = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, HSKTemplateMainEdOutTextField))));
			FldPtrResult = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, HSKTemplateMainEdResultField))));
			FldPtrDotDash = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, HSKTemplateMainDotDashField))));			

			txtptr=FldGetTextPtr (FldPtrOut);		//henter ut infoen fra edit feltet (txtptr er en peker til Buf[])

			if (txtptr != NULL)	LastMenuClicked=MainOptionsMorse;		//gi itemID'en p siste menyklikk til repeat blockka i nilevent handler
				else LastMenuClicked=0;
				
			View = (CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainViewRealTimeCheckbox)))!=0);

			if (txtptr != NULL)
			for (i=0;i<StrLen(txtptr);i++)
			{
			if (txtptr[i]>96 && txtptr[i]<123)
				{
				FldDelete(FldPtrResult, 0, FldGetTextLength(FldPtrResult));
				if (View) if (txtptr != NULL) FldInsert(FldPtrResult, txtptr,i+1);//FldInsert(FldPtr, Buf, StrLen(Buf));
				Morsewhat(txtptr[i]-32);
				}
			else 
				{
				FldDelete(FldPtrResult, 0, FldGetTextLength(FldPtrResult));
				if (View) if (txtptr != NULL) FldInsert(FldPtrResult, txtptr,i+1);//FldInsert(FldPtr, Buf, StrLen(Buf));
				Morsewhat(txtptr[i]);
				}
		    if(EvtSysEventAvail(true)) i=StrLen(txtptr)-1; //aybryter om en event er i i ken..
			}			  		
			

			FldDelete(FldPtrResult, 0, FldGetTextLength(FldPtrResult));
			if (txtptr != NULL) FldInsert(FldPtrResult, txtptr,StrLen(txtptr));
			FldDelete(FldPtrDotDash, 0, FldGetTextLength(FldPtrDotDash));

			Clear = (CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainClearInputCheckbox)))!=0);
			if (Clear) FldDelete(FldPtrOut, 0, FldGetTextLength(FldPtrOut));
		
   		
		}
   		
		handled = true;
	}



	else if (event->eType == menuEvent)		// P2. process menu events for this form
		{

			// First clear the menu status from the display.
			MenuEraseStatus(0);
			EditDoMenuCommand(event->data.menu.itemID);
			handled = true;
		}
	
	else if (event->eType == nilEvent)
		{

		volt = SysBatteryInfo(false,&warnlev,&critlev,NULL,&btype,NULL);
	    
	    if (volt!=GVolt)
      		{
        	GVolt=volt;
	        Voltage(volt,temptxt);
	        WinDrawChars(temptxt,StrLen(temptxt),45,149);
	      	}

		frm = FrmGetFormPtr(HSKTemplateMainForm);
		Repeat = (CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainCBRepeatCheckbox)))!=0);

		if (Repeat && LastMenuClicked)						//her legger jeg til en menu event slik at siste menyklikk blir gjentatt.....
			{
			MemSet(&LastMenuEvent, sizeof(EventType), 0);
	   		LastMenuEvent.eType = menuEvent;
	   		LastMenuEvent.data.menu.itemID = LastMenuClicked;
	   		LastMenuClicked=0;
   			EvtAddEventToQueue(&LastMenuEvent);
			}

		

      	handled = true;
		}


	return handled;
}


/***********************************************************************
 *
 * FUNCTION:		EventLoop
 *
 * DESCRIPTION:	A simple loop that obtains events from the Event
 *						Manager and passes them on to various applications and
 *						system event handlers before passing them on to
 *						FrmHandleEvent for default processing.
 *
 * PARAMETERS:		None.
 *
 * RETURNED:		Nothing.
 *
 ***********************************************************************/
static void EventLoop(void)
{
	EventType	event;
	Word			error;
	
	do
		{
		// Get the next available event.
		EvtGetEvent(&event, sysTicksPerSecond);
		
		// Give the system a chance to handle the event.
		if (! SysHandleEvent(&event))

			// P2. Give the menu bar a chance to update and handle the event.	
			if (! MenuHandleEvent(CurrentMenu, &event, &error))

				// Give the application a chance to handle the event.
				if (! MainFormHandleEvent(&event))

					// Let the form object provide default handling of the event.
					FrmHandleEvent(FrmGetActiveForm(), &event);
		}
	while (event.eType != appStopEvent);
}


/***********************************************************************
 *
 * FUNCTION:		PilotMain
 *
 * DESCRIPTION:	This function is the equivalent of a main() function
 *						under standard C.  It is called by the Emulator to begin
 *						execution of this application.
 *
 * PARAMETERS:		cmd - command specifying how to launch the application.
 *						cmdPBP - parameter block for the command.
 *						launchFlags - flags used to configure the launch.			
 *
 * RETURNED:		Any applicable error code.
 *
 ***********************************************************************/
DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
{
	
Word error;		// P4. error starting the app
short err;	
	
	// P4. This app makes use of PalmOS 2.0 features.  It will crash if
	// run on an earlier version of PalmOS.  Detect and warn if this happens,
	// then exit.
	error = RomVersionCompatible (version20, launchFlags);
	if (error)
		return error;

	
	// Check for a normal launch.
	if (cmd == sysAppLaunchCmdNormalLaunch)
		{
		// Set up initial form.
		err = StartApplication();
		if(err) return err;
		
		// Start up the event loop.
		EventLoop();
		
		StopApplication();
		}

	return 0;
}

void TrainXXrandomwords(int NumberOfWords)
{
	FieldPtr	FldPtrOut,FldPtrResult;
	FormPtr	frm;
	int i,j=0;
	char		Buf[120];//, Buf2[15];	//HSK
	char 		*txtptr;//,*txtptr2;
	char outsign=0;
	Boolean View;//,Randomize;	
	txtptr=Buf;
//	txtptr2=Buf2;

			frm = FrmGetFormPtr(HSKTemplateMainForm);
			FldPtrOut = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, HSKTemplateMainEdOutTextField))));			
			FldPtrResult = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, HSKTemplateMainEdResultField))));

			View = (CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainViewRealTimeCheckbox)))!=0);
			
			for(i=0;i<(NumberOfWords*6);i+=6)
				{
				for(j=0;j<5;j++)
				{
					outsign=RandN(42)+48;
					if(outsign>57 && outsign<65) outsign+=7;
					txtptr[i+j]=outsign;
				}
				txtptr[i+5]=' ';
				}
				
			for(i=0;i<(NumberOfWords*6);i++)
				{
				FldDelete(FldPtrResult, 0, FldGetTextLength(FldPtrResult));
				if (View) if (txtptr != NULL) FldInsert(FldPtrResult, txtptr,i+1);//FldInsert(FldPtr, Buf, StrLen(Buf));				
				Morsewhat(txtptr[i]);
	            if(EvtSysEventAvail(true)) i=(NumberOfWords*6);
				}			

				FldDelete(FldPtrResult, 0, FldGetTextLength(FldPtrResult));
				if (txtptr != NULL)FldInsert(FldPtrResult, txtptr,(NumberOfWords*6));					

}

void LearnAlphabetXX(int from,  int count)
{
	FieldPtr	FldPtrOut,FldPtrResult;
	FormPtr	frm;
	int i,j=0;
	char		Buf[12], Buf2[12];	//HSK
	char 		*txtptr,*txtptr2;
	char outsign=0;
	Boolean View,Randomize;	
	txtptr=Buf;
	txtptr2=Buf2;


			frm = FrmGetFormPtr(HSKTemplateMainForm);
			FldPtrOut = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, HSKTemplateMainEdOutTextField))));			
			FldPtrResult = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, HSKTemplateMainEdResultField))));
			View = (CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainViewRealTimeCheckbox)))!=0);
			Randomize = (CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainRandomizeCheckbox)))!=0);			

			j=0;
			for(j=0;j<12;j++)		//denne nuller ut begge bufrene... fikk flyt i strlen() nr jeg ikke gjorde det..
			{
			Buf2[j]='\0';
			Buf[j]='\0';
			}

			for (i=0;i<count;i++)
				{
				txtptr2[i]=i+from;
				}

			if (Randomize) txtptr2=RandomizeAlphabet(txtptr2);
			
			j=0;
			
			for(i=0;i<(count*2);i+=2)
				{
				txtptr[i]=txtptr2[j];
				txtptr[i+1]=' ';
				j++;
				}

			for(i=0;i<(count*2);i++)
				{
				FldDelete(FldPtrResult, 0, FldGetTextLength(FldPtrResult));
				if (View) if (txtptr != NULL) FldInsert(FldPtrResult, txtptr,i+1);//FldInsert(FldPtr, Buf, StrLen(Buf));				
				Morsewhat(txtptr[i]);
			    if(EvtSysEventAvail(true)) i=(count*2);
				}			

				FldDelete(FldPtrResult, 0, FldGetTextLength(FldPtrResult));
				if (txtptr != NULL)FldInsert(FldPtrResult, txtptr,count*2);
				
}

char* RandomizeAlphabet(char *instring)
{
UInt i,j,k,p=0;
p=StrLen(instring);
for (j=0;j<p-1;j++)		//minus 1 fordi den gikk til og med strlen..skulle g til strlen-1
	{
	i=RandN(p);
	k=instring[j];
	instring[j]=instring[i];
	instring[i]=k;
	}

return instring;
}

void MorseRandomAbbreviation(void)
{
	FieldPtr	FldPtrOut,FldPtrResult;
	FormPtr	frm;
	int i,randomabbr=0;
	char 		*txtptr;
	Boolean View;	

	char	ABBR1[]		="QSO ";
	char	ABBR2[]		="QSL ";
	char	ABBR3[]		="QTH ";
	char 	ABBR4[]		="CQ";
	char	ABBR5[]		="CUAGN";
	char	ABBR6[]		="B4";
	char	ABBR7[]		="RX";
	char	ABBR8[]		="TX";	
	char	ABBR9[]		="XTAL";	
	char	ABBR10[]	="XPECT";		
	char	ABBR11[]	="ABT";	
	char	ABBR12[]	="AC";	
	char	ABBR13[]	="ADR";	
	char	ABBR14[]	="AF";	
	char	ABBR15[]	="AGN";	
	char	ABBR16[]	="ANS";	
	char	ABBR17[]	="ANT";	
	char	ABBR18[]	="BCI";	
	char	ABBR19[]	="BD";
	char	ABBR20[]	="BFO";	
	char	ABBR21[]	="BK";
	char	ABBR22[]	="BUG";
	char	ABBR23[]	="BURO";
	char	ABBR24[]	="C";
	char	ABBR25[]	="CONDS";
	char	ABBR26[]	="CPY";
	char	ABBR27[]	="CRD";
	char	ABBR28[]	="CU";
	char	ABBR29[]	="CUL";
	char	ABBR30[]	="CW";
	char	ABBR31[]	="DC";
	char	ABBR32[]	="DNT";
	char	ABBR33[]	="DR";
	char	ABBR34[]	="DX";
	char	ABBR35[]	="DWN";
	char	ABBR36[]	="ES";
	char	ABBR37[]	="FB";
	char	ABBR38[]	="FER";
	char	ABBR39[]	="FM";
	char	ABBR40[]	="FRQ";
	char	ABBR41[]	="GA";
	char	ABBR42[]	="GB";
	char	ABBR43[]	="GE";
	char	ABBR44[]	="GL";
	char	ABBR45[]	="GLD";
	char	ABBR46[]	="GM";
	char	ABBR47[]	="GN";
	char	ABBR48[]	="GP";
	char	ABBR49[]	="GUD";
	char	ABBR50[]	="GV";
	char	ABBR51[]	="HAM";
	char	ABBR52[]	="HI";
	char	ABBR53[]	="HPE";
	char	ABBR54[]	="HQ";
	char	ABBR55[]	="HR";
	char	ABBR56[]	="HRD";
	char	ABBR57[]	="HW";
	char	ABBR58[]	="INFO";
	char	ABBR59[]	="LOG";
	char	ABBR60[]	="MIKE";
	char	ABBR61[]	="MNI";
	char	ABBR62[]	="MOD";
	char	ABBR63[]	="MSG";
	char	ABBR64[]	="NIL";
	char	ABBR65[]	="NR";
	char	ABBR66[]	="NW";
	char	ABBR67[]	="OB";
	char	ABBR68[]	="OK";
	char	ABBR69[]	="OM";
	char	ABBR70[]	="OPR";
	char	ABBR71[]	="PA";
	char	ABBR72[]	="PSE";
	char	ABBR73[]	="PWR";
	char	ABBR74[]	="R";
	char	ABBR75[]	="RCV";
	char	ABBR76[]	="RF";
	char	ABBR77[]	="RIG";
	char	ABBR78[]	="RPRT";
	char	ABBR79[]	="RPT";
	char	ABBR80[]	="SKED";
	char	ABBR81[]	="SN";
	char	ABBR82[]	="SRI";
	char	ABBR83[]	="SSB";
	char	ABBR84[]	="STN";
	char	ABBR85[]	="TEST";
	char	ABBR86[]	="TFC";
	char	ABBR87[]	="TKS";
	char	ABBR88[]	="TNX";
	char	ABBR89[]	="TU";
	char	ABBR90[]	="TVI";
	char	ABBR91[]	="U";
	char	ABBR92[]	="UP";
	char	ABBR93[]	="UR";
	char	ABBR94[]	="UFB";
	char	ABBR95[]	="UNLIS";
	char	ABBR96[]	="UTC";
	char	ABBR97[]	="VFO";
	char	ABBR98[]	="VOX";
	char	ABBR99[]	="VY";
	char	ABBR100[]	="W";
	char	ABBR101[]	="WKD";
	char	ABBR102[]	="WPM";
	char	ABBR103[]	="WRD";
	char	ABBR104[]	="WUD";
	char	ABBR105[]	="WX";
	char	ABBR106[]	="XMAS";
	char	ABBR107[]	="XYL";
	char	ABBR108[]	="YL";
	char	ABBR109[]	="Z";
	char	ABBR110[]	="73";
	char	ABBR111[]	="88";
	
	char	ABBR112[]	="QRG";
	char	ABBR113[]	="QRH";
	char	ABBR114[]	="QRK";
	char	ABBR115[]	="QRL";
	char	ABBR116[]	="QRM";
	char	ABBR117[]	="QRN";
	char	ABBR118[]	="QRP";
	char	ABBR119[]	="QRO";
	char	ABBR120[]	="QRS";
	char	ABBR121[]	="QRT";
	char	ABBR122[]	="QRU";
	char	ABBR123[]	="QRV";
	char	ABBR124[]	="QRX";
	char	ABBR125[]	="QRZ";
	char	ABBR126[]	="QSA";
	char	ABBR127[]	="QSB";
	char	ABBR128[]	="QSK";
	char	ABBR129[]	="QSP";
	char	ABBR130[]	="QSY";
	char	ABBR131[]	="QTR";
	char	ABBR132[]	="QST";
	
	char	ABBR133[]	="HSK";

//	char	ABBR19[]	="";	

	randomabbr=RandN(133);
	
	switch(randomabbr)
	{
		case 0:txtptr=ABBR1;
			break;
		case 1:txtptr=ABBR2;
			break;
		case 2:txtptr=ABBR3;
			break;
		case 3:txtptr=ABBR4;
			break;
		case 4:txtptr=ABBR5;
			break;
		case 5:txtptr=ABBR6;
			break;
		case 6:txtptr=ABBR7;
			break;
		case 7:txtptr=ABBR8;
			break;
		case 8:txtptr=ABBR9;
			break;
		case 9:txtptr=ABBR10;
			break;
		case 10:txtptr=ABBR11;
			break;
		case 11:txtptr=ABBR12;
			break;
		case 12:txtptr=ABBR13;
			break;
		case 13:txtptr=ABBR14;
			break;
		case 14:txtptr=ABBR15;
			break;
		case 15:txtptr=ABBR16;
			break;
		case 16:txtptr=ABBR17;
			break;
		case 17:txtptr=ABBR18;
			break;
		case 18:txtptr=ABBR19;
			break;
		case 19:txtptr=ABBR20;
			break;
		case 20:txtptr=ABBR21;
			break;
		case 21:txtptr=ABBR22;
			break;
		case 22:txtptr=ABBR23;
			break;
		case 23:txtptr=ABBR24;
			break;


		case 24:txtptr=ABBR25;
			break;
		case 25:txtptr=ABBR26;
			break;
		case 26:txtptr=ABBR27;
			break;
		case 27:txtptr=ABBR28;
			break;
		case 28:txtptr=ABBR29;
			break;
		case 29:txtptr=ABBR30;
			break;
		case 30:txtptr=ABBR31;
			break;
		case 31:txtptr=ABBR32;
			break;
		case 32:txtptr=ABBR33;
			break;
		case 33:txtptr=ABBR34;
			break;
		case 34:txtptr=ABBR35;
			break;
		case 35:txtptr=ABBR36;
			break;
		case 36:txtptr=ABBR37;
			break;
		case 37:txtptr=ABBR38;
			break;
		case 38:txtptr=ABBR39;
			break;
		case 39:txtptr=ABBR40;
			break;
		case 40:txtptr=ABBR41;
			break;
		case 41:txtptr=ABBR42;
			break;
		case 42:txtptr=ABBR43;
			break;
		case 43:txtptr=ABBR44;
			break;
		case 44:txtptr=ABBR45;
			break;
		case 45:txtptr=ABBR46;
			break;
		case 46:txtptr=ABBR47;
			break;
		case 47:txtptr=ABBR48;
			break;
		case 48:txtptr=ABBR49;
			break;
		case 49:txtptr=ABBR50;
			break;
		case 50:txtptr=ABBR51;
			break;
		case 51:txtptr=ABBR52;
			break;
		case 52:txtptr=ABBR53;
			break;
		case 53:txtptr=ABBR54;
			break;
		case 54:txtptr=ABBR55;
			break;
		case 55:txtptr=ABBR56;
			break;
		case 56:txtptr=ABBR57;
			break;
		case 57:txtptr=ABBR58;
			break;
		case 58:txtptr=ABBR59;
			break;
		case 59:txtptr=ABBR60;
			break;
		case 60:txtptr=ABBR61;
			break;
		case 61:txtptr=ABBR62;
			break;
		case 62:txtptr=ABBR63;
			break;
		case 63:txtptr=ABBR64;
			break;
		case 64:txtptr=ABBR65;
			break;
		case 65:txtptr=ABBR66;
			break;
		case 66:txtptr=ABBR67;
			break;
		case 67:txtptr=ABBR68;
			break;
		case 68:txtptr=ABBR69;
			break;
		case 69:txtptr=ABBR70;
			break;

		case 70:txtptr=ABBR71;
			break;
		case 71:txtptr=ABBR72;
			break;
		case 72:txtptr=ABBR73;
			break;
		case 73:txtptr=ABBR74;
			break;
		case 74:txtptr=ABBR75;
			break;
		case 75:txtptr=ABBR76;
			break;
		case 76:txtptr=ABBR77;
			break;
		case 77:txtptr=ABBR78;
			break;
		case 78:txtptr=ABBR79;
			break;
		case 79:txtptr=ABBR80;
			break;

		case 80:txtptr=ABBR81;
			break;
		case 81:txtptr=ABBR82;
			break;
		case 82:txtptr=ABBR83;
			break;
		case 83:txtptr=ABBR84;
			break;
		case 84:txtptr=ABBR85;
			break;
		case 85:txtptr=ABBR86;
			break;
		case 86:txtptr=ABBR87;
			break;
		case 87:txtptr=ABBR88;
			break;
		case 88:txtptr=ABBR89;
			break;
		case 89:txtptr=ABBR90;
			break;

		case 90:txtptr=ABBR91;
			break;
		case 91:txtptr=ABBR92;
			break;
		case 92:txtptr=ABBR93;
			break;
		case 93:txtptr=ABBR94;
			break;
		case 94:txtptr=ABBR95;
			break;
		case 95:txtptr=ABBR96;
			break;
		case 96:txtptr=ABBR97;
			break;
		case 97:txtptr=ABBR98;
			break;
		case 98:txtptr=ABBR99;
			break;
		case 99:txtptr=ABBR100;
			break;

		case 100:txtptr=ABBR101;
			break;
		case 101:txtptr=ABBR102;
			break;
		case 102:txtptr=ABBR103;
			break;
		case 103:txtptr=ABBR104;
			break;
		case 104:txtptr=ABBR105;
			break;
		case 105:txtptr=ABBR106;
			break;
		case 106:txtptr=ABBR107;
			break;
		case 107:txtptr=ABBR108;
			break;
		case 108:txtptr=ABBR109;
			break;
		case 109:txtptr=ABBR110;
			break;

		case 110:txtptr=ABBR111;
			break;
		case 111:txtptr=ABBR112;
			break;
		case 112:txtptr=ABBR113;
			break;
		case 113:txtptr=ABBR114;
			break;
		case 114:txtptr=ABBR115;
			break;
		case 115:txtptr=ABBR116;
			break;
		case 116:txtptr=ABBR117;
			break;
		case 117:txtptr=ABBR118;
			break;
		case 118:txtptr=ABBR119;
			break;
		case 119:txtptr=ABBR120;
			break;

		case 120:txtptr=ABBR121;
			break;
		case 121:txtptr=ABBR122;
			break;
		case 122:txtptr=ABBR123;
			break;
		case 123:txtptr=ABBR124;
			break;
		case 124:txtptr=ABBR125;
			break;
		case 125:txtptr=ABBR126;
			break;
		case 126:txtptr=ABBR127;
			break;
		case 127:txtptr=ABBR128;
			break;
		case 128:txtptr=ABBR129;
			break;
		case 129:txtptr=ABBR130;
			break;

		case 130:txtptr=ABBR131;
			break;
		case 131:txtptr=ABBR132;
			break;
		case 132:txtptr=ABBR133;
			break;

	}

			frm = FrmGetFormPtr(HSKTemplateMainForm);
			FldPtrOut = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, HSKTemplateMainEdOutTextField))));			
			FldPtrResult = (FieldPtr)(FrmGetObjectPtr(frm, (FrmGetObjectIndex(frm, HSKTemplateMainEdResultField))));
			View = (CtlGetValue(FrmGetObjectPtr(frm, FrmGetObjectIndex(frm, HSKTemplateMainViewRealTimeCheckbox)))!=0);

			for(i=0;i<StrLen(txtptr);i++)
				{
				FldDelete(FldPtrResult, 0, FldGetTextLength(FldPtrResult));
				if (View) if (txtptr != NULL) FldInsert(FldPtrResult, txtptr,i+1);//FldInsert(FldPtr, Buf, StrLen(Buf));				
				Morsewhat(txtptr[i]);
			    if(EvtSysEventAvail(true)) i=StrLen(txtptr)-1; //aybryter om en event er i i ken..
				}			

				FldDelete(FldPtrResult, 0, FldGetTextLength(FldPtrResult));
				if (txtptr != NULL)FldInsert(FldPtrResult, txtptr,StrLen(txtptr));
				
}

/*----------------------------------*/
/* openDatabase                     */
/*----------------------------------*/
/* Does what it says on the label ! */
/*----------------------------------*/
static Boolean OpenDataBase()
{
	MorseManDB = DmOpenDatabaseByTypeCreator(MorseManDBType,MorseManAppID,dmModeReadWrite);

	if(!MorseManDB)
	{
		if(DmCreateDatabase(0,MorseManDBName,MorseManAppID,MorseManDBType,false)) return 1;
		MorseManDB = DmOpenDatabaseByTypeCreator(MorseManDBType,MorseManAppID,dmModeReadWrite);
	}

	return 0;
}

/*----------------------------------*/
/*Add record to database			*/
/*----------------------------------*/
static void addRecord(Char FileName[20])
{
	dbRecord Rec;
	UInt currRec;
	VoidHand recHandle;
	Ptr		recPtr;
	CharPtr		txtptr;
	Handle	bufferHandle;
	FormPtr	MainFrm;
	FieldPtr	FldPtrOutText;
	UInt count = DmNumRecords(MorseManDB);

	MainFrm = FrmGetFormPtr(HSKTemplateMainForm);
	FldPtrOutText	= (FieldPtr)(FrmGetObjectPtr(MainFrm, (FrmGetObjectIndex(MainFrm, HSKTemplateMainEdOutTextField))));	

	bufferHandle = MemHandleNew(sizeof(Rec.TextFile));
	txtptr = MemHandleLock(bufferHandle);			//NB totalhavari p CharPtr Buffer om ikke denne var med nr den ble strre enn 26..
	
	txtptr=FldGetTextPtr (FldPtrOutText);

	MemSet(Rec.TextFile,sizeof(Rec.TextFile),0);
	MemSet(Rec.Name,sizeof(Rec.Name),0);

	if (txtptr!=NULL) StrCopy(Rec.TextFile,txtptr);	
	StrCopy(Rec.Name,FileName);
		
	currRec=0;
	recHandle = DmNewRecord(MorseManDB,&currRec,sizeof(Rec));


	recPtr = MemHandleLock(recHandle);
	DmWrite(recPtr,0,&Rec,sizeof(Rec));
	MemPtrUnlock(recPtr);
	DmReleaseRecord(MorseManDB,currRec,true);

MemHandleUnlock(bufferHandle);		
MemHandleFree(bufferHandle);
}


/*-------------------------------------------------------*/
/* getRecord                                             */
/*-------------------------------------------------------*/
/* Returns the record retrieved from the specified index */
/*-------------------------------------------------------*/
static dbRecord getRecord(UInt recNum)
{
	VoidHand recHandle;
	Ptr recPtr;
	dbRecord rec;
	UInt count = DmNumRecords(MorseManDB);	
	
	if (count!=NULL)
	{
	recHandle = DmQueryRecord(MorseManDB,recNum);
	recPtr = MemHandleLock(recHandle);
	MemMove(&rec,recPtr,sizeof(rec));
	MemPtrUnlock(recPtr);
	}
	else
		{
		MemSet(rec.TextFile,sizeof(rec.TextFile),0);
		MemSet(rec.Name,sizeof(rec.Name),0);
		}

return(rec);
}





void LoadProgram(int ListItem)
{
	dbRecord Rec;
	FormPtr	MainFrm;
	FieldPtr	FldPtrOutText;

	MemSet(Rec.TextFile,sizeof(Rec.TextFile),0);
	MemSet(Rec.Name,sizeof(Rec.Name),0);

	Rec = getRecord(ListItem);

//herr...	

	MainFrm = FrmGetFormPtr(HSKTemplateMainForm);
	FldPtrOutText	= (FieldPtr)(FrmGetObjectPtr(MainFrm, (FrmGetObjectIndex(MainFrm, HSKTemplateMainEdOutTextField))));	
	FldDelete(FldPtrOutText, 0, FldGetTextLength(FldPtrOutText));
	FldInsert(FldPtrOutText, Rec.TextFile,StrLen(Rec.TextFile));		

}



void SaveLoadProgram(void)
{
	FormPtr frmSaveLoad;
	FieldPtr FldPtrSaveAs;
	int 	button,ListItem=0;
	CharPtr	txtptr;
	Char 	FileName[20];
	Handle tempBufferHandle;
	
		
	tempBufferHandle = MemHandleNew(60);
	txtptr = MemHandleLock(tempBufferHandle);			//NB totalhavari p CharPtr Buffer om ikke denne var med nr den ble strre enn 26..

			frmSaveLoad = FrmInitForm(SaveDialogForm);
	 	    FldPtrSaveAs = (FieldPtr)(FrmGetObjectPtr(frmSaveLoad, (FrmGetObjectIndex(frmSaveLoad,SaveDialogSaveAsField))));

			updateRecordList(frmSaveLoad,SaveDialogFileList);

			button=FrmDoDialog(frmSaveLoad);
			
			ListItem=LstGetSelection(FrmGetObjectPtr(frmSaveLoad,FrmGetObjectIndex(frmSaveLoad,SaveDialogFileList)));
			
			txtptr=FldGetTextPtr (FldPtrSaveAs);	

			if (txtptr!=NULL) StrCopy(FileName,txtptr);
				else StrCopy(FileName,"NoName.mrs");			

 			FrmDeleteForm(frmSaveLoad);
	
		MemHandleUnlock(tempBufferHandle);
		MemHandleFree(tempBufferHandle);


	switch(button)
		{
		
		case SaveDialogSaveButton:
			addRecord(FileName);			
			break;

		case SaveDialogLoadButton:
			LoadProgram(ListItem);			
			break;

		case SaveDialogDeleteButton:
			if(ListItem!=-1)DmRemoveRecord(MorseManDB,ListItem);
			break;
		
		}

}

/*---------------------------------------------------------*/
/* updateRecordList                                        */
/*---------------------------------------------------------*/
/* Dynamically updates the specified list from the records */
/* in the database.                                        */
/*---------------------------------------------------------*/
static void updateRecordList(FormPtr form,int fieldID)
{
	UInt i;
	UInt count = DmNumRecords(MorseManDB);
	char **listChoices = (char **) MemPtrNew(count * (sizeof(char *)));
	dbRecord checkingRecord;
	Ptr field;


	for (i = 0; i < count; i++)
	{
		checkingRecord = getRecord(i);
		listChoices[i] = makeListItem(checkingRecord);
	}

	field = FrmGetObjectPtr(form, FrmGetObjectIndex(form, fieldID));
	LstSetListChoices((ListPtr) field, listChoices, count);
}



/*------------------------------------------------------------*/
/* makeListItem                                               */
/*------------------------------------------------------------*/
/* Returns a CharPtr to a new item to be added to a list.     */
/*------------------------------------------------------------*/
CharPtr makeListItem(dbRecord rec)
{
	CharPtr listItem;
	Char temp[20];


	listItem=MemPtrNew(35);
	MemSet(listItem,35,0);
	MemSet(temp,20,0);

	StrCat(listItem,rec.Name); 

	return listItem;
}







