#include "app.h"
#include "lng.h" // language file
#include "unzip.h" // распаковщик zip-архивов by om2804

static DRAWING_BUFFER_T bufd = {NULL, 176, 220}; // Буфер для рисования
static FILEINFO  	*file_list; // Память для списка. Инфа о файлах.
static LINE 		*menu; // Память для списка-меню.
static SETTING_T 	setting; // Настройки
static FILE_T 		file; // Файлы
static EDIT 		*edit;
static ITEM 		item; //Пункты
static COLOR		Color; // Цветовая палитра
static STATES_T		state, next_state, file_op_state;
static WCHAR        cur_folder[FILEURI_MAX_LEN]=L"/";  // текущая папка
static UINT8        y=0, item_distance=0, max_items=0;
static UINT16       status=0,  page_null=0, count_select=0;

UIS_DIALOG_T        dialog; // Диалог
ldrElf				elf;

/* Название приложения. Длина строки именно такая и никакая иначе */
const char app_name[APP_NAME_LEN+1] = ELF_NAME; 

/* Обработчики событий для каждого state-а */

/* Обработчики событий для MC_STATE_ANY (используется в любом state) */
static EVENT_HANDLER_ENTRY_T any_state_handlers[] =
{  
  //{ STATE_HANDLERS_RESERVED,             appShow },
	{ EV_PM_API_EXIT,					destroyApp },
    { STATE_HANDLERS_END,           		  NULL },
};

static EVENT_HANDLER_ENTRY_T main_state_handlers[] =
{
    { EV_INK_KEY_PRESS,				  ListKeypress },
	{ EV_GAIN_FOCUS,					 	 Paint },		
    { STATE_HANDLERS_END,                     NULL },
};

static EVENT_HANDLER_ENTRY_T edit_state_handlers[] =
{
    { EV_DATA,                         	  EditData },
    { EV_DONE,                       	    EditOk },
	{ EV_CANCEL,                  	    EditCancel },
    { STATE_HANDLERS_END,         	          NULL },
};

static EVENT_HANDLER_ENTRY_T notice_state_handlers[] =
{
	{ EV_INK_KEY_PRESS,			  	NoticeKeypress },
    { STATE_HANDLERS_END,					  NULL },
};

static EVENT_HANDLER_ENTRY_T viewer_state_handlers[] =
{
	{ EV_INK_KEY_PRESS,			  	ViewerKeypress },
    { STATE_HANDLERS_END,					  NULL },
};

static EVENT_HANDLER_ENTRY_T menu_state_handlers[] =
{
    { EV_INK_KEY_PRESS,				  MenuKeypress },
    { STATE_HANDLERS_END,					  NULL },
};

/* Таблица соответствий обработчиков, состояний и функций входа-выхода из состояния.
   Порядок состояний такой же, как в enum-e */
static const STATE_HANDLERS_ENTRY_T state_handling_table[] =
{
    { MC_STATE_ANY,               // State
      NULL,                       // Обработчик входа в state
      NULL,                       // Обработчик выхода из state
      any_state_handlers          // Список обработчиков событий
    },
    { MC_STATE_MAIN,
      MainStateEnter,
      NULL,
      main_state_handlers
    },
	{ MC_STATE_EDIT,
      EditStateEnter,
      StateExit,
      edit_state_handlers
	},
	{ MC_STATE_NOTICE,
      NoticeStateEnter,
      NULL,
      notice_state_handlers
	},
	{ MC_STATE_VIEWER,
      ViewerStateEnter,
      NULL,
      viewer_state_handlers
    },
	{ MC_STATE_EDIT_PROPS,
	  EditPropsEnter,
	  StateExit,
	  edit_props_state_handlers
	},
	{ MC_STATE_MENU,
      MenuStateEnter,
      NULL,
      menu_state_handlers
	}
	
};

static const APP_STATE_NAME_TABLE_T state_name_table[] =
{
	{MC_STATE_ANY,			"ANY"},
	{MC_STATE_MAIN,			"MAIN"},
	{MC_STATE_EDIT,			"EDIT"},
	{MC_STATE_NOTICE,		"NOTICE"},
	{MC_STATE_VIEWER,		"VIEWER"},
	{MC_STATE_EDIT_PROPS,	"EDIT_PROPS"},
	{MC_STATE_MENU,			"MENU"},
	{MC_STATE_MAX,			 NULL}
};
ldrElf* _start( WCHAR *uri, WCHAR *params )
{
	UINT32 			reserve = ldrRequestEventBase();
    int    			i = 0, j = 0;
	char   			buf[128];	
	char   			run_event[8];
	char   			BufR[128];

	dbg("\n==============================================");
	dbgf("%s  Copyright 2009-2010 R.U.S.H.A.N. Build date: %s %s", app_name, __DATE__, __TIME__);
	dbg("_start");

	i = u_strlen( uri ) - 1;
	while ( i >= 0 && uri[i] != L'/' ) i--;
	i++;
	elf.dir = malloc( i * sizeof(WCHAR) );
	if ( elf.dir )
		u_strncpy( elf.dir, uri, i );
			
	u_mkpath(file.cfg, elf.dir, L"mc.cfg", 0);
	
	
	LoadSkin();
		
	// база ивентов
	reserve = ldrRequestEventBase();
	// заполняем структуру эльфа
	elf.name = (char *)app_name;
	elf.app = NULL;
	
	// инитим таблицы ивентов
	for ( i=0; i<APP_STATE_MAX; i++ )
		reserve = ldrInitEventHandlersTbl((EVENT_HANDLER_ENTRY_T *)state_handling_table[i].htable, reserve);
		
	ReadSetting();
	
	if(setting.ev_code) 
		elf.evbase = setting.ev_code;
	else
		elf.evbase = reserve ++;
	
	/* Регистрируем приложение */
	 status = APP_Register( &elf.evbase,            // На какое событие должно запускаться приложение
                           1,                       // Кол-во событий, на которое должно запускаться приложение
                           state_handling_table,    // Таблица состояний
                           MC_STATE_MAX,            // Количество состояний
                           (void*)startApp );   // Функция, вызываемая при запуске
						   
	
	if (!setting.ev_code)
    ldrSendEvent( elf.evbase );	// Start now

    return &elf;
}


/* Функция вызываемая при старте приложения */
UINT32 startApp( EVENT_STACK_T *ev_st,  REG_ID_T reg_id,  UINT32 param2 )
{
    APP_MC_T     *app = NULL;
	dbg("startApp");
	
	// Если приложение уже запужено то разворачиваем его
	if( AFW_InquireRoutingStackByRegId( reg_id ) == RESULT_OK ) {
		appShow( elf.app );
		return RESULT_FAIL;
	}
	
    /* Инициализация для фоновых приложений */
    app = (APP_MC_T*)APP_InitAppData( (void *)APP_HandleEvent, // Обработчик для приложений с GUI
                                              sizeof(APP_MC_T), // Размер структуры приложения
                                              reg_id,
                                              0, 1,
                                              1,
											  1, 1, 0 );										  
	app->window = 1;
	
	AHG_Init();
	DL_FsMkDir(setting.temp_dir, 0);
	
    status = APP_Start( ev_st,
                        &app->apt,
                        MC_STATE_MAIN, // Начальное состояние
                        state_handling_table,
                        destroyApp,
                        app_name,
                        state_name_table );
						
	// Теперь приложение может обрабатывать события
	if ( status == RESULT_OK ) {
		elf.app = &papp->apt;
		cprint(ELF_NAME ":\x82 Started\n");
	}
	else
	{
		cprint(ELF_NAME ": Start Failed!\n");
		APP_HandleFailedAppStart( ev_st, &papp->apt, 0 );
		return ldrUnloadElf(); 
	}
	
    return RESULT_OK;
}



/* Функция выхода из приложения */
UINT32 destroyApp( EVENT_STACK_T *ev_st,  APPLICATION_T *app )
{
	UINT32			status;
	EVENT_T *		event = AFW_GetEv(ev_st);
	
	dbgf("destroyApp: Enter, event = 0x%p, code = 0x%X", event, event->code);
		
	if ( event != NULL ) {
		// это нажатие красной кнопки
		appHide(app);
		return RESULT_OK;
	}
	
	AHG_Done();	// Завершаем работу драйвера ATI
		
	if ( state_handling_table[app->state].exit_fn != NULL && app->state != APP_STATE_BG )
		(state_handling_table[app->state].exit_fn)(ev_st, app, EXIT_STATE_EXIT);
		
	cprint( ELF_NAME ":\x8E Exit\n" );
	
    /* Завершаем работу приложения */
    status = APP_Exit( ev_st, app, NULL );
	
    if(!setting.ev_code) ldrUnloadElf();
   
    return status;
}

/* Обработчик входа в main state */
UINT32 MainStateEnter( EVENT_STACK_T *ev_st,  APPLICATION_T *app,  ENTER_STATE_TYPE_T type )
{

	dbg("MainStateEnter: start");
	if(type!=ENTER_STATE_ENTER) return RESULT_OK;
	
	if( !app->dialog ){
		app->dialog = UIS_CreateColorCanvas( &app->port, &bufd, true ); // создаём канвас
		if(app->dialog == NULL) return RESULT_FAIL;
	}	
	
	FindFile(cur_folder, L"*", app);
	DrawList(app);
	dbg("MainStateEnter: end");
	
    return RESULT_OK;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
UINT32 EditStateEnter( EVENT_STACK_T *ev_st,  APPLICATION_T *app,  ENTER_STATE_TYPE_T type )
{
    APP_MC_T           		*papp = (APP_MC_T*) app;
	dbg("EditStateEnter: start");
	
	if( app->dialog )
		APP_UtilUISDialogDelete( &app->dialog );
	
	switch(state)
	{
		case EDIT_FILE:
		app->dialog = UIS_CreateCharacterEditor( &app->port, viewer_content, 1, 1275, FALSE, NULL, papp->res );
		break;
		
		case RENAME:
		app->dialog = UIS_CreateCharacterEditor( &app->port, file_list[item.select].name, 1, 256, FALSE, NULL, papp->res );
		break;
		
		default:
		app->dialog = UIS_CreateCharacterEditor( &app->port, L"", 1, 1275, FALSE, NULL, papp->res );
		break;
    }
	return RESULT_OK;
}

UINT32 NoticeStateEnter( EVENT_STACK_T *ev_st,  APPLICATION_T *app,  ENTER_STATE_TYPE_T type )
{
    
	if(type!=ENTER_STATE_ENTER) return RESULT_OK;
	
	  SetBrushColor(0x000000);
	  FillRect(7,88,167,47);// тень
	  SetBrushColor(0xD6D3D6);
	  FillRect(4,85,167,47); //фон
	  SetBrushColor(0x000000);
	  DrawRect(5,86, 164, 44); //рамка
	  DrawRect(7,88, 160, 40); //
	  SetFgColor(0x000000);
	  DrawText(msg, 88-(StringWidth(msg)/2),100,false);
	  DrawText(L"[Ok] [Cancel]", 55,116,false);
	  AHG_Flush();
	  
	if( !app->dialog ){
		app->dialog = UIS_CreateColorCanvas( &app->port, &bufd, true ); // создаём канвас
		if(app->dialog == NULL) return RESULT_FAIL;
	}
    return RESULT_OK;
}

UINT32 ViewerStateEnter( EVENT_STACK_T *ev_st,  APPLICATION_T *app,  ENTER_STATE_TYPE_T type )
{
	dbg(" ViewerStateEnter: start");
	if(type!=ENTER_STATE_ENTER) return RESULT_OK;
	
	if( !app->dialog ){
		app->dialog = UIS_CreateColorCanvas( &app->port, &bufd, true ); // создаём канвас
		if(app->dialog == NULL) return RESULT_FAIL;
	}	 
	
	dbg("ViewerStateEnter: end");
    return RESULT_OK;
}

/* Обработчик входа в main state */
UINT32 EditPropsEnter( EVENT_STACK_T *ev_st,  APPLICATION_T *app,  ENTER_STATE_TYPE_T type )
{
	dbg("EditPropsEnter: start");
  
	if(type!=ENTER_STATE_ENTER) return RESULT_OK;
	  
	if( !app->dialog ) {
		app->dialog = UIS_CreateColorCanvas( &app->port, &bufd, true ); // создаём канвас
		if(app->dialog == NULL) return RESULT_FAIL;
	}	 
 
	DrawEditProps(item.edit);
	dbg("EditPropsEnter: end");
	
    return RESULT_OK;
}
UINT32 MenuStateEnter( EVENT_STACK_T *ev_st,  APPLICATION_T *app,  ENTER_STATE_TYPE_T type )
{
	dbg("MainStateEnter: start");
  
	if(type!=ENTER_STATE_ENTER) return RESULT_OK;
	if( !app->dialog ) {
		app->dialog = UIS_CreateColorCanvas( &app->port, &bufd, true ); // создаём канвас
		if(app->dialog == NULL) return RESULT_FAIL;
	}
	item.menu = 0;
	  
	dbg("MainStateEnter: end");
	
    return RESULT_OK;
}
UINT32 StateExit( EVENT_STACK_T *ev_st,  APPLICATION_T *app,  EXIT_STATE_TYPE_T type )
{
	if ( type != EXIT_STATE_EXIT ) return RESULT_OK;
	
	status = APP_UtilUISDialogDelete( &app->dialog );
	
	return RESULT_OK;
}

UINT32 ListKeypress( EVENT_STACK_T * ev_st,  APPLICATION_T *app )
{
    APP_MC_T         *papp = (APP_MC_T*)app;
	EVENT_T 		 *event = AFW_GetEv(ev_st);
	WCHAR			 src_file[256];
	UINT16			 __item;
	APP_ConsumeEv( ev_st, app );
	
     switch (event->data.key_pressed)
     {
	     case KEY_UP:
			 		if (item.select == 0)
					     item.select = papp->entries_num;
					if (item.select > 0) 
                         item.select--;
                      DrawList( app );
					  AHG_Flush();
                      break;
					  
         case KEY_DOWN:
                      if (item.select < papp->entries_num) 
                           item.select ++;
					  if (item.select == papp->entries_num)
						   item.select = 0;
						DrawList( app );
					  AHG_Flush();
					break;
					
		
		
		case KEY_SOFT_LEFT:
				break;

		//Выбрать
		case KEY_SOFT_RIGHT:
        case KEY_JOY_OK:
                SelectItemList(ev_st, app );
				break;
		//Выход
		case KEY_RED:
				destroyApp(ev_st, app );
				break;	
		//Отправить по ВТ
		case KEY_GREEN:
				if(file_list[item.select].attrib & FS_ATTR_DIRECTORY ) return RESULT_OK;
				
				if( !IsRoot() && state != ZIP_BROWSER  && item.select != 0 ) {											  
					u_mkpath(src_file, cur_folder, file_list[item.select].name, 0);
					//SendViaBT( src_file, "*/*");
				}
				break;
		//Справка
		case KEY_1:
                break;	
		//Свойства
		case KEY_2:
                break;
		//Смотреть
		case KEY_3:
                break;
		//Редактировать
		case KEY_4:
               break;  
		//Копировать		
		case KEY_5:
                break;
		//Переименовать
		case KEY_6:
                break;	
		//Создать папку	
		case KEY_7:
                break;	
		//Удалить			
		case KEY_8:
		case KEY_CLEAR:
                break;	
		
		//Копировать файл из Zip-архива
		case KEY_9:
                break;
				
		// Выделить
		case KEY_0:
				break;
				
		case KEY_STAR:
				break;
				
		case KEY_POUND:
				break;
				
		case KEY_MENU:
				break;		
	}	
	return RESULT_OK;
}

UINT32 NoticeKeypress( EVENT_STACK_T * ev_st,  APPLICATION_T *app )
{
	EVENT_T 		*event = AFW_GetEv(ev_st);
	APP_ConsumeEv( ev_st, app );
	
     switch (event->data.key_pressed)
     {	
		//Выбрать
		case KEY_5:
		case KEY_SOFT_LEFT:
		case KEY_JOY_OK:
				Action(ev_st, app );
				break;
				
			
		//Назад
		case KEY_RED:
		case KEY_SOFT_RIGHT:
				state=MAIN;
				break;
		}	
	APP_UtilChangeState( MC_STATE_MAIN, ev_st, app );
	AHG_Flush();
		
	return RESULT_OK;
}

UINT32 ViewerKeypress( EVENT_STACK_T * ev_st,  APPLICATION_T *app )
{
	EVENT_T 		*event = AFW_GetEv(ev_st);
	UINT32      	 b;
	APP_ConsumeEv( ev_st, app );
	
     switch (event->data.key_pressed)
     {
		 case KEY_2:
	     case KEY_UP:
                break;
				
		 case KEY_8:		  
         case KEY_DOWN:
				break;
				
					
		//Выбрать
		case KEY_5:
		case KEY_SOFT_RIGHT:
		case KEY_JOY_OK:
				break;
				
		case KEY_MENU:
				break;
			
		//Назад
		case KEY_RED:
		case KEY_SOFT_LEFT:
				break;
		}		
	return RESULT_OK;
}

//#####################################MAIN#####################################//

UINT32 DrawLoadingScreen(WCHAR *text)
{
    y=110-(item_distance*2+10);
	
	SetBrushColor(0x000000);
	//FillRect(0, 0, 176, 220); //фон
	FillRect(13, y+3, 153, item_distance*2+10); //тень
	SetBrushColor(Color.Background);
	FillRect(10, y, 153, item_distance*2+10);

	SetBrushColor(Color.Lines);
	DrawRect(10, y, 153, item_distance*2+10); // рамка
	DrawRect(12, y+2, 149,item_distance*2+6);

	
	SetFgColor(Color.Lines);

	DrawText(ELF_NAME" "ELF_VER, 20, y+7, false);
	DrawText(text, 20, y+item_distance+7, false);

	AHG_Flush();
    return RESULT_OK;
}


UINT32 DrawMenu(UINT16 index, APPLICATION_T *app)
{
	APP_MC_T        		*papp = (APP_MC_T*)app;
	UINT16 					i=0;
	dbg("DrawMenu: start");

    y=110-(papp->entries_num_menu*item_distance+10)/2;
	
	SetBrushColor(0x000000);
	FillRect(13, y+3, 153, item_distance*papp->entries_num_menu+10); //тень
	SetBrushColor(Color.Background);
	FillRect(10, y, 153, item_distance*papp->entries_num_menu+10);

	SetBrushColor(Color.Lines);
	DrawRect(10, y, 153, item_distance*papp->entries_num_menu+10); // рамка
	DrawRect(12, y+2, 149,item_distance*papp->entries_num_menu+6);

	
	SetFgColor(Color.Lines);
	for(i=0; i<papp->entries_num_menu; i++)
	{
		DrawText(menu[i].name, 20, (y+i*item_distance+6)+1, false);
	}
	SetBrushColor(Color.Cursor);
	DrawRect(15, y+(index*item_distance)+5, 143, item_distance);
	
	AHG_Flush();
	dbg("DrawMenu: end");
    return RESULT_OK;
}

UINT32 DrawMenu2(UINT16 index, APPLICATION_T *app)
{
	APP_MC_T        		*papp = (APP_MC_T*)app;
	dbg("DrawMenu2: start");

	
	SetBrushColor(0x000000);
	FillRect(3, 3, 102, papp->entries_num_menu*item_distance+10); // тень
	SetBrushColor(Color.Cursor);
	FillRect(0, 0, 102, papp->entries_num_menu*item_distance+10); // фон

	SetBrushColor(0xFFFFFF);
	DrawRect(0, 0, 100, (papp->entries_num_menu*item_distance+10)-2); // рамка
	DrawRect(2, 2, 96, (papp->entries_num_menu*item_distance+10)-6);
	
	FillRect(97, index*item_distance+4+1, 5, item_distance-1); // Ползунок
	
	SetBrushColor(0x000000); 
	FillRect(4, index*item_distance+4, 94, item_distance+1); // Курсор
	
	SetFgColor(0xFFFFFF);
	if(state==MAIN_MENU)
	{
		DrawTextInFullDisplay_(Language(24), 7, 0*item_distance+6); //Открыть
		DrawTextInFullDisplay_(Language(25), 7, 1*item_distance+6); //Новый файл
		DrawTextInFullDisplay_(Language(26), 7, 2*item_distance+6); //Создать ярлык
		DrawTextInFullDisplay_(Language(27), 7, 3*item_distance+6); //Закладки
		DrawTextInFullDisplay_(Language(28), 7, 4*item_distance+6); //Справка
		DrawTextInFullDisplay_(Language(29), 7, 5*item_distance+6); //О программе
		DrawTextInFullDisplay_(Language(30), 7, 6*item_distance+6); //Выход
	}else{
		DrawTextInFullDisplay_(L"1 CP-1251", 7, 0*item_distance+6); 	//CODE_ANSI
		DrawTextInFullDisplay_(L"2 UTF-16BE", 7, 1*item_distance+6); 	//CODE_UCS2_BE
		DrawTextInFullDisplay_(L"3 UTF-8", 7, 2*item_distance+6); 		//CODE_UTF8
		DrawTextInFullDisplay_(L"4 UTF-8 BOM", 7, 3*item_distance+6); 	//CODE_UTF8_BOM
	}
	AHG_Flush();
	dbg("DrawMenu2: end");
    return RESULT_OK;
}

UINT32 DrawEditProps(UINT16 index)
{
	RESOURCE_ID 			icon;
	int i=0;
	dbg("DrawEditProps");
	

	
	CanvasSetFillColor(0x00000000);
	CanvasSetBgColor(0x00000000);
    CanvasFillRect(0,0,176,220);
	
	CanvasDrawTitleBar(file_list[item.select].name);
	CanvasDrawSoftKey(0,0, false);
	CanvasDrawSoftKey(Language(20),1, false);
	CanvasDrawSoftKey(Language(21),2, false);
	

	CanvasSetFgColor(0xFFFFFF00);
	
	CanvasDrawText(L"Read only", 25, 40, 0);
	CanvasDrawText(L"Hidden", 25, 60, 0);
	CanvasDrawText(L"System", 25, 80, 0);
	CanvasDrawText(L"Archive", 25, 100, 0);
	
	for(i=0; i<4; i++){
		if(edit[i].sel == true)
		icon = 0x1200009D;
		else
		icon = 0x1200009E;
	CanvasDrawDrmImage(icon, 5, 40+(i*20),0,0); 
	}
	

    CanvasDrawRect(23, 39+(20*index), 173, 16);
	
    return RESULT_OK;
}


//Рисует просмотощик
UINT32 DrawViewer()
{
	dbg("DrawViewer: start");
	
	SetBrushColor(Color.Background);
	FillRect(0, 0, 176, 220);
	
	SetBrushColor(Color.Cursor);
	FillRect(0, 0, 176, 10); // заголовок
	SetFgColor(0x000000);
	if(state==HELP)
	DrawText(Language(0), 5, 1, 0); // текст загаловка
	else
	DrawText(viewer_title, 5, 1, 0); // текст загаловка
	
	
	// Ползунок
	SetBrushColor(0x000000);
	FillRect(173,10,3,210);
	SetBrushColor(0xAAAAAA);
	FillRect(173,10,3,0+((210/file.count_pages)*(UINT32)file.num_page));
	
	SetFgColor(Color.Lines);
	file.page_size = DrawTextInFullDisplay_(viewer_content, 6, 11);
    if (file.s_page_size==0)  file.s_page_size = file.page_size;
    file.s_page_size = (file.s_page_size + file.page_size)/2;
    file.count_pages = ((file.size-file.cur_position)/file.s_page_size) + file.num_page - 1; // кол-во страниц
    if (file.size%(file.cur_position+file.page_size) != 0) file.count_pages++;
    if (file.count_pages < file.num_page) file.count_pages = file.num_page;
	

	AHG_Flush();
	dbg("DrawViewer: end");
    return RESULT_OK;
}
//рисует список
UINT32 DrawList(APPLICATION_T *app)
{
	APP_MC_T        		*papp = (APP_MC_T*)app;
	UINT32					i=0, n=0; 
	UINT8					Y=0; 
	dbg("DrawList: start");
	
	y=11;
	SetBrushColor(Color.Background);
	FillRect(0, 0, 176, 220);

	//рисуем рамку
	SetBrushColor(Color.Lines);
	DrawRect(0, 2, 175, 186);
	DrawRect(2, 4, 171, 182);
	//Ползунок
	FillRect(172,6+((160/papp->entries_num)*item.select),3,8);
	
		// иконки
		if (item.select > max_items) {
			i = getNumFrame(item.select);
			i = (i*max_items) - (max_items-1);
		} else {
			i = 0;
		}

	DrawInfo(app);
	
	
	 for (n=i,Y=0; n < i+(max_items+1) && n < papp->entries_num && Y < papp->entries_num; n++, Y++) {

		UtilSetColForFile(n);
		DrawText(file_list[n].name, 7, y+Y*item_distance, 0);
	}
	
	dbg("DrawList: end");
    return RESULT_OK;
}

//выбранный пункт
UINT32 PaintSelectList(UINT16 index, APPLICATION_T *app)
{
	APP_MC_T         *papp = (APP_MC_T*)app;
	WCHAR  			 buf[64];
	WCHAR  			 uri[256];
	CLK_TIME_T       time;
	UINT8 			 I=0;

	dbgf("PaintSelectList: start: item.select: %d, papp->entries_num: %d", item.select, papp->entries_num);
	
	if(item.select  > papp->entries_num)
	item.select=papp->entries_num-1;
	
	if(index  > papp->entries_num)
	index=papp->entries_num-1;
	
	
	if (index > max_items) {
        I = (index % max_items)-1;
		if ((index % max_items) == 0) I=max_items-1;
    } else {
        I = index;
    }
	if( I==0 || I==max_items || I==max_items-1 || item.select >= papp->entries_num-1 ) DrawList(app); else DrawInfo(app);
	
	//рисуем рамку
	SetBrushColor(Color.Lines);
	DrawRect(0, 2, 175, 186);
	DrawRect(2, 4, 171, 182);
	//Ползунок
	FillRect(172,6+((160/papp->entries_num)*item.select),3,8);
	
	// текущий пункт
	SetFgColor(0x000000);
	SetBrushColor(Color.Cursor);
	
	if(file_list[item.select].attrib & FS_ATTR_DIRECTORY){
			u_strcpy(buf, Language(4));
		}else{
			u_strcpy(uri, cur_folder);
			u_strcat(uri, file_list[item.select].name);
			file.size=DL_FsSGetFileSize(uri,0);
			u_strcpy(buf, L"<");
			
				if(file.size >= 1024){
						u_ltou(file.size/1024, buf+u_strlen(buf));
						u_strcat(buf, L"Kb>");
					}else{
						u_ltou(file.size, buf+u_strlen(buf));
						u_strcat(buf, L"b>");
				}
	}
	DrawText(buf, 10, 185, 1 );
	
	// текущий папка
	if(StringWidth(cur_folder) >= 130){
			u_strncpy(buf, cur_folder, 3);
			u_strcat(buf, L"../");
			u_strcpy(uri, cur_folder);
			uri[u_strlen(uri)-1]=0;
			u_strcat(buf, SplitPath(uri, L"/"));
			u_strcat(buf, L"/");
			DrawText(buf, 10, 1, true );
		}else{
			DrawText(cur_folder, 10, 1, true );
	}

	
	//Часы 
	u_strcpy(buf, L"");
	DL_ClkGetTime(&time);
	u_ltou(time.hour, buf+u_strlen(buf));
	u_strcat(buf, L":");
	if(time.minute<=9)
	u_strcat(buf,L"0");
	u_ltou(time.minute, buf+u_strlen(buf));
	SetBrushColor(Color.Cursor);
	SetFgColor(0xFFE400);
	DrawText(buf, 141, 1, true);
	
	// Номер окна
	u_strcpy(buf, Language(19));
	u_ltou(papp->window, buf+u_strlen(buf));
	FillRect(124,185, StringWidth(buf)+1, 8);
	SetFgColor(0x000000);
	DrawText(buf, 125, 185, true);
	y=10;
	
	//курсор
	FillRect(6, y+I*item_distance, 164, item_distance);
	y=11;

		UtilSetColForFile(index);
		DrawText(file_list[index].name, 7, y+I*item_distance, 0);

	dbg("PaintSelectList: end");
	
    return RESULT_OK;
}

UINT32 PaintClearList(UINT16 index)
{
	UINT8 		I=0;

	dbg("PaintClearList: start");
	

	if (index > max_items) {
        I = (index % max_items)-1;
		if ((index % max_items) == 0) I=max_items-1;
    } else {
        I = index;
    }
	
	SetBrushColor(Color.Background);
	FillRect(171, 3, 4, 171);
	
	//рисуем рамку
	SetBrushColor(Color.Lines);
	DrawRect(0, 2, 175, 186);
	DrawRect(2, 4, 171, 182);
	//курсор
	y=10;
	SetBrushColor(Color.Background);
	FillRect(6, y+I*item_distance, 164, item_distance);
	y=11;

	UtilSetColForFile(index);
	DrawText(file_list[index].name, 7, y+I*item_distance, 0);
	
	dbg("PaintClearList: end");
	
    return RESULT_OK;
}

UINT32 DrawInfo(APPLICATION_T *app)
{
	APP_MC_T        *papp = (APP_MC_T*)app;
	WCHAR  			buf[256];
	UINT32          i=0, count_dirs=0,count_files=0;
	
	dbg(" - DrawInfo: start");
	
	//рисуем рамку
	SetBrushColor(Color.Lines);
	DrawRect(0, 188, 175, 30);
	DrawRect(2, 190, 171, 26);
	
	SetFgColor(Color.Lines);
		
	// Хип
	TestMem();	
	u_strcpy(buf, Language(18));
	u_ltou(free_mem, buf+u_strlen(buf));
	u_strcat(buf ,L"b");
	DrawTextInFullDisplay_(buf, 4, 205);
	

	// Всего файлов, папок
	u_strcpy(buf, Language(14));
	for(i=0; i< papp->entries_num; i++){ 
	if(file_list[i].attrib & FS_ATTR_DIRECTORY)
	count_dirs++;
	}
	if (!IsRoot())
	count_dirs = count_dirs-1;
	
	u_ltou(count_dirs, buf+u_strlen(buf));
	u_strcat(buf, Language(22));
	if (IsRoot())
	count_files = 0;
	else
	count_files = papp->entries_num-count_dirs-1;
	
	u_ltou(count_files, buf+u_strlen(buf));
	
	DrawTextInFullDisplay_(buf, 4, 195);
	
	
	dbg(" - DrawInfo: end");
	
    return RESULT_OK;
}
// возвращает номер фрейма
UINT16 getNumFrame(UINT16 index)
{
    UINT16 i;

    i = index / max_items;
    if ((index % max_items) != 0) i++;

    return i;
}

//Создает контент из файла для просмоторщика/редактора
UINT32 MakeContentFromFlie()
{
	WCHAR  			uri[272]=L"";
	char    		buf[8]="";
	UINT32  		r;
	
		if(state == HELP){
			u_mkpath(uri, elf.dir, L"mc.hlp", 0);
			file.code_type = CODE_ANSI;
		}else{
			u_mkpath(uri, cur_folder, file_list[item.select].name, 0);
		}
		udbg(" MakeContentFromFlie: uri = %s", uri);
		
		if(DL_FsFFileExist(uri)){
	    file.handle = DL_FsOpenFile(uri, FILE_READ_MODE, 0);
	    if (file.handle == FILE_INVALID){
		DL_FsCloseFile(file.handle);
		dbg("file.handle == FILE_INVALID");
		return RESULT_FAIL;
		}
		DL_FsReadFile( buf, 1, 3, file.handle, &r );
		
		state=next_state;
		
	file.cur_position=-1;
    file.page_size = 0;
    file.s_page_size = 0;
    file.size = DL_FsSGetFileSize(uri,0)+1;
    file.num_page = 1;
	page_null = 1;
	LoadBuffer(0);
		
		if(state!=HELP) {
		u_strcpy(viewer_title, file_list[item.select].name);
		u_strcat(viewer_title, L" ");
		u_ltou(file.size-1, viewer_title+u_strlen(viewer_title));
		u_strcat(viewer_title, L"b ");
		
		if(file.code_type == CODE_ANSI)
		u_strcat(viewer_title, L"CP-1251");
		else if(file.code_type == CODE_UCS2_BE)
		u_strcat(viewer_title, L"UTF-16BE");
		else if(file.code_type == CODE_UTF8)
		u_strcat(viewer_title, L"UTF-8");
		else if(file.code_type == CODE_UTF8_BOM)
		u_strcat(viewer_title, L"UTF-8 BOM");
		}else{
		if(!DL_FsFFileExist(uri))
		u_strcpy(viewer_title, L"mc.hlp не найден");
		}
	}
    return RESULT_OK;
}

UINT32 MakeContentAboutFlie(APPLICATION_T *app )
{
	APP_MC_T         *papp = (APP_MC_T*)app;
	VOLUME_DESCR_T   volume_info;
	WCHAR  			 uri[256];
	WCHAR			 attr[5] = L"----";
	UINT16			 i=0;
	
	file.size = 0;
	
	u_strcpy(viewer_title, Language(5));
	
	if(!IsRoot()){
		// Инфо о файле/папке
		count_select=0;
		for(i=1; i< papp->entries_num; i++){
		if(file_list[i].selected)
		{
		count_select++;
		}
		}

			u_strcpy(uri, cur_folder);
			u_strcat(uri, file_list[item.select].name);
			
			if(count_select==1)
			{
			u_strcpy(viewer_content, Language(6));
			u_strcat(viewer_content, file_list[item.select].name);
			u_strcat(viewer_content, L"\n");
			}else{
				u_strcpy(viewer_content, L"---\n");
			}
			
			//Тип:
			if(count_select==1)
			{
				u_strcat(viewer_content, Language(16));
				if (file_list[item.select].attrib & FS_ATTR_DIRECTORY )
				u_strcat(viewer_content, L"<DIR>");
				else
				u_strcat(viewer_content, file_list[item.select].ext);
				u_strcat(viewer_content, L"\n");
			}else{
				u_strcat(viewer_content, L"---\n");
			}
			
			//Папка:
			u_strcat(viewer_content, Language(7));
			u_strcat(viewer_content, cur_folder);
			u_strcat(viewer_content, L"\n");

			//Размер:
			if( count_select == 1 ) {
				if (file_list[item.select].attrib & FS_ATTR_DIRECTORY )
				file.size = UtilRGetDirSize(uri);
				else
				file.size = DL_FsSGetFileSize(uri,0);
			} else {
				for(i=1; i< papp->entries_num; i++){
					if(file_list[i].selected)
					{
					u_strcpy(uri, cur_folder);
					u_strcat(uri, file_list[i].name);
					
					if (file_list[i].attrib & FS_ATTR_DIRECTORY )
						file.size += UtilRGetDirSize(uri);
					else
						file.size += DL_FsSGetFileSize(uri,0);
					}
				}
			}
			u_strcat(viewer_content, lang(LG_SIZE));
			if(file.size >= 1024) {
				u_ltou(file.size/1024, viewer_content+u_strlen(viewer_content));
				u_strcat(viewer_content, L"Kb\n");
			} else {
				u_ltou(file.size, viewer_content+u_strlen(viewer_content));
				u_strcat(viewer_content, L"b\n");
			}
			//Атрибуты:
			if(count_select==1)
			{
			u_strcat(viewer_content, lang(LG_ATTRIBUTES));
			u_strcat(viewer_content, L": ");
				if ( file_list[item.select].attrib & FS_ATTR_READONLY ){ attr[0] = 'r';  edit[0].sel = true;}
				if ( file_list[item.select].attrib & FS_ATTR_HIDDEN ){ attr[1] = 'h';  edit[1].sel = true;}
				if ( file_list[item.select].attrib & FS_ATTR_SYSTEM ){ attr[2] = 's';  edit[2].sel = true;}
				if ( file_list[item.select].attrib & FS_ATTR_ARCHIVE ){ attr[3] = 'a';  edit[3].sel = true;}
				u_strcat(viewer_content, attr);	
				u_strcat(viewer_content, L"\n");
			} else {
				u_strcat(viewer_content, L"---\n");
			}

	}else{
		
				// Инфо о диске
				u_strcpy(uri, cur_folder);
				u_strcat(uri, file_list[item.select].name);
				DL_FsGetVolumeDescr(uri, &volume_info);
				
					//Имя диска:
					u_strcpy(viewer_content, Language(6));
					u_strcat(viewer_content, L"/");
					u_strcat(viewer_content, file_list[item.select].name);
					u_strcat(viewer_content, L"/\n");
					
					//Итого:
					u_strcat(viewer_content, Language(10));
					u_ltou(volume_info.capacity/1024, viewer_content+u_strlen(viewer_content));
					u_strcat(viewer_content,L"Kb\n");
					//Занято:
					u_strcat(viewer_content, Language(11));
					u_ltou(volume_info.capacity/1024 - volume_info.free/1024, viewer_content+u_strlen(viewer_content));
					u_strcat(viewer_content,L"Kb\n");
					
					//Свобондо:
					u_strcat(viewer_content, Language(12));
					u_ltou(volume_info.free/1024, viewer_content+u_strlen(viewer_content));
					u_strcat(viewer_content,L"Kb\n");
					//Метка:
					u_strcat(viewer_content, Language(13));
					u_strcat(viewer_content, volume_info.vol_name);
					u_strcat(viewer_content, L"\n");	
	}
	
    return RESULT_OK;
}

//Выбрать
UINT32 SelectItemList( EVENT_STACK_T *ev_st,  APPLICATION_T *app ) 
{
    UINT32         		  i;
    WCHAR          		  uri[256];
	WCHAR          		  src_name[128];

    dbg("Select item in FB");
    
    	    if (item.select == 0 && !IsRoot())
			{
                 dbg("Select item in FB: Level Up");
				// назад
				if (cur_folder[u_strlen(cur_folder)-1] == '/') cur_folder[u_strlen(cur_folder)-1] = 0;
					for (i=u_strlen(cur_folder)-1; i > 0 ; i--)
					{
						if (cur_folder[i] == '/'){
							break;
						} else {
							cur_folder[i] = 0;
						}
					}
					if(state == ZIP_BROWSER) state = MAIN;
					item.select=item.prev;
					FindFile( cur_folder, L"*", app );
					DrawList(app);
					PaintSelectList(item.select, app);
					AHG_Flush();
			}
			else
			{
	if(state != ZIP_BROWSER)
	{
					if (IsRoot())
					{
                        dbg("Select item in FB: Open Drive");
                        //  открыть диск
						u_strcpy(cur_folder, L"/");
						u_strcat(cur_folder, file_list[item.select].name);
	                    item.prev=item.select;
						FindFile( cur_folder, L"*", app );
						item.select=0;
						DrawList(app);
						PaintSelectList(0, app);
						AHG_Flush();
					}
					else if (file_list[item.select].attrib & FS_ATTR_DIRECTORY)
					{
                        dbg("Select item in FB: Open folder");
                        //  открыть папку
						u_strcat(cur_folder, file_list[item.select].name);
						u_strcat(cur_folder, L"/");
	                    item.prev=item.select;
						FindFile( cur_folder, L"*", app );
						item.select=0;
						DrawList(app);
						PaintSelectList(0, app);
						AHG_Flush();
					}
                    else if (cmpstr(file_list[item.select].ext, L"elf" ))
					{
						//  запустить эльф
						u_strcpy(uri, cur_folder);
						u_strcat(uri, file_list[item.select].name); 
						if (DL_FsFFileExist(uri)) {						
						udbg(" Select item in FB: ldrLoadElf : %s ", uri);						
						ldrLoadElf(uri, NULL);}
					}
					else if (cmpstr(file_list[item.select].ext, L"zip" ) || cmpstr(file_list[item.select].ext, L"jar" ))
					{
						//  открыть zip файл
						state=ZIP_BROWSER;
						
						u_strcpy(file.zip_uri, cur_folder);
						u_strcat(file.zip_uri, file_list[item.select].name); 
						
						u_strcat(cur_folder, file_list[item.select].name);
						u_strcat(cur_folder, L"/");
						
						udbg(" Select item in FB: open zip: %s", file.zip_uri);
						ZIP_ReadFileList( file.zip_uri, app);
						
						item.select=0;
						DrawList(app);
						PaintSelectList(0, app);
						AHG_Flush();
					}
					else
					{
						//  открыть файл
						u_strcpy(uri, cur_folder);
						u_strcat(uri, file_list[item.select].name); 
						udbg(" Select item in FB: open file: %s", uri);
						OpenFile(uri);
					}
			
	}
	else
	{				
			u_strcat(src_name, file_list[item.select].name);

			
			u_strcpy(file.temp_uri, setting.temp_dir);
			u_strcat(file.temp_uri, SplitPath(file_list[item.select].name, L"/"));
			UnpackFile(file.zip_uri, src_name, file.temp_uri);
			
			if(!u_strcmp(file_list[item.select].ext, L"elf" ))
			{
					if (DL_FsFFileExist(file.temp_uri)){	
					udbg(" Select item in ZIP : ldrLoadElf : %s ",file.temp_uri);	
					ldrLoadElf(uri, NULL); 
					state=MAIN;
					}else{
					err(" Select item in ZIP : ldrLoadElf: Error: file not exist ", 0);}
				}
				else
				{
					if (DL_FsFFileExist(file.temp_uri)){	
					udbg(" Select item in ZIP : Open File: %s ",  file.temp_uri);	
					OpenFile(file.temp_uri);
					}else{
					udbg(" Select item in ZIP : Open File: %s, Error: file not exist ", file.temp_uri);
				}
			}
		}
	}
	return RESULT_OK;
}
//Выбрать
UINT32 SelectItemMenu( EVENT_STACK_T *ev_st,  APPLICATION_T *app ) 
{
	WCHAR           file_uri[272];
	DL_FS_MID_T 	fid;
	WCHAR *			arg = NULL;
	_u64			tmp;

		if(state==FAST_MENU)
		{
			if(DL_FsDirExist(menu[item.menu].value))
			u_strcpy(cur_folder, menu[item.menu].value);
		}
		else
		{
			u_strcat(file_uri, cur_folder);
			u_strcat(file_uri, file_list[item.select].name);

			DL_FsGetIDFromURI( file_uri, &fid );
			
			
			arg = (WCHAR *) malloc(sizeof(WCHAR)*16+1);
			memcpy(&tmp, &fid, sizeof(UINT64));
			util_ul2u(tmp.R0, arg, 8);
			util_ul2u(tmp.R1, arg+8, 8);
			
				if (DL_FsFFileExist(menu[item.menu].value)){	
					udbg(" SelectItemMenu : Open File: %s ", file_uri);	
					ldrLoadElf(menu[item.menu].value, arg);	
					mfree(arg);
				}else{
					err(" SelectItemMenu : Open File: Error: elf not exist ", 0);
				}
		}

	item.menu=0;
	state=MAIN;
	APP_UtilChangeState( MC_STATE_MAIN, ev_st, app );
	AHG_Flush();
	
		return RESULT_OK;
}

//Выбрать
UINT32 SelectItemMenu2( EVENT_STACK_T *ev_st,  APPLICATION_T *app ) 
{
	APP_MC_T         *papp = (APP_MC_T*)app;
	FILE			 f;
	UINT32	         written, r;
	char  			 enter[] = {0x0D, 0x0A};
    char  			 buf[2];
	char  			 buf_fullname[256];
	WCHAR  			 uri[256];
	
	
	if(state==MAIN_MENU)
	{
		switch(item.menu)
		{
			case 0:
				SelectItemList(ev_st, app );
				break;
			
			case 1:
				state=CREATE_FILE;
				papp->res = 0x010000DB; // Новый
				APP_UtilChangeState( MC_STATE_EDIT, ev_st, app );
				break;
			
			// Добавить закладку
			case 2:
				if(item.select == 0) return RESULT_OK;
				u_mkpath(uri, cur_folder, file_list[item.select].name, 0);
				u_strcat(uri, L"/");
				
				if(DL_FsDirExist(uri)){
					u_utoa(file_list[item.select].name, buf_fullname);
					strcat(buf_fullname, "=");
					u_utoa(uri, buf_fullname+strlen(buf_fullname));
					
					f = DL_FsOpenFile(file.menu, FILE_APPEND_PLUS_MODE, 0);
					DL_FsFSeekFile( f,  -2, SEEK_WHENCE_END );
					DL_FsReadFile( buf, 2, 1, f,  &r );
					DL_FsFSeekFile( f,  0, SEEK_WHENCE_END );

						if (DL_FsGetFileSize(f) != 0 && buf[0] != enter[0] && buf[1] != enter[1]) {
							DL_FsWriteFile( enter, 2, 1, f, &written );
						}
					DL_FsWriteFile(buf_fullname, strlen(buf_fullname), 1, f, &written );
					DL_FsWriteFile( enter, 2, 1, f, &written );
				
					DL_FsCloseFile(f);
				}
				state=MAIN;
				APP_UtilChangeState( MC_STATE_MAIN, ev_st, app );
				AHG_Flush();
				break;
			
			case 3:
				state=FAST_MENU;
				ReadMenu(app);
				APP_UtilChangeState( MC_STATE_MAIN, ev_st, app );
				AHG_Flush();
				APP_UtilChangeState( MC_STATE_MENU, ev_st, app );
				DrawMenu(item.menu, app);
				AHG_Flush();
				break;
			
			case 4:
				state=HELP;
				next_state=HELP;
				MakeContentFromFlie();
				APP_UtilChangeState( MC_STATE_VIEWER, ev_st, app );
				DrawViewer();
				break;
			
			case 5:
				state=ABOUT;
				u_strcpy(viewer_title, L"About...");
				u_strcpy(viewer_content, L"MiniCommader " APP_VERSION L"\n"
										 L"(c) 2009-2010 R.U.S.H.A.N.\n"
										 L"http://forum.motofan.ru\n"
										 L"http://elfov.net.ru\n"
										 L"Thank`s to: baat ,\n"
										 L"Gray One for tests\n");
				APP_UtilChangeState( MC_STATE_VIEWER, ev_st, app );				
				DrawViewer();
				AHG_Flush();
				break;
			
			case 6:
				destroyApp(ev_st, app );
				break;
		}
	}else{
		switch(item.menu)
		{
			case 0:
				file.code_type = CODE_ANSI;
				break;
			
			case 1:
				file.code_type = CODE_UCS2_BE;
				break;
			
			case 2:
				file.code_type = CODE_UTF8;
				break;
				
			case 3:
				file.code_type = CODE_UTF8_BOM;
				break;
		}
		if (MakeContentFromFlie() != RESULT_FAIL){
				APP_UtilChangeState( MC_STATE_VIEWER, ev_st, app );
				DrawViewer();
		}
	}		
	item.menu=0;
	
		return RESULT_OK;
}

//Сохранить
UINT32 Save( EVENT_STACK_T *ev_st,  APPLICATION_T *app )
{
	WCHAR          		uri[256]=L"";
	char 		  		buf[BUFFER_SIZE];
	WCHAR 		  		u_buf[BUFFER_SIZE+3];
	UINT8 		  		utf_buf[BUFFER_SIZE];
	FILE_HANDLE_T 		File=0;
    UINT32 		  		w=0;
		u_mkpath(uri, cur_folder, file_list[item.select].name, 1);
		udbg(" Save: start, file = %s", uri);	
		
		File = DL_FsOpenFile(uri, FILE_WRITE_MODE, 0);
		
		if (File == FILE_HANDLE_INVALID ){
			err(" Save: error, FILE_HANDLE_INVALID", 0);
			MakeContentFromFlie();
			APP_UtilChangeState( MC_STATE_VIEWER, ev_st, app );
			DrawViewer();
			return RESULT_FAIL;
		}
		
		// запись в файл
		if(file.code_type == CODE_ANSI)
		{
			UCS2toCP1251(file.buffer, buf);
			DL_FsWriteFile( buf, 1, strlen(buf)+1, File, &w );
		}
		else if (file.code_type == CODE_UCS2_BE) 
		{
			u_buf[0] = 0xfeff; // учитываем magic у кодировок
			u_buf[1] = 0;      //
			u_strcat(u_buf, file.buffer);
			DL_FsWriteFile( u_buf, 1, sizeof(WCHAR)*u_strlen(u_buf), File, &w );
		}
		else if (file.code_type == CODE_UTF8) 
		{
			u_strcpy(u_buf, file.buffer);
			DL_Char_convUCS2toUTF8String(u_buf, sizeof(WCHAR)*u_strlen(u_buf), utf_buf, sizeof(WCHAR)*u_strlen(u_buf));

			DL_FsWriteFile( utf_buf, 1, u_strlen(u_buf)*2, File, &w );
		}
		else if (file.code_type == CODE_UTF8_BOM) 
		{
			u_strcpy(u_buf, L"000");
			u_strcat(u_buf, file.buffer);
			DL_Char_convUCS2toUTF8String(u_buf, sizeof(WCHAR)*u_strlen(u_buf), utf_buf, sizeof(WCHAR)*u_strlen(u_buf));
			utf_buf[0] = 0xef; // 
			utf_buf[1] = 0xbb; // учитываем magic у кодировок
			utf_buf[2] = 0xbf; //
			DL_FsWriteFile( utf_buf, 1, u_strlen(u_buf)*2, File, &w );
		}

	dbgf("- Write %d bytes", w);
	DL_FsCloseFile(File);

	
	MakeContentFromFlie();
	APP_UtilChangeState( MC_STATE_VIEWER, ev_st, app );
	DrawViewer();
	
	dbg("Save: end");
	return RESULT_OK;
}

UINT32 EditOk( EVENT_STACK_T *ev_st,  APPLICATION_T *app )
{
	 APPLICATION_T			   *papp = (APPLICATION_T*) app;
     ADD_EVENT_DATA_T 		   *ev_data;

	 dbg("EditOk"); 
	 
     AFW_AddEvEvD(ev_st, EV_REQUEST_DATA,ev_data);
	 UIS_HandleEvent( papp->dialog,  ev_st );

    return status;
}


UINT32 EditData( EVENT_STACK_T *ev_st,  APPLICATION_T *app )
{
	WCHAR         src[256];
    WCHAR         dst[256];
	FILE          file_;

	EVENT_T       *event = AFW_GetEv(ev_st);
	dbg("EditData"); 

	if(event->attachment!=NULL){
	
		switch(state)
		{
			case EDIT_FILE:
				u_strcpy(file.buffer, event->attachment);
				Save(ev_st, app );
				break;
				
			case RENAME:
				u_strcpy(src, cur_folder);
				u_strcat(src, file_list[item.select].name);
				u_strcpy(dst, event->attachment);		
				DL_FsSRenameFile(src, dst,0);
				APP_UtilChangeState( MC_STATE_MAIN, ev_st, app );
				AHG_Flush();
				break;
		
			case CREATE_FILE:
				u_strcpy(src, cur_folder);
				u_strcat(src, event->attachment);
				file_ = DL_FsOpenFile(src, FILE_WRITE_PLUS_MODE, 0);
				DL_FsCloseFile(file_);
				APP_UtilChangeState( MC_STATE_MAIN, ev_st, app );
				AHG_Flush();
				break;
				
			case CREATE_DIR:
				u_strcpy(src, cur_folder);
				u_strcat(src, event->attachment);
				DL_FsMkDir(src, 0);
				APP_UtilChangeState( MC_STATE_MAIN, ev_st, app );
				AHG_Flush();
				break;
		}
	}
    return RESULT_OK;

}



//Обработчик кнопки "Отмена" в редакторе
UINT32 EditCancel( EVENT_STACK_T *ev_st,  APPLICATION_T *app )
{
	dbg("EditCancel");
	APP_ConsumeEv( ev_st, app );

	
    status = APP_UtilChangeState( MC_STATE_MAIN, ev_st, app );
	AHG_Flush();
	
    return status;
}

UINT32 OpenFile(WCHAR *uri) 
{ 
	DL_FS_MID_T *	fid;
	dbg("OpenFile: Enter");
	
	fid = (DL_FS_MID_T *) malloc(sizeof(DL_FS_MID_T));
	DL_FsGetIDFromURI( uri, fid );
	dbgf("OpenFile: send CMD to ExtMGR, fid = 0x%x%x", *fid);
	status = AFW_CreateInternalQueuedEvAux( EXTMGR_MAIN_REGISTER_, FBF_FREE, sizeof(DL_FS_MID_T), fid );

	
    return status;
}

//////////////////////////////////////////////////////////////util//////////////////////////////////////////////////////////////

BOOL IsRoot(void)
{
	
	if (!u_strcmp(cur_folder, L"/"))
		return TRUE;
	else
		return FALSE;
}

WCHAR* Language(UINT8 lng)
{
	LANGUAGE_T LGID;
	
	DRM_GetCurrentLanguage(&LGID);
	
	
	if (LGID == LNG_RUSSIAN)
		return lang_rus[lng];
	else
		return lang_eng[lng];
}

void * alloc_biggest( UINT32 start_sz, UINT32 * block_sz )
{
	void *		ptr;
	UINT32		sz;
	INT32		err;
	
	sz = start_sz;
	
	err = 0;
	while ( err == 0 ) {
		ptr = suAllocMem( sz, &err );
		if ( err == 0 ) {
			suFreeMem(ptr);
			sz += 512*4;
		} else {
			while ( err != 0 && sz > start_sz ) {
				sz -= 512;
				ptr = suAllocMem( sz, &err );
			}
			break;
		}
	}
	
	if ( ptr )
		*block_sz = sz;
	else
		*block_sz = 0;
	return ptr;
}

void TestMem()
{
	void *			ptrs[256];
	UINT32			szs[256];
	UINT32			total_sz;
	UINT32			i;
	
	i = 0;
	total_sz = 0;
	do {
		ptrs[i] = alloc_biggest( 512*5, &szs[i] );
		total_sz += szs[i];
	} while ( ptrs[i++] != NULL );
	i--;
	while ( i-- > 0 ) {
		suFreeMem( ptrs[i] );
	}
	free_mem = total_sz;
}

void util_ul2u( UINT32 src, WCHAR * dst, int count )
{
	UINT32	tmp;
	int		i = 7;
	
	while ( count > 0 && i >= 0 ) {
		tmp = src;
		tmp = tmp >> (i*4);
		tmp = tmp & 0xF;
		tmp += '0';
		if ( tmp > '9' )
			tmp += 7;
		*dst++ = tmp;
		
		count--;
		i--;
	}
	*dst = 0;
}
// сравнить две строки без учёта регистра
BOOL cmpstr(WCHAR *str1, WCHAR *str2) 
{
    u_strmakelower(str1);
    u_strmakelower(str2);

    if (!u_strcmp(str1, str2))
	return true;
    else
	return false;

    return RESULT_OK;
}

UINT32 ReadSetting() 
{
	UINT32 					readen;
	FILE_HANDLE_T 			f;
	
	// читаем данные из конфига
	if (!DL_FsFFileExist(file.cfg)) return RESULT_OK; // проверяем есть ли файл
	
		f = DL_FsOpenFile(file.cfg, FILE_READ_MODE, 0);
		DL_FsReadFile( setting.cur_folder1, sizeof(WCHAR)*256, 1, f, &readen );
		DL_FsReadFile( setting.cur_folder2, sizeof(WCHAR)*256, 1, f, &readen );
		
        DL_FsCloseFile(f);

		if(!DL_FsDirExist(setting.cur_folder1))
		u_strcpy(setting.cur_folder1, L"/");
		else
		u_strcpy(cur_folder, setting.cur_folder1);
		
		if(!DL_FsDirExist(setting.cur_folder2))
		u_strcpy(setting.cur_folder2, L"/");
	
	return RESULT_OK;
}

// записываем в конфиг
UINT32 SaveSetting(APPLICATION_T *app)
{
	APP_MC_T         		*papp = (APP_MC_T*)app;
	UINT32 					written;
	FILE_HANDLE_T 			f;
	dbg("SaveSetting");
	if(state == ZIP_BROWSER) return RESULT_OK;
	// запись в файл
	f = DL_FsOpenFile(file.cfg, FILE_WRITE_MODE, 0);
	
		if( papp->window == 1 )
		u_strcpy(setting.cur_folder1, cur_folder);
		else
		u_strcpy(setting.cur_folder2, cur_folder);
		
		DL_FsWriteFile( setting.cur_folder1, sizeof(WCHAR)*256, 1, f, &written );
		DL_FsWriteFile( setting.cur_folder2, sizeof(WCHAR)*256, 1, f, &written );
	
	DL_FsCloseFile(f);
	
	return RESULT_OK;
}


UINT32 Action( EVENT_STACK_T * ev_st,  APPLICATION_T *app )
{
	APP_MC_T         		*papp = (APP_MC_T*)app;
	WCHAR					src[256];
	UINT16					i=0;
	
	switch(file_op_state)
	{
			case COPY_FILE:
				count_select=0;
				dbg("Action: COPY_FILE");
				for(i=1; i< papp->entries_num; i++){
					if(file_list[i].selected)
					{
					count_select++;
					file.src_copy_uri[count_select] = (WCHAR*)malloc(sizeof(WCHAR) * u_strlen(cur_folder)+u_strlen(file_list[i].name) );
					file.src_copy_name[count_select] = (WCHAR*)malloc(sizeof(WCHAR) * u_strlen(file_list[i].name) );
					
					u_strcpy(file.src_copy_uri[count_select], cur_folder);
					u_strcat(file.src_copy_uri[count_select], file_list[i].name);
					u_strcpy(file.src_copy_name[count_select], file_list[i].name);
					}
				}
				break;
				
			case PASTE_FILE:
			dbg("Action: PASTE_FILE");
				for(i=0; i <= count_select; i++){
				file.dst_copy_uri[count_select] = (WCHAR*)malloc(sizeof(WCHAR) * u_strlen(cur_folder)+u_strlen(file_list[i].name) );
				
					u_strcpy(file.dst_copy_uri[i], cur_folder);
					u_strcat(file.dst_copy_uri[i], file.src_copy_name[i]);
					UtilCopyFile(file.src_copy_uri[i], file.dst_copy_uri[i]);
				}
				state=MAIN;
				break;

			case ZIP_BROWSER_COPY:
				file.src_copy_name[0] = (WCHAR*)malloc(sizeof(WCHAR) * u_strlen(file_list[item.select].name) );
				u_strcpy(file.src_copy_name[0], file_list[item.select].name);
				
				if (cur_folder[u_strlen(cur_folder)-1] == '/') cur_folder[u_strlen(cur_folder)-1] = 0;
				for (i=u_strlen(cur_folder)-1; i > 0 ; i--)
				{
					if (cur_folder[i] == '/'){
						break;
					} else {
						cur_folder[i] = 0;
					}
				}
				state=MAIN;
				break;
				
			case ZIP_BROWSER_PASTE:
				file.dst_copy_uri[0] = (WCHAR*)malloc(sizeof(WCHAR) * u_strlen(cur_folder)+u_strlen(file_list[item.select].name) );
				u_mkpath(file.dst_copy_uri[0], cur_folder, SplitPath(file.src_copy_name[0], L"/"), 0);
				UnpackFile(file.zip_uri, file.src_copy_name[0], file.dst_copy_uri[0]);
				break;
				
			case DEL_DIR: //Удалить папку/файл
				dbg("Action: DEL_DIR");
				for(i=1; i< papp->entries_num; i++){
					if(file_list[i].selected) {
						u_mkpath(src, cur_folder, file_list[item.select].name, 0);
						status = UtilRDelDir(src, NULL);
						if(status != RESULT_OK); DL_AudPlayTone(13, 125);
					}
				}
				state=MAIN;
				FindFile(cur_folder, L"*", app);
				PaintSelectList(item.select, app);
				break;
	}
				
	return RESULT_OK;
}

// поиск файлов
UINT32 FindFile( WCHAR *folder, WCHAR *filtr, APPLICATION_T *app)
{
	 APP_MC_T         		*papp = (APP_MC_T*)app;
     FS_SEARCH_PARAMS_T		sp;
     FS_SEARCH_RESULT_T		hResult;
     FS_SEARCH_HANDLE_T		hSearch;
    
    
     UINT16		count_files=0, count_res=1;
     INT32		i=0, j=0;
     UINT8      mode=0;
     WCHAR      volumes[64];
    
     WCHAR      search_string[272];


     if ( folder==NULL || !u_strcmp(folder, L"/")) {
             u_strcpy(search_string, L"/");
     } else {
         // определяем нужен ли file://
         if(u_strncmp(folder, L"file:/", 6))
         {
             u_strcpy(search_string, L"file:/");
             u_strcat(search_string, folder);
         } else {
             u_strcpy(search_string, folder);
         }
    
         // определяем нужен ли сплеш
         if ( folder[u_strlen(folder)-1] != '/' ) 
             u_strcat(search_string, L"/");
    
         u_strcat(search_string, L"\xFFFE");
         u_strcat(search_string, filtr);
     }

 ///// Особенности /////
 // 1) в корне диска `a` в hResult.name относительный путь!
 // 2) в списке может быть имя текущей папки. При этом в конце есть слэш. Последствия патча "удаление ненужных папок с тела"
 //////////////////////


    if (!u_strcmp(search_string, L"/")) { // диски

	dbg("Find Volumes...");
	
        DL_FsVolumeEnum(volumes);

        if ( file_list ) mfree(file_list);
		file_list = malloc(sizeof(FILEINFO) * 3);
		if (file_list == NULL) return RESULT_FAIL;
        cur_folder[0] = '/';

        papp->entries_num = 0;

        for (i=0; i < 4; i++ ) {
            file_list[i].name[0] = volumes[i*3+1];//'a' + i;
			file_list[i].name[1] = '/';
            file_list[i].name[2] = 0;
            file_list[i].attrib = FS_ATTR_DIRECTORY;
			file_list[i].selected = false;
			
            papp->entries_num++;

            if ( volumes[i*3+2] == NULL ) break;
        }
		dbg("Find Volumes: is done");
        return RESULT_OK;
    }

	dbg("Find files...");
	
	sp.flags = 0x1C; 
	sp.attrib = 0;
	sp.mask = 0;
	
	status = DL_FsSSearch( sp, search_string, &hSearch, &count_files, 0 );
    dbgf("Search status = %d", status);
	if ( status != RESULT_OK ) {
        DL_FsSearchClose( hSearch );
        return RESULT_FAIL;
    }

    dbgf("count_files = %d", count_files);
	
	papp->entries_num = count_files+1;

	if ( file_list ) mfree(file_list);
	file_list = malloc(sizeof(FILEINFO) * (count_files+1));
	if (file_list == NULL) return RESULT_FAIL;

	u_strcpy(file_list[0].name, L"..");
	file_list[0].attrib = FS_ATTR_DIRECTORY;
	file_list[0].selected = false;


    for ( i=0, j=1; j<=count_files; i++ ) {

            if (i >= count_files){
                if (mode > 0) {
                    break;
                } else {
                    i=-1;
                    mode=1;
                    continue;
                }
            }

		status = DL_FsSearchResults( hSearch, i, &count_res, &hResult );
		if ( status == RESULT_OK ) 
		{
            if ((mode==0) && !(hResult.attrib&FS_ATTR_DIRECTORY)) continue;
            if ((mode==1) && (hResult.attrib&FS_ATTR_DIRECTORY)) continue;

            // фиксим последствия  патча "удаление ненужных папок с тела"
            if(!u_strcmp(hResult.name+u_strlen(hResult.name)-1, L"/")) continue;
            	
			u_strcpy(file_list[j].name, SplitPath(hResult.name, L"/"));
			u_strcpy(file_list[j].ext, SplitPath(file_list[j].name, L"."));
			file_list[j].attrib = hResult.attrib;
			file_list[j].selected = false;
		} 
        j++;
	}

	DL_FsSearchClose( hSearch ); 


    dbg("Find files: end");

	
	return RESULT_OK;
}

UINT32 UtilCopyFile(WCHAR * src, WCHAR * dst )
{
	char				cbuf[2<<12];	// Copy buffer
	FILE				fSrc, fDst;
	UINT32				size;	// Сколько записать
	UINT16				attr;

	if ( DL_FsFFileExist(dst) )
		return RESULT_FAIL;		// Не перезаписывать!
	if ( !DL_FsFFileExist(src) )
		return RESULT_FAIL;		// Копируемый файл удален? Кто посмел?

	// Копирование
	fSrc = DL_FsOpenFile( src, FILE_READ_MODE, NULL );
	fDst = DL_FsOpenFile( dst, FILE_WRITE_MODE, NULL );
	if ( fSrc == FILE_HANDLE_INVALID || fDst == FILE_HANDLE_INVALID ) {
		DL_FsCloseFile(fSrc);
		DL_FsCloseFile(fDst);
		return RESULT_FAIL;
	}
	size = 2<<12;
	while(size == 2<<12) {
		DL_FsReadFile( cbuf, 1, size, fSrc, &size );
		DL_FsWriteFile( cbuf, 1, size, fDst, &size );
	}
	
	DL_FsFlush();
	attr = DL_FsGetAttr(fSrc);
	DL_FsFSetAttr(fDst, attr);
	DL_FsCloseFile(fSrc);
	DL_FsCloseFile(fDst);
	
	return RESULT_OK;
}

// рекурсивное удаление папки
UINT32 UtilRDelDir(WCHAR * uri, WCHAR * filtr )
{
	FS_SEARCH_PARAMS_T		fs_sp;			// Параметры поиска
	FS_SEARCH_RESULT_T *	fs_sres;		// результаты
	FS_SEARCH_HANDLE_T		fs_shandle;		// Идентификатор поиска
	WCHAR 					search_str[256];
	UINT16					fc;
	UINT16					i;
	
	if(DL_FsDirExist(uri))
	{
	u_mksearch(search_str, uri, filtr );
	fs_sp.flags = 0x18;
	fs_sp.attrib = 0;
	fs_sp.mask = 0;
	status = DL_FsSSearch( fs_sp, search_str, &fs_shandle, &fc, 0 );
	mfree(search_str);
	if ( status != RESULT_OK ) {
		return status;
	}
	fs_sres = (FS_SEARCH_RESULT_T *) malloc( sizeof(FS_SEARCH_RESULT_T) * fc );
	status = DL_FsSearchResults( fs_shandle, 0, &fc, fs_sres );
	DL_FsSearchClose( fs_shandle );
	if ( status != RESULT_OK ) {
		mfree(fs_sres);
		return RESULT_FAIL;
	}
	for ( i=0; i<fc; i++ ) {
		if ( fs_sres[i].attrib & FS_ATTR_DIRECTORY ) {
			status |= UtilRDelDir( fs_sres[i].name, filtr );
		} else {
			status |= DL_FsDeleteFile(fs_sres[i].name, NULL);
		}
	}
	mfree(fs_sres);
	
	// Предположительно папка уже пуста!
	// если статус RESULT_FAIL , то возможно что некоторые файлы уже были удалены до нас и все ОК
	
	// Если выбирали удаление по фильтру, то папки не нада удалять =). Они могут быть еще не пустыми
	if ( !filtr )
		status |= DL_FsRmDir(uri, 0, NULL);
	}else{
		status |= DL_FsDeleteFile(uri, NULL);
	}
	return status;
}
UINT32 UtilRGetDirSize( WCHAR * uri )
{
	FS_SEARCH_PARAMS_T		s_par;
	FS_SEARCH_RESULT_T *	s_res;
	FS_SEARCH_HANDLE_T		sh;
	WCHAR 					s_str[256];
	UINT32					i;
	size_t					size;
	UINT16					c, j, c1;
	
	udbg(" UtilRGetDirSize: Enter, uri = `%s`", uri);
	size = 0;
	s_par.flags		= FS_SEARCH_RECURSIVE | FS_SEARCH_START_PATH;
	s_par.attrib	= 0;
	s_par.mask		= 0;
	
	u_mksearch(s_str, uri, L"*.*" );
	
	status = DL_FsSSearch( s_par, s_str, &sh, &c, 0 );
	dbgf("UtilRGetDirSize: DL_FsSSearch DONE, status = %d, file_count = %d", status, c );
	mfree( s_str );
	if ( status != RESULT_OK )
		return 0;
	s_res = (FS_SEARCH_RESULT_T *) malloc(sizeof(FS_SEARCH_RESULT_T) * 35);
	j = 0;
	while ( j < c ) {
		c1 = 35;
		status = DL_FsSearchResults( sh, j, &c1, s_res );
		dbgf("UtilRGetDirSize: DL_FsSearchResults DONE, status = %d, file_count = %d", status, c1);
		j+= c1;
		for ( i=0; i<c1; i++ ) {
			size += DL_FsSGetFileSize(s_res[i].name, NULL);
		}
	}
	DL_FsSearchClose( sh );
	dbg("UtilRGetDirSize: DL_FsSearchClose DONE");
	mfree(s_res);
	dbgf("UtilRGetDirSize DONE, size = %d", size);
	return size;
}


UINT32 UtilSetColForFile(UINT32 index)
{
		if(file_list[index].attrib & FS_ATTR_DIRECTORY ){
			SetFgColor(Color.Dir);
			
	
		}else if(cmpstr(file_list[index].ext, L"elf")){
			SetFgColor(Color.App);
		}else if(cmpstr(file_list[index].ext, L"bat")){
			SetFgColor(Color.App);
			
		}else if(cmpstr(file_list[index].ext, L"zip")){
			SetFgColor(Color.Arc);
		}else if(cmpstr(file_list[index].ext, L"jar")){
			SetFgColor(Color.Arc);
	
		}else if(cmpstr(file_list[index].ext, L"png")){
			SetFgColor(Color.Pic);
		}else if(cmpstr(file_list[index].ext, L"gif")){
			SetFgColor(Color.Pic);
		}else if(cmpstr(file_list[index].ext, L"jpg")){
			SetFgColor(Color.Pic);
		}else if(cmpstr(file_list[index].ext, L"bmp")){
			SetFgColor(Color.Pic);
			
		}else if(cmpstr(file_list[index].ext, L"mp3")){
			SetFgColor(Color.Audio);
		}else if(cmpstr(file_list[index].ext, L"m4a")){
			SetFgColor(Color.Audio);
		}else if(cmpstr(file_list[index].ext, L"amr")){
			SetFgColor(Color.Audio);
		}else if(cmpstr(file_list[index].ext, L"mid")){
			SetFgColor(Color.Audio);
		}else{
			SetFgColor(Color.Def);
		}
		if(file_list[index].attrib & FS_ATTR_HIDDEN )
		SetFgColor(Color.Sys);
		if(file_list[index].attrib & FS_ATTR_SYSTEM )
		SetFgColor(Color.Sys);
		
		if(file_list[index].selected)
		SetFgColor(0xFFFF00);

    return RESULT_OK;
}

UINT32 UtilGetTotalSelectFiles(APPLICATION_T *app)
{
	APP_MC_T         		*papp = (APP_MC_T*)app;
	UINT16					i=0;
	count_select=0;
		for(i=1; i< papp->entries_num; i++)
		{
			if(file_list[i].selected)
			{
			count_select++;
			}
		}

	return count_select;
}

UINT32 UtilEditAtt(WCHAR * uri, UINT16 attrib)
{
	FS_SEARCH_PARAMS_T		s_par;
	FS_SEARCH_RESULT_T *	s_res;
	FS_SEARCH_HANDLE_T		sh;
	WCHAR 					s_str[256];
	UINT32					i;
	size_t					size;
	UINT16					c, j, c1;

	
	udbg(" UtilEditAtt: Enter, uri = `%s`", uri);
	if(DL_FsDirExist(uri))
	{
		size = 0;
		s_par.flags		= FS_SEARCH_RECURSIVE | FS_SEARCH_START_PATH;
		s_par.attrib	= 0;
		s_par.mask		= 0;
		
		u_mksearch( s_str, uri, L"*.*" );
		status = DL_FsSSearch( s_par, s_str, &sh, &c, 0 );
		dbgf("UtilEditAtt: DL_FsSSearch DONE, status = %d, file_count = %d", status, c );
		mfree( s_str );
		if ( status != RESULT_OK )
			return 0;
		s_res = (FS_SEARCH_RESULT_T *) malloc( sizeof(FS_SEARCH_RESULT_T) * 35 );
		j = 0;
		while ( j < c ) {
			c1 = 35;
			status = DL_FsSearchResults( sh, j, &c1, s_res );
			dbgf("UtilEditAtt: DL_FsSearchResults DONE, status = %d, file_count = %d", status, c1);
			j+= c1;
			for ( i=0; i<c1; i++ ) {
				size += DL_FsSSetAttr(s_res[i].name,0, attrib);
			}
		}
		DL_FsSearchClose( sh );
		dbg("UtilEditAtt: DL_FsSearchClose DONE");
		mfree(s_res);
		dbgf("UtilEditAtt DONE, size = %d", size);
	}else{
	DL_FsSSetAttr(uri, 0 , attrib);
	}
	return size;
}


UINT32 ZIP_ReadFileList(WCHAR * uri, APPLICATION_T *app)
{
	APP_MC_T         	*papp = (APP_MC_T*)app;
	UINT32				count	= 0;
	FILE_HANDLE_T		zip_file;
	UINT32				file_sz, len;
	char				end_hdr[ZIP_END_HEADER_SIZE];
	char				mid_hdr[ZIP_MID_HEADER_SIZE];
	UINT32				read = NULL;
	UINT32				i = NULL;
	UINT32				mid_hdr_off = NULL;
	char *				file_name = NULL;
	
	if ( uri[0] == 0 )
		return 0;
	zip_file = DL_FsOpenFile( uri, FILE_READ_MODE, 0 );
	if ( zip_file == FILE_INVALID )
		return 0;
	file_sz = DL_FsGetFileSize(zip_file);
	dbgf("ZIP_ReadFileList: file_sz = %d", file_sz);
	
	status = DL_FsFSeekFile(zip_file, -ZIP_END_HEADER_SIZE, SEEK_WHENCE_END);
	dbgf("ZIP_ReadFileList: DL_FsFSeekFile DONE, status = %d", status);
	
	status = DL_FsReadFile(end_hdr, 1, ZIP_END_HEADER_SIZE, zip_file, &read);
	dbgf("ZIP_ReadFileList: DL_FsReadFile DONE, status = %d, read = %d", status, read);
	
	if ( end_hdr[0] == 'P' &&
		end_hdr[1] == 'K' &&
		end_hdr[2] == 0x05 &&
		end_hdr[3] == 0x06 ) {
			// Найден последний заголовок
			count = get_UINT16(end_hdr+0x0008)+1;
			mid_hdr_off = getint(end_hdr+0x0010);
			if ( count == 0 ) {
				warn("ZIP_ReadFileList: count == 0", NULL);
			} else if ( DL_FsFSeekFile(zip_file, mid_hdr_off, SEEK_WHENCE_SET) != RESULT_OK ) {
				count = 0;
			} else {

				if ( file_list ) mfree(file_list);
				file_list = malloc(sizeof(FILEINFO) * count);
				
				
				if ( file_list == NULL )
					err("ZIP_ReadFileList: can't allocate file_list", NULL);
				else {
				
					u_strcpy(file_list[0].name, L"..");
					file_list[0].attrib = FS_ATTR_DIRECTORY;
					file_list[0].selected = false;
	
					for ( i=1; i<count; i++ ) {
						DL_FsReadFile(mid_hdr, 1, ZIP_MID_HEADER_SIZE, zip_file, &read);
						if ( mid_hdr[0] != 'P' || mid_hdr[1] != 'K' || mid_hdr[2] != 0x01 || mid_hdr[3] != 0x02 ) {
							err("ZIP_ReadFileList: bad magik", NULL);
							break;
						}
						len = getint(mid_hdr+0x001C);
						file_name = malloc(sizeof(char) * len+1);
						if ( file_name == NULL ) {
							err("ZIP_ReadFileList: can't allocate memory", NULL);
						}
						if ( DL_FsReadFile(file_name, 1, len, zip_file, &read) != RESULT_OK || read != len) {
							err("ZIP_ReadFileList: we have some error here... ", NULL);
							break;
						}
						file_name[len] = 0;
						// TODO: DOS -> Unicode
						CP866toUCS2(file_name, file_list[i].name);
						// TODO: add file name to list
						u_strcpy(file_list[i].ext, SplitPath(file_list[i].name, L"."));
						file_list[i].attrib = 0;	// Нужно узнать как читать атрибуты из архива
						file_list[i].selected = FALSE;
						if ( file_name[len-1] == '/' ) {
							// Это папка
							file_list[i].attrib |= FS_ATTR_DIRECTORY;
						}
						// test
						dbgf("ZIP_ReadFiles: file = %s", file_name);
						mfree(file_name);
					}
				}
//				papp->file_list.list = file_list;
				papp->entries_num = count;
			}
			
	} else {
		// error
		err("ZIP_ReadFileList: can't read zip file", NULL);
		ddbg(end_hdr, sizeof(end_hdr));
		count = 0;
	}
	
	DL_FsCloseFile(zip_file);
	
	return count;
}

UINT32 ReadMenu(APPLICATION_T *app)
{
	APP_MC_T        *papp = (APP_MC_T*)app;
	char            *bufR=NULL;
	UINT32          readen;
	WCHAR 			__file[256];
	FILE_HANDLE_T   f;

    int i = 0, j = 0;
	WCHAR bufVal_buf[256];
	char bufVal[256];
    char bufName[32];
	BOOL bValue = FALSE; 
	papp->entries_num_menu=0;
	if(state==FAST_MENU){ 
	u_strcpy(__file, file.menu);
	}else{
	u_mkpath(__file, elf.dir, L"open_with.ini", 0);
	}
	udbg(" ReadMenu: %s", __file);
	
	
		if (DL_FsFFileExist(__file)) // проверяем есть ли файл
		{
			f = DL_FsOpenFile(__file, FILE_READ_MODE, 0);
			file.size = DL_FsGetFileSize(f);
			bufR = (char*) malloc( sizeof(char) * file.size );
			DL_FsReadFile( bufR, file.size, 1, f, &readen );
            DL_FsCloseFile(f);
            for (i=0; i < file.size; i++)
				if (bufR[i] == 0x0D) j++;

			if(menu != NULL) mfree(menu);
            menu = (LINE*)malloc(sizeof(LINE) * (j+1));
            j=0;

                for (i=0; i < file.size; i++)
                {
                    if (bufR[i] == 0x0D) // разделитель 
                    {
                         u_atou(bufName, menu[papp->entries_num_menu].name);
                         j=0;
                         bValue = FALSE;
                         papp->entries_num_menu++; // следующаястрока
                    }
                    else if (bufR[i] == '=') // =
                    { 
                        bValue = TRUE;
                        j=0;
                    } 
                    else 
                    {
                        if(bufR[i] != 0x0A) // пропускать
                        {
                            if (bValue) {
                                bufVal[j] = bufR[i];
                                bufVal[j+1] = 0;
							u_atou(bufVal,bufVal_buf);
							u_strcpy(menu[papp->entries_num_menu].value, bufVal_buf);
                            } else {
                                if (j < 30) {
                                    bufName[j] = bufR[i];
                                    bufName[j+1] = 0;
                                }
                            }
                             j++;
                        }
                    }
                }
            u_atou(bufName, menu[papp->entries_num_menu].name);
		}
		
	if(!bufR)
	mfree(bufR);
		 
		return status;
}

UINT8 Symbol2Byte(WCHAR symbol) // кол-во байт на символ
{
        if (file.code_type == CODE_UCS2_BE ) {
            return 2;
        } else if(file.code_type == CODE_UTF8 || CODE_UTF8_BOM) {
            if (symbol < 128) return 1;
            else return 2;
        } else {
            return 1;
        }
}

UINT32 LoadBuffer(INT32 off_set) // грузит чаcть файла в буффер
{
    UINT32  r;
	UINT8   buffer[BUFFER_SIZE];

    dbg("Load buffer:");
    if (file.handle == FILE_HANDLE_INVALID) {
        dbg("file.handle invalid");
        return RESULT_FAIL; // файл не открылся
    }

	 if (off_set <= 0) { // учитываем magic у кодировок
        if (file.code_type == CODE_UCS2_BE) 
           off_set = 2;
		else if (file.code_type == CODE_UTF8_BOM)
           off_set = 3;
        else 
           off_set = 0;
    }
		
    if (file.cur_position == off_set) return RESULT_FAIL; // уже на этом смещении


    DL_FsFSeekFile( file.handle, off_set, SEEK_WHENCE_SET ); // переходим на смещение
    dbgf(" - set Offset file = 0x%x", off_set);
	
		
	if (file.code_type == CODE_UCS2_BE ) 
	{
        DL_FsReadFile( viewer_content,  1,  BUFFER_SIZE*sizeof(WCHAR), file.handle, &r );
        if (r == 0) return RESULT_FAIL;
        viewer_content[r/2] = 0; // строка должна заканчиваться нулём
	} 
	else if (file.code_type == CODE_UTF8 || file.code_type == CODE_UTF8_BOM )
	{
        DL_FsReadFile( buffer,  1,  BUFFER_SIZE, file.handle, &r );
		if (r == 0) return RESULT_FAIL;
		buffer[r] = 0;
        DL_Char_convUTF8toUCS2String(buffer,  r, viewer_content,  BUFFER_SIZE*sizeof(WCHAR));
    } 
	else 
	{
		DL_FsReadFile( buffer,  1,  BUFFER_SIZE, file.handle, &r );
		if (r == 0) return RESULT_FAIL;
		buffer[r] = 0;
		DL_Char_convCP1251toUCS2String(buffer, r, viewer_content, BUFFER_SIZE*sizeof(WCHAR));
	}
	
	if(page_null && state==EDIT_FILE)
	{
		dbg(" - num_page==null");
		
		if(DL_FsGetFileSize(file.handle) > 1024){
		u_strcpy(viewer_content, L"Error: File > 1024bytes");
		state=VIEW_FILE;
		return RESULT_FAIL;
		}
		
		
		DL_FsFSeekFile( file.handle, off_set, SEEK_WHENCE_SET ); // переходим на смещение
		if (file.code_type == CODE_UCS2_BE ) 
		{
	        DL_FsReadFile( file.buffer,  1,  file.size*sizeof(WCHAR), file.handle, &r );
	        if (r == 0) return RESULT_FAIL;
	        file.buffer[r/2] = 0; // строка должна заканчиваться нулём
		} 
		else if (file.code_type == CODE_UTF8 || file.code_type == CODE_UTF8_BOM)
		{
	        DL_FsReadFile( buffer,  1,  file.size, file.handle, &r );
			if (r == 0) return RESULT_FAIL;
			buffer[r] = 0;
	        DL_Char_convUTF8toUCS2String(buffer,  r, file.buffer,  file.size*sizeof(WCHAR));
	    } 
		else 
		{
			
			DL_FsReadFile( buffer,  1,  file.size, file.handle, &r );
			if (r == 0) return RESULT_FAIL;
			buffer[r] = 0;
			DL_Char_convCP1251toUCS2String(buffer, r, file.buffer, file.size*sizeof(WCHAR));
		}
		dbg(" - read end");
		page_null=0;
	}
	file.cur_position = off_set;
	
	dbgf(" - Read %d b", r);
    return RESULT_OK;
}

// размер предидущей страницы в байтах
UINT32 SizePrevPage(WCHAR *str, UINT8 x, UINT8 y)
{
    GRAPHIC_POINT_T     anchor_point;
    WCHAR               wchr[2];
    UINT32              i, b=0;
    UINT16              str_width=x; // ширина строки    
    UINT16              h; // высота для текста
	
    h = bufd.h-12;
 

    anchor_point.x = x;
    anchor_point.y = y;

    
    for (i=u_strlen(str)-1; i > 0; i--) {

        wchr[0] = str[i];
        wchr[1] = 0;
		

        if (str_width + FontWidth() > bufd.w-12 || wchr[0] == '\n' ) {
            
            str_width = x;
            anchor_point.y += FontHeight();
            if (anchor_point.y + FontHeight() > h) break; // вышло за пределы экрана по высоте
            if (wchr[0] == ' ') { 
                 b+=Symbol2Byte(wchr[0]);;
                continue;
            }
        } 

            anchor_point.x = str_width;
            str_width += FontWidth();

        b+=Symbol2Byte(wchr[0]);;

    }

    dbgf("Draw %d bytes", b);
    return b; // возвращаем кол-во отрисованных байт
}
UINT32 DrawTextInFullDisplay_(WCHAR *str, UINT8 x, UINT8 y)
{
    GRAPHIC_POINT_T     anchor_point;
    WCHAR               wchr[2];
    UINT32              i,comment=0,comment_2=0,section=0,link=0,file_link=0,hex=0,nick=0,operator=0, b=0;
    UINT8              str_width=x; // ширина строки    
	
    anchor_point.x = x;
    anchor_point.y = y;

    for (i=0; i < u_strlen(str)+1; i++) {

        wchr[0] = str[i];
        wchr[1] = 0;

		
	        if (str_width + FontWidth() > 171 || wchr[0] == '\n' ) {
	            if (wchr[0] > 0x40 && str[i-1] > 0x40) {
	                anchor_point.x = str_width;
	                DrawText(L"-",  anchor_point.x, anchor_point.y, false);				 

	            }
	            str_width = 0;
	            anchor_point.y += FontHeight();
	            if (anchor_point.y + FontHeight()+2 > 220) break; // вышло за пределы экрана по высоте
	            if (wchr[0] == ' ') { 
	                 b+=Symbol2Byte(wchr[0]);
	                continue;
	            }
	        } 

			
            anchor_point.x = str_width;
            str_width += FontWidth();
			
			if (wchr[0] == '\n')
			anchor_point.x = x;
			
			b+=Symbol2Byte(wchr[0]);
	

		if (wchr[0] == '\n'){
			SetFgColor(Color.Lines);
			section=0;
			comment=0;
			link=0;
			file_link=0;
			hex=0;
		}
		if (str[i-1] == ']') 
		section=0;
		
		if (wchr[0] == ' '){
			SetFgColor(Color.Lines);
			link=0;
			file_link=0;
			hex=0;
			nick=0;
			operator=0;
		}
		
		if(str[i-1] == '*' && str[i] == '/')
		comment_2=0;
		
		if(wchr[0] == ';')
		comment=1;
		if(str[i] == '/' && str[i+1] == '*' )
		comment_2=1;
		
		if (wchr[0] == '[') 
		section=1;
		
		
		if(str[i] == 'h' && str[i+1] == 't' && str[i+2] == 't' && str[i+3] == 'p' && str[i+4] == ':' && str[i+5] == '/' )
		link=1;
		if(str[i] == 'f' && str[i+1] == 'i' && str[i+2] == 'l' && str[i+3] == 'e' && str[i+4] == ':' && str[i+5] == '/' )
		file_link=1;
		if(str[i] == '0' && str[i+1] == 'x' )
		hex=1;
		if(str[i] == 'b' && str[i+1] == 'a' && str[i+2] == 'a' && str[i+3] == 't' && str[i+4] == ' ' )
		nick=1;
		
		if(str[i] == 'i' && str[i+1] == 'f' && str[i+2] == ' ' ) //if
		operator=1;
		if(str[i] == 'e' && str[i+1] == 'l' && str[i+2] == 's' && str[i+3] == 'e' && str[i+4] == ' ') //else
		operator=1;
		if(str[i] == 'f' && str[i+1] == 'o' && str[i+2] == 'r' && str[i+3] == ' ') // for
		operator=1;
		if(str[i] == 'w' && str[i+1] == 'h' && str[i+2] == 'i' && str[i+3] == 'l' && str[i+4] == 'e' && str[i+5] == ' ') //while
		operator=1;
		if(str[i] == 'r' && str[i+1] == 'e' && str[i+2] == 't' && str[i+3] == 'u' && str[i+4] == 'r' && str[i+5] == 'n' && str[i+6] == ' ') //return
		operator=1;
		if(str[i] == 's' && str[i+1] == 'w' && str[i+2] == 'i' && str[i+3] == 't' && str[i+4] == 'c' && str[i+5] == 'h' && str[i+5] == ' ') // switch
		operator=1;
		if(str[i] == 'c' && str[i+1] == 'a' && str[i+2] == 's' && str[i+3] == 'e' && str[i+4] == ' ') // case
		operator=1;
		
		if(comment || comment_2)
		{
			SetFgColor(0x00A000);
		}
		else if(section)
		{
			SetFgColor(0x0000FF);
		}
		else if(link)
		{
			SetFgColor(0x0000FF);
		}
		else if(file_link)
		{
			SetFgColor(0x00FF00);
		}
		else if(hex)
		{
			SetFgColor(0xFFD400);
		}
		else if(nick)
		{
			SetFgColor(0x00C000);
		}
		else if(operator)
		{
			SetFgColor(0x0000FF);
		}
		else
		{
			if(!u_strcmp(wchr, L"="))
			SetFgColor(0xFF0000);
			if(wchr[0] > 0x2F && wchr[0] < 0x3A) 
			SetFgColor(0xFFE400);
		}
		
		DrawText(wchr,  anchor_point.x, anchor_point.y, false);	
		
		if(!comment || !section || !link || !file_link || !hex || !operator)
		SetFgColor(Color.Lines);

    }
	
    dbgf("Draw %d bytes", b);
    return b; // возвращаем кол-во отрисованных байт
}
#ifdef	DEBUG
static void	ReportPhoneInfo( void );
#endif	

#endif
