/******************************************************************************
 *
 * Copyright (c) 2006 SAMSUNG Co. Ltd,
 * All rights reserved.
 *
 * File: menu.c
 *
 * Description: Simple menu system for boot loader
 *
 *****************************************************************************/
#include <windows.h>
#include <bsp.h>
#include "loader.h"
#include "menu.h"



extern BOOLEAN         g_bUSBDownload;
extern BOOL            g_bDownloadImage;
extern BOOL           bIsLogoBin;

extern DWORD           g_ImageType;

static UINT32 bstrtoul(PUCHAR pStr, UCHAR nBase)
{
    UCHAR nPos=0;
    BYTE c;
    ULONG nVal = 0;
    UCHAR nCnt=0;
    ULONG n=0;

    // fulllibc doesn't implement isctype or iswctype, which are needed by
    // strtoul, rather than including coredll code, here's our own simple strtoul.

    if (pStr == NULL)
        return(0);

    for (nPos=0 ; nPos < strlen(pStr) ; nPos++)
    {
        c = tolower(*(pStr + strlen(pStr) - 1 - nPos));
        if (c >= '0' && c <= '9')
            c -= '0';
        else if (c >= 'a' && c <= 'f')
        {
            c -= 'a';
            c  = (0xa + c);
        }

        for (nCnt = 0, n = 1 ; nCnt < nPos ; nCnt++)
        {
            n *= nBase;
        }
        nVal += (n * c);
    }

    return(nVal);
}

#define MAX_NUMBER_SIZE		11
UINT32 OEMReadNumber(int hexInput)
{
	char selection, strNum[MAX_NUMBER_SIZE];
	int i = 0, maxDigit = MAX_NUMBER_SIZE - 1;

	memset(strNum, 0, sizeof(strNum));
	if (hexInput)
		maxDigit = 8;

	while(1)
	{
		selection = OEMReadDebugByte();
		if (selection == 10 || selection == 13 || i >= maxDigit)
		{
			EdbgOutputDebugString("\r\n");
			break;
		}
		if (i && selection == 8)	// Backspace
		{
			EdbgOutputDebugString("%c %c", selection, selection);
			strNum[i--] = 0;
			continue;
		}
		if (hexInput)
		{
			if (selection >= 'a')
				selection -= ('a' - 'A');
			if (selection < '0' || (selection > '9' && selection < 'A') || selection > 'F')
				continue;
		} else if (selection > '9' || selection < '0')
			continue;

		EdbgOutputDebugString("%c", selection);
		strNum[i++] = selection;
	}

	if (hexInput)
		return bstrtoul(strNum, 16);
	return bstrtoul(strNum, 10);
}

UINT32 OEMReadNumberMax(int hexInput, UINT32 min, UINT32 max)
{
	unsigned long result;
	result = OEMReadNumber(hexInput);
	if (result > max)
		return max;
	if (result < min)
		return min;
	return result;
}

int DisplayMenu(char *pMenuTitle, PFN_TITLE_HANDLER pfnTitleHandler, MENU_ITEM *pMenuList, void *menuArg)
{
	int i;
	char selection;
	int nMenuItem;

	while(1)
	{
		//EdbgOutputDebugString("\r\n\r\n\r\n");
		EdbgOutputDebugString("\r\n***************************************************************\r\n");
		if (pfnTitleHandler)
			pfnTitleHandler(menuArg);
		else
			EdbgOutputDebugString(pMenuTitle);
		EdbgOutputDebugString("\r\n***************************************************************\r\n");

		nMenuItem=0;

		/* Display the menu list */
		for(i=0; pMenuList[i].cMenuKey!='\0' ; i++)
		{
			if (pMenuList[i].pfnTitleHandler) 
			{
				EdbgOutputDebugString("%c) ", pMenuList[i].cMenuKey);
				(*pMenuList[i].pfnTitleHandler)(pMenuList[i].menuArg);
				EdbgOutputDebugString("\r\n");
			} 
			else
				EdbgOutputDebugString("%c) %s\r\n", pMenuList[i].cMenuKey, pMenuList[i].szMenuName);
			
			nMenuItem++;
		}
		EdbgOutputDebugString("X: Exit to previous menu\r\n");
		EdbgOutputDebugString("---------------------------------\r\nEnter Choice >>  ");

		while(1)
		{
			selection = OEMReadDebugByte();
			for(i = 0; i < nMenuItem; i++)
			{
				if (selection=='x' || selection=='X')
				{
					EdbgOutputDebugString("%c\r\n\r\n", selection);
					return 0;
				}
				
                if (selection=='u' || selection=='U')
				{
					EdbgOutputDebugString("%c\r\n\r\n", selection);

					g_bDownloadImage = TRUE;
        			g_bUSBDownload = TRUE;
					//CheckUSBDownload();
					return 0;//返回值并不重要
				}
				

                if (selection=='l' || selection=='L')
				{
					EdbgOutputDebugString("%c\r\n\r\n", selection);

					g_bDownloadImage = TRUE;
        			g_bUSBDownload = TRUE;
					g_ImageType = IMAGE_TYPE_LOGO;
				//	bIsLogoBin = TRUE;

					return 0;
				}

				
				if (selection >= 'a' && selection <= 'z')
					selection -= 32;//小写转大写
				
				if (selection == pMenuList[i].cMenuKey)
				{
					EdbgOutputDebugString("%c\r\n\r\n", selection);
					if (pMenuList[i].pSubMenu)
					{
						if (pMenuList[i].pfnPreFunction) 
							(*pMenuList[i].pfnPreFunction)(pMenuList[i].menuArg);
						DisplayMenu(pMenuList[i].szMenuName, pMenuList[i].pfnTitleHandler, pMenuList[i].pSubMenu, pMenuList[i].menuArg);
						if (pMenuList[i].pfnPostFunction) 
							(*pMenuList[i].pfnPostFunction)(pMenuList[i].menuArg);
					} 
					else if (pMenuList[i].pfnHandler) 
					{
						int result;
						result = (*pMenuList[i].pfnHandler)(pMenuList[i].menuArg);
						if (result)
							return result;
					}
					else
						EdbgOutputDebugString("Handler is not defined yet.\r\n");
					break;
				}
			}

			if(nMenuItem != i) 
				break;	// Start the function again.
		}
	}
}

//081127 by wChang
void Hex2Str(DWORD hex, unsigned char *str, unsigned short strSize)
{
	unsigned char nibble;
	unsigned char c;
	int i;

	for(i=0 ; i<strSize ; i++)
	{
		nibble = (unsigned char)(hex >>(((strSize-1)-i)*4))&0x0f;

		switch(nibble)
		{
			case 0:
				c = '0';
				break;
			case 1:
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
			case 9:
				c = '1'+(nibble-1);
				break;
			case 10:
			case 11:
			case 12:
			case 13:
			case 14:
			case 15:
				c = 'A'+(nibble-10);
				break;
		}
		str[i]=c;
	}
}

void Dec2Str(DWORD dec, unsigned char *str, unsigned short strSize)
{
	int i, div=10;
	DWORD value;
	unsigned char quota;

	for (i=1;i<=strSize;i++)
	{
		value = (dec%div)/(div/10);		
		quota = (unsigned char)value;
		str[strSize-i] = '0'+quota;		
		div *= 10;
	}
}


/*
 #include <windows.h>
#include "loader.h"

#include "menu.h"

extern int OEMReadDebugByte();
static char GetLowercase(char ch);

void DisplayMenu(char *pMenuTitle, MENU_ITEM *pMenuList)
{
	int i;
	char selection;
	int nMenuItem;

	while(1)
	{
		EdbgOutputDebugString("***************\r\n");
		EdbgOutputDebugString(pMenuTitle);
		EdbgOutputDebugString("\r\n***************\r\n");

		nMenuItem=0;

//		EdbgOutputDebugString("%X ", pMenuList);
//		EdbgOutputDebugString("%s", pMenuList[0].szMenuName);
		
		for(i=0; pMenuList[i].cMenuKey!='\0' ; i++)
		{
			EdbgOutputDebugString("%c: %s\r\n", pMenuList[i].cMenuKey, pMenuList[i].szMenuName);
			nMenuItem++;
		}
		EdbgOutputDebugString("X: Exit to previous menu\r\n");
		EdbgOutputDebugString("*************** \r\n>>  ");

		while(1)
		{
			selection = OEMReadDebugByte();
			for( i=0; i<nMenuItem ; i++ )
			{
				if(selection=='x'||selection=='X') return;
				
				if(GetLowercase(selection)==GetLowercase( pMenuList[i].cMenuKey))
				{
					EdbgOutputDebugString("%c\r\n", selection);
					if( NULL==pMenuList[i].pSubMenu )
					{
						if(NULL!=pMenuList[i].pfnHandler)
						{
							if(NULL!=pMenuList[i].pfnPreFunction) (*pMenuList[i].pfnPreFunction)();
							(*pMenuList[i].pfnHandler)();
							//EdbgOutputDebugString("Return from Handler.\r\n");
						}
						else
						{
							EdbgOutputDebugString("Handler is not defined yet.\r\n");
						}
						
					}
					else
					{
						if(NULL!=pMenuList[i].pfnPreFunction) (*pMenuList[i].pfnPreFunction)();
						DisplayMenu(pMenuList[i].szMenuName, pMenuList[i].pSubMenu);
						//EdbgOutputDebugString("Return from sub-menu.\r\n");
					}
					break;
				}
			}

			if(i==nMenuItem) 
			{
			//if(selection!='\0')	EdbgOutputDebugString(">> Unknown Command %c\r\n", selection);
			}
			else 
				break;	// Start the function again.
		}
	}
}

char GetLowercase(char ch)
{
	if(ch>='a' && ch<='z')
	{
		return (ch-32);
	}
	else
		return ch;
}
*/
