/****************************************************************************
	Aplikace Klavesnice pro zadavani textovych povelu zarizeni a ovladani
	vzdaleneho Pocitace.

	TODO:	v pripade pouziti masky by bylo vhodne vlozit misto masky nejaky
			defaultni text, aby to nemusel uzivatel cele vyplnovat.

*****************************************************************************/
#include "stdafx.h"
#include "Applications.h"
#include "GLCD.h"
#include "OS.h"
#include "GRAPHICS.h"
#include "stdlib.h"




KEYBOARD_BUFFER KeyboardBuffer;														//Textovy buffer

/****************************************************************************
	Definice fontu pro aplikaci

*****************************************************************************/
FONT keyboardScreenFont = {RGB_GREEN,FONT_SMALL,RGB_LIGHT_BLUE};					
FONT keyboardObjectFont = {RGB_CYAN,FONT_SMALL,RGB_DARK_GRAY};
FONT keyboardSpecialObjectFont = {RGB_RED,FONT_SMALL,RGB_DARK_GRAY};
FONT keyboardTextBoxFont = {RGB_GREEN, FONT_SMALL, RGB_BLACK};

TScreen keyboardScreen;																//Definice okna aplikace
TScreenObject keyboardScreenObjects[KEYBOARD_OBJECTS_COUNT];						//definice objektu aplikace

TApplicationInternal KeyboardInternal;												//Definice ridiciho objektu aplikace

/****************************************************************************
	Definice parametru objektu aplikace

*****************************************************************************/
TScreenObjectParams keyboardLetterParams = {KEY_SIZE, KEY_SIZE, &keyboardObjectFont};
TScreenObjectParams keyboardSpecialParams = {KEY_SPECIAL_SIZE, KEY_SIZE, &keyboardSpecialObjectFont};
TScreenObjectParams keyboardTextBoxParams = {KEYBOARD_TEXT_BOX_WIDTH, KEYBOARD_TEXT_BOX_HEIGHT, &keyboardTextBoxFont};



KEYBOARD_TYPES keyboardType = KEYBOARD_NORMAL;			//aktualni vybrane rozlozeni pismen


/****************************************************************************
	Definice rozlozeni klavesnice

*****************************************************************************/
char layoutUpperCapital[LAYOUT_UPPER_COUNT+1] = "QWERTZUIOP";
char layoutMiddleCapital[LAYOUT_MIDDLE_COUNT+1] = "ASDFGHJKL";
char layoutLowerCapital[LAYOUT_LOWER_COUNT+1] = {BACKSPACE,'Y','X','C','V','B','N','M',LEFT,RIGHT};

char layoutUpperNormal[LAYOUT_UPPER_COUNT+1] = "qwertzuiop";
char layoutMiddleNormal[LAYOUT_MIDDLE_COUNT+1] = "asdfghjkl";
char layoutLowerNormal[LAYOUT_LOWER_COUNT+1] = {BACKSPACE,'y','x','c','v','b','n','m',LEFT,RIGHT};

char layoutUpperNumeric[LAYOUT_UPPER_COUNT+1] = "0123456789";
char layoutMiddleNumeric[LAYOUT_MIDDLE_COUNT+1] = "ìšèøžýáíé";
char layoutLowerNumeric[LAYOUT_LOWER_COUNT+1] = {BACKSPACE,'\"','@','.',':','?',',','!',LEFT,RIGHT};

char layoutUpperSymbolic[LAYOUT_UPPER_COUNT+1] = "#$%^&*()[]";
char layoutMiddleSymbolic[LAYOUT_MIDDLE_COUNT+1] = "<>\\/-+=|\'";
char layoutLowerSymbolic[LAYOUT_LOWER_COUNT+1] = {BACKSPACE,'{','}',';','~',0,0,'/',LEFT,RIGHT};

char layoutUpperNumericOnly[LAYOUT_UPPER_COUNT+1] = "0123456789";
char layoutMiddleNumericOnly[LAYOUT_MIDDLE_COUNT+1] = {0,0,0,0,0,0,0,0,0};
char layoutLowerNumericOnly[LAYOUT_LOWER_COUNT+1] = {0,0,0,'.',0,0,0,0,LEFT,RIGHT};

//Zde jsou ulozeny ukazatele na aktualni rozlozeni klavesnice
char *layoutUpper = layoutUpperNormal;	
char *layoutMiddle = layoutMiddleNormal;
char *layoutLower = layoutLowerNormal; 

char layoutSpecial[LAYOUT_SPECIAL_COUNT];						//Specialni objekty


/****************************************************************************
	Funkce pro nastaveni typu rozlozeni klavesnice

	Do ukazatelu layoutXXXX jsou ulozeny ukazatele na prislusny radek definice
	klavesnicoveho rozlozeni

	Vstup:
		type:		typ klavesnice

	Vystup:
		neni

*****************************************************************************/
void setKeyboardType(KEYBOARD_TYPES type)
{
	switch(type)
	{
	case KEYBOARD_NORMAL:
		layoutUpper = layoutUpperNormal;
		layoutMiddle = layoutMiddleNormal;
		layoutLower = layoutLowerNormal; 
		keyboardType = KEYBOARD_NORMAL;
		DebugOut("Keyboard type switch to Normal.\n");
		break;
	case KEYBOARD_NUMERIC:
		layoutUpper = layoutUpperNumeric;
		layoutMiddle = layoutMiddleNumeric;
		layoutLower = layoutLowerNumeric; 
		keyboardType = KEYBOARD_NUMERIC;
		DebugOut("Keyboard type switch to Numeric.\n");
		break;
	case KEYBOARD_CAPITAL:
		layoutUpper = layoutUpperCapital;
		layoutMiddle = layoutMiddleCapital;
		layoutLower = layoutLowerCapital; 
		keyboardType = KEYBOARD_CAPITAL;
		DebugOut("Keyboard type switch to Capital.\n");
		break;
	case KEYBOARD_SYMBOLIC:
		layoutUpper = layoutUpperSymbolic;
		layoutMiddle = layoutMiddleSymbolic;
		layoutLower = layoutLowerSymbolic; 
		keyboardType = KEYBOARD_SYMBOLIC;
		DebugOut("Keyboard type switch to Symbolic.\n");
		break;
	case KEYBOARD_NUMERIC_ONLY:
		layoutUpper = layoutUpperNumericOnly;
		layoutMiddle = layoutMiddleNumericOnly;
		layoutLower = layoutLowerNumericOnly; 
		keyboardType = KEYBOARD_NUMERIC_ONLY;
		DebugOut("Keyboard type switch to Numeric only.\n");
		break;
	default:
		DebugOut("Invalid keyboard type requested.\n");
		break;
	}
	keyboardInitialize();

}


/****************************************************************************
	Funkce pro kresleni tvaru tlacitka

	Vstup: 
		obj:			instance objektu
		msg:			parametr volani

	Vystup
		neni

*****************************************************************************/
void DrawKeyboardButtonShape(TScreenObject* obj, OBJECT_MESSAGE msg)
{
#ifdef FIX_ALL_WARNINGS
	msg;
#endif
	TRect buttonRect = {obj->x, obj->y, obj->x+obj->params->width, obj->y+obj->params->height};		//Definice obdelniku
	LCD_fcrect(&buttonRect,obj->params->font->bg_color,(unsigned char)obj->params->height>>2);		//vykresleni pozadi
	LCD_crect(&buttonRect,RGB_WHITE,(unsigned char)obj->params->height>>2);							//vykresleni ramecku
	LCD_Set_Font(obj->params->font);																//Nastaveni fontu
	LCD_Set_ROI(&buttonRect);																		//Nastaveni ROI
}

/****************************************************************************
	Funkce pro kresleni text boxu

	Vstup: 
		obj:			instance objektu
		msg:		parametr volani

	Vystup
		neni

*****************************************************************************/
void DrawKeyboardTextBox(TScreenObject * obj, OBJECT_MESSAGE msg)
{
	if (msg == MSG_COMPLETE)						//Pokud je pozadavek o prekresleni celeho objektu, kreslime pozadi
		DrawTextBoxShape(obj,MSG_NONE);
	LCD_Goto_XY(obj->x+5, obj->y+8);				//Prechod do horniho rohu objektu
	KeyboardBuffer.Last = LCD_cprintf(KeyboardBuffer.First,obj->caption,KeyboardBuffer.Counter)+KeyboardBuffer.First;	//vypis jedne "obrazovky" text boxu, pokud je text dlouhy
}


/****************************************************************************
	Funkce pro kresleni datovych tlacitek

	Vstup: 
		obj:			instance objektu
		msg:			parametr volani

	Vystup
		neni

*****************************************************************************/
void DrawKeyboardSpecialButton(TScreenObject* obj, OBJECT_MESSAGE msg)
{
#ifdef FIX_ALL_WARNINGS
	msg;
#endif
	DrawKeyboardButtonShape(obj,MSG_NONE);					//Vykreslei tvaru tlacitka
	LCD_Goto_XY(obj->x+9, obj->y+8);						//Presun na pozici tisku textu
	
	//Podle ID objektu rozhodni o textu objektu
	switch(obj->id)
	{
	case CANCEL:
		LCD_printf(STR_CANCEL);								//Cancel					
		break;
	case OK:
		LCD_printf(STR_OK);									//OK
		break;
	case SHIFT:
		if (keyboardType == KEYBOARD_NORMAL)				//Prepnuti klavesnice
			LCD_printf(STR_SHIFT_CAPITAL);
		else if (keyboardType == KEYBOARD_CAPITAL)
			LCD_printf(STR_SHIFT_NUMERIC);
		else if (keyboardType == KEYBOARD_NUMERIC)
			LCD_printf(STR_SHIFT_SYMBOLS);
		else
			LCD_printf(STR_SHIFT_NORMAL);
		break;
	case SPACE:
		LCD_printf(STR_SPACE);								//Mezernik
		break;
	case ENTER:
		LCD_printf(STR_ENTER);								//Enter
		break;
	}
}


/****************************************************************************
	Vykresleni tlacitka s pismenem

	Vstup: 
		obj:			instance objektu
		msg:			parametr volani

	Vystup
		neni

*****************************************************************************/
void DrawKeyboardButton(TScreenObject * obj, OBJECT_MESSAGE msg)
{
#ifdef FIX_ALL_WARNINGS
	msg;
#endif
	DrawKeyboardButtonShape(obj,MSG_NONE);			//Vykresleni tvaru
	LCD_Goto_XY(obj->x+9, obj->y+8);				//Presun na pozici
	LCD_putchar(obj->id);							//Tisk znaku dle ID
}

/****************************************************************************
	Metoda je ponechana pro info jak vypada funkce pro rozliseni indexu 
	objektu z pozice. Neni pouzivana, praktictejsi je brute force vyhledani
	objektu v seznamu objektu

	Vstup: 
		pos:		pozice kliknuti

	Vystup
		neni

*****************************************************************************/
static int translateClickPosition(POSITION* pos)
{
	int tmp = (pos->y-ROW_TOP_UPPER);
	int index = 0;
	int tmpToSwitch = 0;
	if (tmp < 0)
		return UNDF;
	tmpToSwitch = integerDiv(tmp,KEY_DISTANCE);							//Vypocet rady s klavesami
	if (tmp%KEY_DISTANCE > KEY_SIZE)									//Zjisteni jestli neni kliknuto do mezery
	{
		DebugOut("Click between rows..\n");
		return UNDF;
	}
	switch (tmpToSwitch)												//Pro prislusnou radu hledame dotcene tlacitko
	{
	case ROW_UPPER:
		CalculateIndex(ROW_LEFT_UPPER, KEY_DISTANCE, KEY_SIZE);			//Vypocet pozice tlacitka
		if (index > LAYOUT_UPPER_COUNT)
			return UNDF;
		return (char)index;												//vysledek
		break;
	case ROW_MIDDLE:
		CalculateIndex(ROW_LEFT_MIDDLE, KEY_DISTANCE, KEY_SIZE);
		if (index > LAYOUT_MIDDLE_COUNT)
			return UNDF;
		return (char)LAYOUT_UPPER_COUNT+index;
		break;
	case ROW_LOWER:
		CalculateIndex(ROW_LEFT_LOWER, KEY_DISTANCE, KEY_SIZE);
		if (index > LAYOUT_LOWER_COUNT)
			return UNDF;
		return (char)LAYOUT_MIDDLE_COUNT+LAYOUT_UPPER_COUNT+index;
		break;
	case ROW_SPECIAL:
		CalculateIndex(ROW_LEFT_SPECIAL, KEY_SPECIAL_DISTANCE, KEY_SPECIAL_SIZE);
		if (index > LAYOUT_SPECIAL_COUNT)
			return UNDF;
		return (char)LAYOUT_MIDDLE_COUNT+LAYOUT_UPPER_COUNT+LAYOUT_LOWER_COUNT+index;
		break;
	default:
		return UNDF;
	}
}


/****************************************************************************
	Funkce reakce klaves na stisknuti

	Vstup: 
		obj:			instance objektu
		msg:			parametr volani

	Vystup
		neni

*****************************************************************************/
void buttonCallback(TScreenObject *obj, OBJECT_MESSAGE msg)
{

	switch (msg)
	{
	case MSG_CLICK:
		switch (obj->id)
		{
		case SHIFT:
			KeyboardInternal.State = KEYBOARD_SWITCH;							//Prepnuti klavesnic
			break;
		case OK:
			KeyboardBuffer.TextBuffer[KeyboardBuffer.TopCounter-1]=0;			//Ukonceni pomoci OK -> zakoncime retezec v bufferu
			DebugOut("Keyboard finishing: OK.\n");
			DebugOut("DATA: \"");
			DebugOut((char*)&KeyboardBuffer.TextBuffer[0]);						
			DebugOut("\"\n");
			KeyboardInternal.State = KEYBOARD_STOP;								//Ukoncime klavesnici
			
			break;
		case CANCEL:
			DebugOut("Keyboard finishing: CANCEL.\n");
			clearBuffer(KeyboardBuffer.TextBuffer, KEYBOARD_TEXT_BUFFER_LENGTH);	//pokud je ukonceno pomoci cancel, vymazeme data
			KeyboardInternal.State = KEYBOARD_STOP;									//Koncime take
			break;
		case 0:
			break;
		default:
			//POkud se jedna o jine tlacitko, predame udalost text boxu
			KeyboardInternal.Screen->objects[KEYBOARD_TB].object_callback(&KeyboardInternal.Screen->objects[KEYBOARD_TB],(OBJECT_MESSAGE)obj->id);
			break;
		}
		break;

	default:
		
		break;
	}
}

/****************************************************************************
	Funkce vraci info o spravnem zformatovani dat v text boxu (resp. info o tom,
	jestli mohla zmenav boxu vytvorit pozadavek na preformatovani)

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
char checkVisibility(void)
{
	char out = 0;
	if (KeyboardBuffer.Counter < KeyboardBuffer.First)
	{	
		KeyboardBuffer.First = KeyboardBuffer.FirstBuffer[--KeyboardBuffer.Index];
		KeyboardBuffer.Last = KeyboardBuffer.LastBuffer[KeyboardBuffer.Index]+KeyboardBuffer.First;
		out = 1;
	}

	if (KeyboardBuffer.Counter > KeyboardBuffer.Last)
	{	
		KeyboardBuffer.LastBuffer[KeyboardBuffer.Index] = KeyboardBuffer.Last-KeyboardBuffer.First;
		KeyboardBuffer.FirstBuffer[KeyboardBuffer.Index++] = KeyboardBuffer.First;
		KeyboardBuffer.First = KeyboardBuffer.Last;
		out = 2;
	}
	return out;
}


/****************************************************************************
	Funkce pro kresleni datovych tlacitek

	Vstup: 
		obj:			instance objektu
		msg:			parametr volani

	Vystup
		neni

*****************************************************************************/
void textBoxCallback(TScreenObject * obj, OBJECT_MESSAGE msg)
{
	char visCheck = 0;
	
	switch (msg)								//Nejprve je proveden prepovcet ID klavesy na odpovidajici znak
	{
	case SPACE:
		msg = (OBJECT_MESSAGE)' ';				//mezera
		break;
	case ENTER:
		msg = (OBJECT_MESSAGE)'\r';				//novy radek
		break;
	default:
		break;
	}
	switch((unsigned char)msg)									//nyni probehne zpracovani prislusnych klaves
	{
	case LEFT:
		if (KeyboardBuffer.Counter == 0)						//pokud je pozice kurzoru 0, nic nedelej
			break;
		KeyboardBuffer.Counter--;								//jinak jej posun zpet
		while(obj->caption[KeyboardBuffer.Counter] == '\n')		//POkud jsme narazili na vice odradkovani, preskocime je
			KeyboardBuffer.Counter--;
		break;
	case RIGHT:													//posun doprava
		if (KeyboardBuffer.Counter == KeyboardBuffer.TopCounter-(KeyboardBuffer.Mask == 0?1:1))		//jej, ted neni cas tohle opravovat
			break;
		KeyboardBuffer.Counter++;								//Posun doprava
		while(obj->caption[KeyboardBuffer.Counter] == '\n')		//Preskoceni odradkovani
			KeyboardBuffer.Counter++;
		//visCheck += checkVisibility();
		break;
	case BACKSPACE:
		if (KeyboardBuffer.TopCounter > 1 && KeyboardBuffer.Counter <= KeyboardBuffer.TopCounter-1)		//mazani
			strDelChar(obj->caption,KeyboardBuffer.Counter-1);
		else
			break;
		//if (--KeyboardBuffer.TopCounter < KeyboardBuffer.Counter+1)
		--KeyboardBuffer.TopCounter;
		if (  0 < KeyboardBuffer.Counter)
			KeyboardBuffer.Counter--;
		visCheck = 1;
		break;
	case MSG_COMPLETE:
		visCheck = 1;
		break;
	default:
		if (KeyboardBuffer.TopCounter < KeyboardBuffer.Length)										//Nalezite chovani s maskou a bez masky...
		{
			strPutChar(obj->caption,(unsigned char)msg,KeyboardBuffer.Counter++);
			KeyboardBuffer.TopCounter++;
		}else if (KeyboardBuffer.Mask !=0)
		{
			KeyboardBuffer.Counter = addNumToMaskedText(KeyboardBuffer.TextBuffer,KeyboardBuffer.Mask,(unsigned char)msg,KeyboardBuffer.Counter);
		}

		break;
	}
	checkVisibility();
	obj->draw(obj,MSG_COMPLETE);


}


/****************************************************************************
	Inicializace aplikace

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
RESULT keyboardInitialize(void)
{
	short i = 0;
	keyboardScreen.Init(LAYOUT_UPPER_COUNT+LAYOUT_MIDDLE_COUNT+LAYOUT_LOWER_COUNT+LAYOUT_SPECIAL_COUNT + 1,keyboardScreenObjects,&keyboardScreenFont);		//Inicializace obrazovky
	KeyboardInternal.Init(KEYBOARD,KEYBOARD_XA, KEYBOARD_YA, KEYBOARD_XC, KEYBOARD_YC,&keyboardScreen,0,YES);												//Inicializace ridici struktury
	if (KeyboardInternal.Screen == 0)
		return FAILED;
	/****************************************************************************
		Inicializace objektu
		===>Zde je s vyhodou vyuzita geometricka pravidelnost rozlozeni objektu,
			neni proto potreba inicializovat kazdy objekt zvlastnim prikazem.
	
	*****************************************************************************/
	KeyboardInternal.Screen->objects[KEYBOARD_TB].Init(			20,
																25,
																KEYBOARD_TEXT_BOX,
																KEYBOARD_TB, 
																&KeyboardBuffer.TextBuffer[0],
																OBJECT_ENABLED,
																&keyboardTextBoxParams,
																&textBoxCallback,
																&DrawKeyboardTextBox);	
	for (i = 0; i < LAYOUT_UPPER_COUNT; i++)
	{
		KeyboardInternal.Screen->objects[i].Init(						i*KEY_DISTANCE+ROW_LEFT_UPPER,
																ROW_TOP_UPPER,
																KEYBOARD_BUTTON,
																layoutUpper[i],
																0,
																OBJECT_ENABLED,
																&keyboardLetterParams,
																&buttonCallback, 
																&DrawKeyboardButton);
	}

	for (i = 0; i < LAYOUT_MIDDLE_COUNT; i++)
	{

		KeyboardInternal.Screen->objects[i+LAYOUT_UPPER_COUNT].Init(	i*KEY_DISTANCE+ROW_LEFT_MIDDLE,
																ROW_TOP_MIDDLE,
																KEYBOARD_BUTTON,
																layoutMiddle[i],
																0,
																OBJECT_ENABLED,
																&keyboardLetterParams,
																&buttonCallback, 
																&DrawKeyboardButton);
	}

	for (i = 0; i < LAYOUT_LOWER_COUNT; i++)
	{
		KeyboardInternal.Screen->objects[i+LAYOUT_UPPER_COUNT+LAYOUT_MIDDLE_COUNT].Init(
																i*KEY_DISTANCE+ROW_LEFT_LOWER,
																ROW_TOP_LOWER,
																KEYBOARD_BUTTON,
																layoutLower[i],
																0,
																OBJECT_ENABLED,
																&keyboardLetterParams,
																&buttonCallback, 
																&DrawKeyboardButton);
	}

	KeyboardInternal.Screen->objects[OK-1+LAYOUT_UPPER_COUNT+LAYOUT_MIDDLE_COUNT+LAYOUT_LOWER_COUNT].Init(
																(OK-1)*KEY_SPECIAL_DISTANCE+ROW_LEFT_SPECIAL,
																ROW_TOP_SPECIAL,
																KEYBOARD_SPECIAL_BUTTON,
																(SPECIAL_KEYS)(OK),
																0,
																OBJECT_ENABLED,
																&PARAMS_BTN_OK,
																&buttonCallback, 
																&DrawKeyboardSpecialButton);

	KeyboardInternal.Screen->objects[SPACE-1+LAYOUT_UPPER_COUNT+LAYOUT_MIDDLE_COUNT+LAYOUT_LOWER_COUNT].Init(
																(SPACE-1)*KEY_SPECIAL_DISTANCE+ROW_LEFT_SPECIAL,
																ROW_TOP_SPECIAL,
																KEYBOARD_SPECIAL_BUTTON,
																(SPECIAL_KEYS)(SPACE),
																0,
																OBJECT_ENABLED,
																&keyboardSpecialParams,
																&buttonCallback, 
																&DrawKeyboardSpecialButton);

	KeyboardInternal.Screen->objects[SHIFT-1+LAYOUT_UPPER_COUNT+LAYOUT_MIDDLE_COUNT+LAYOUT_LOWER_COUNT].Init(
																(SHIFT-1)*KEY_SPECIAL_DISTANCE+ROW_LEFT_SPECIAL,
																ROW_TOP_SPECIAL,
																KEYBOARD_SPECIAL_BUTTON,
																(SPECIAL_KEYS)(SHIFT),
																0,
																OBJECT_ENABLED,
																&keyboardSpecialParams,
																&buttonCallback, 
																&DrawKeyboardSpecialButton);

	KeyboardInternal.Screen->objects[ENTER-1+LAYOUT_UPPER_COUNT+LAYOUT_MIDDLE_COUNT+LAYOUT_LOWER_COUNT].Init
																((ENTER-1)*KEY_SPECIAL_DISTANCE+ROW_LEFT_SPECIAL,
																ROW_TOP_SPECIAL,
																KEYBOARD_SPECIAL_BUTTON,
																(SPECIAL_KEYS)(ENTER),
																0,
																OBJECT_ENABLED,
																&keyboardSpecialParams,
																&buttonCallback, 
																&DrawKeyboardSpecialButton);

	KeyboardInternal.Screen->objects[CANCEL-1+LAYOUT_UPPER_COUNT+LAYOUT_MIDDLE_COUNT+LAYOUT_LOWER_COUNT].Init(
																(CANCEL-1)*KEY_SPECIAL_DISTANCE+ROW_LEFT_SPECIAL,
																ROW_TOP_SPECIAL,
																KEYBOARD_SPECIAL_BUTTON,
																(SPECIAL_KEYS)(CANCEL),
																0,
																OBJECT_ENABLED,
																&PARAMS_BTN_CANCEL,
																&buttonCallback, 
																&DrawKeyboardSpecialButton);

	return PASSED;
}


/****************************************************************************
	Postovni schranka aplikace

	Vstup: 
		msg:		zprava aplikaci

	Vystup
		neni

*****************************************************************************/
RESULT KBMsgBox(MESSAGE* msg)
{
	POSITION *tmpPosition = 0;
	switch (msg->msg)
	{
	case RUN:
		DebugOut("Keyboard RUN command received.\n");
		if (KeyboardInternal.State == KEYBOARD_READY)						//Pokud je aplikace zinicializovana
		{
			KeyboardInternal.State = KEYBOARD_RESTART;						//provedeme start
			return PASSED;
		}
		break;
	case INIT:
		DebugOut("Keyboard INIT command received.\n");
		if (KeyboardInternal.State == KEYBOARD_NOT_INITIALIZED)				//POkud neni aplikace zinicializovana
		{
			KeyboardInternal.State = KEYBOARD_INITIALIZE;					//Inicializujeme
			return PASSED;
		}
	case GET_STATE:
		//DebugOut("Keyboard GET_STATE command received.\n");
		return (RESULT)KeyboardInternal.State;								//Vraci stav aplikace
		break;
	case SET_MASK:
		KeyboardBuffer.Mask = (unsigned char*)msg->data;					//Nastavi klavesnici masku - nastaveni trva do ukonceni aplikace
		return PASSED;
		break;
	case SET_NUMERIC_MODE:
		setKeyboardType(KEYBOARD_NUMERIC_ONLY);								//Nastaveni numerickeho rezimu
		return PASSED;
		break;
	case APP_CLICK:
		KeyboardInternal.ClickPosition.isFresh = YES;						//Prijeti kliknuti od OS
		tmpPosition = (POSITION*)msg->data;									//kopie informaci
		KeyboardInternal.ClickPosition.x = tmpPosition->x;
		KeyboardInternal.ClickPosition.y = tmpPosition->y;
		return PASSED;
		break;
	default:
		break;
		
	}
	return FAILED;
}



/****************************************************************************
	Ridici stavovy automat aplikace

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
void AppKeyboard(void)
{
	
	switch (KeyboardInternal.State)
	{
	case KEYBOARD_NOT_INITIALIZED:
		break;
	case KEYBOARD_INITIALIZE:	
		if (keyboardInitialize()==FAILED)										//Inicializace
		{
			DebugOut("Keyboard init failed!\n");
			KeyboardInternal.State = KEYBOARD_ERROR;							//Pokud se nezdarilo, chyba
			break;
		}
		DebugOut("Keyboard initialized successfully.\n");
		
		KeyboardInternal.State = KEYBOARD_READY;								//Jinak prejdi do dalsiho stavu
		break;	
	case KEYBOARD_RESTART:
		DebugOut("Keyboard was reset.\n");
		clearBuffer(KeyboardBuffer.TextBuffer,KEYBOARD_TEXT_BUFFER_LENGTH);		//Proved reset bufferu
		if (KeyboardBuffer.Mask != 0)											//pokud je nastavena maska
		{
			strcopy(KeyboardBuffer.Mask,KeyboardBuffer.TextBuffer);				//Vloz masku do bufferu
			KeyboardBuffer.TopCounter = get_length(KeyboardBuffer.Mask);		//Pracuj s maskou jako sablonou pro text
			KeyboardBuffer.Length = KeyboardBuffer.TopCounter;
			int i = 0;
			while(KeyboardBuffer.TextBuffer[i]!=NUMBER_ALIAS)	
				i++;
			KeyboardBuffer.Counter = i;
		}
		else
		{
			KeyboardBuffer.TextBuffer[0] = ' ';									//JInak prichystej buffer pro zadani textu
			KeyboardBuffer.TopCounter = 1;
			KeyboardBuffer.Length = KEYBOARD_TEXT_BUFFER_LENGTH;
			KeyboardBuffer.Counter = 0;
		}

		
		KeyboardInternal.Screen->fullScreen = TRUE;								//nastaveni celoobrazovkoveho rezimu
		KeyboardInternal.Startup();												//Akce nezbytne pro spusteni
		KeyboardInternal.State = KEYBOARD_DRAW;									//Prechod do dalsiho stavu
		break;
	case KEYBOARD_DRAW:
		DebugOut("Keyboard drawing.\n");
		KeyboardInternal.Screen->Draw();										//Vykresleni
		KeyboardInternal.Screen->objects[KEYBOARD_TB].state = OBJECT_ENABLED;	//Povoleni text boxu
		KeyboardInternal.State = KEYBOARD_ACTIVE;								//Prechod do aktivniho stavu
		break;
	case KEYBOARD_ACTIVE:
		KeyboardInternal.ProceedClick();										//Zpracovani kliknuti
		KeyboardInternal.ProceedCursor();										//Zpracovani kurzoru
                break;
	case KEYBOARD_READY:
		break;
	case KEYBOARD_SWITCH:
		
		switch(keyboardType)													//Prepnuti typu klavesnice
		{
		case KEYBOARD_NORMAL:
			setKeyboardType(KEYBOARD_CAPITAL);
			break;
		case KEYBOARD_CAPITAL:
			setKeyboardType(KEYBOARD_NUMERIC);
			break;
		case KEYBOARD_NUMERIC:
			setKeyboardType(KEYBOARD_SYMBOLIC);
			break;
		case KEYBOARD_SYMBOLIC:
			setKeyboardType(KEYBOARD_NORMAL);
			break;
		case KEYBOARD_NUMERIC_ONLY:
			DebugOut("Cannot change type to different than NUMERIC_ONLY");
			break;
		default:
			setKeyboardType(KEYBOARD_NORMAL);
			DebugOut("Keyboard type switch to default state.\n");
			break;
		}
		
		KeyboardInternal.Screen->objects[KEYBOARD_TB].state = OBJECT_DISABLED;	//V pripade prepnuti neprekresluj text-box
		KeyboardInternal.Screen->fullScreen = FALSE;
		KeyboardInternal.State = KEYBOARD_DRAW;									//Kresli
		break;
	case KEYBOARD_STOP:
		KeyboardInternal.Stop();												//Ukonci aplikaci
		setKeyboardType(KEYBOARD_NORMAL);										//resetuj typ klavesnice
		KeyboardBuffer.Mask = 0;												//vypni maskovani
		break;
	case KEYBOARD_ERROR:
		break;
	default:
		KeyboardInternal.State = KEYBOARD_ERROR;
		KeyboardInternal.UnregisterArea();
		DebugOut("Keyboard unknown state, falling to error.\n");
		break;
	};



}