5 * Copyright (C) 2010-2011 Scott Smith
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "cselector.h"
25 CSelector::CSelector() : CBase(),
30 SetOneEntryValue (false),
31 SetAllEntryValue (false),
33 ExtractAllFiles (false),
34 DrawState_Title (true),
35 DrawState_About (true),
36 DrawState_Filter (true),
37 DrawState_FilePath (true),
38 DrawState_Index (true),
39 DrawState_ZipMode (true),
40 DrawState_Preview (true),
41 DrawState_ButtonL (true),
42 DrawState_ButtonR (true),
43 Mode (MODE_SELECT_ENTRY),
44 LastSelectedEntry (0),
65 ImageBackground (NULL),
67 ImageSelectPointer (NULL),
83 ConfigPath (DEF_CONFIG),
84 ProfilePath (DEF_PROFILE),
85 ZipListPath (DEF_ZIPLIST),
106 Fonts.resize( FONT_SIZE_TOTAL, NULL );
108 ButtonModesLeft.resize( BUTTONS_MAX_LEFT );
109 ButtonModesRight.resize( BUTTONS_MAX_RIGHT );
110 RectButtonsLeft.resize( BUTTONS_MAX_LEFT );
111 RectButtonsRight.resize( BUTTONS_MAX_RIGHT );
112 ImageButtons.resize( EVENT_TOTAL, NULL );
113 LabelButtons.resize( EVENT_TOTAL, "" );
115 LabelButtons.at(EVENT_ONE_UP) = BUTTON_LABEL_ONE_UP;
116 LabelButtons.at(EVENT_ONE_DOWN) = BUTTON_LABEL_ONE_DOWN;
117 LabelButtons.at(EVENT_PAGE_UP) = BUTTON_LABEL_PAGE_UP;
118 LabelButtons.at(EVENT_PAGE_DOWN) = BUTTON_LABEL_PAGE_DOWN;
119 LabelButtons.at(EVENT_DIR_UP) = BUTTON_LABEL_DIR_UP;
120 LabelButtons.at(EVENT_DIR_DOWN) = BUTTON_LABEL_DIR_DOWN;
121 LabelButtons.at(EVENT_ZIP_MODE) = BUTTON_LABEL_ZIP_MODE;
122 LabelButtons.at(EVENT_CFG_APP) = BUTTON_LABEL_CONFIG;
123 LabelButtons.at(EVENT_CFG_ITEM) = BUTTON_LABEL_EDIT;
124 LabelButtons.at(EVENT_SET_ONE) = BUTTON_LABEL_SET_ONE;
125 LabelButtons.at(EVENT_SET_ALL) = BUTTON_LABEL_SET_ALL;
126 LabelButtons.at(EVENT_BACK) = BUTTON_LABEL_BACK;
127 LabelButtons.at(EVENT_SELECT) = BUTTON_LABEL_SELECT;
128 LabelButtons.at(EVENT_QUIT) = BUTTON_LABEL_QUIT;
130 DisplayList.resize( MODE_TOTAL );
132 EventPressCount.resize( EVENT_TOTAL, EVENT_LOOPS_OFF );
133 EventReleased.resize( EVENT_TOTAL, false );
136 CSelector::~CSelector()
140 int8_t CSelector::Run( int32_t argc, char** argv )
147 ProcessArguments( argc, argv );
149 System.SetCPUClock( Config.CPUClock );
151 // Load video,input,profile resources
157 // Display and poll the user for a selection
160 selection = DisplayScreen();
162 // Setup a exec script for execution following termination of this application
165 if (RunExec( selection ))
170 else if (selection < -1)
181 CloseResources( result );
186 void CSelector::ProcessArguments( int argc, char** argv )
192 launcher = string(argv[0]);
193 Profile.LauncherName = launcher.substr( launcher.find_last_of('/')+1 );
194 Profile.LauncherPath = launcher.substr( 0, launcher.find_last_of('/')+1 );
195 if (Profile.LauncherPath.compare("./") == 0 || Profile.LauncherPath.length() == 0)
197 Profile.LauncherPath = string(getenv("PWD"))+"/";
201 Log( "Running from '%s'\n", launcher.c_str() );
203 Log( "Running from '%s' as '%s'\n", Profile.LauncherPath.c_str(), Profile.LauncherName.c_str() );
205 for (arg_index=0; arg_index<argc; arg_index++ )
207 argument = string(argv[arg_index]);
209 if (argument.compare( ARG_RESETGUI ) == 0)
211 Config.ResetGUI = true;
214 if (argument.compare( ARG_PROFILE ) == 0)
216 ProfilePath = string(argv[++arg_index]);
219 if (argument.compare( ARG_CONFIG ) == 0)
221 ConfigPath = string(argv[++arg_index]);
224 if (argument.compare( ARG_ZIPLIST ) == 0)
226 ZipListPath = string(argv[++arg_index]);
231 int8_t CSelector::OpenResources( void )
233 uint8_t button_index;
237 Log( "Loading config.\n" );
238 if (Config.Load( ConfigPath ))
240 Log( "Failed to load config\n" );
244 Log( "Loading ziplist.\n" );
245 if (Config.UseZipSupport == true && Profile.Minizip.LoadUnzipList( ZipListPath ))
247 Log( "Failed to load ziplist\n" );
251 // Initialize defaults, Video and Audio subsystems
252 Log( "Initializing SDL.\n" );
253 if (SDL_Init( SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_TIMER|SDL_INIT_JOYSTICK )==-1)
255 Log( "Failed to initialize SDL: %s.\n", SDL_GetError() );
258 Log( "SDL initialized.\n" );
261 flags = SCREEN_FLAGS;
262 if (Config.Fullscreen == true)
264 flags |= SDL_FULLSCREEN;
266 Screen = SDL_SetVideoMode( Config.ScreenWidth, Config.ScreenHeight, Config.ScreenDepth, flags );
269 Log( "Failed to %dx%dx%d video mode: %s\n", Config.ScreenWidth, Config.ScreenHeight, Config.ScreenDepth, SDL_GetError() );
273 // Refresh entire screen for the first frame
274 UpdateRect( 0, 0, Config.ScreenWidth, Config.ScreenHeight );
277 #if !defined(PANDORA) && !defined(X86)
278 Joystick = SDL_JoystickOpen(0);
279 if (Joystick == NULL)
281 Log( "Warning failed to open first joystick: %s\n", SDL_GetError() );
286 if (TTF_Init() == -1)
288 Log( "Failed to init TTF_Init: %s\n", TTF_GetError() );
293 Fonts.at(FONT_SIZE_SMALL) = TTF_OpenFont( Config.PathFont.c_str(), Config.FontSizes.at(FONT_SIZE_SMALL) );
294 if (!Fonts.at(FONT_SIZE_SMALL))
296 Log( "Failed to open small TTF_OpenFont: %s\n", TTF_GetError() );
299 Fonts.at(FONT_SIZE_MEDIUM) = TTF_OpenFont( Config.PathFont.c_str(), Config.FontSizes.at(FONT_SIZE_MEDIUM) );
300 if (!Fonts.at(FONT_SIZE_MEDIUM))
302 Log( "Failed to open medium TTF_OpenFont: %s\n", TTF_GetError() );
305 Fonts.at(FONT_SIZE_LARGE) = TTF_OpenFont( Config.PathFont.c_str(), Config.FontSizes.at(FONT_SIZE_LARGE) );
306 if (!Fonts.at(FONT_SIZE_LARGE))
308 Log( "Failed to open large TTF_OpenFont: %s\n", TTF_GetError() );
312 Log( "Loading profile.\n" );
313 if (Profile.Load( ProfilePath, Config.Delimiter ))
315 Log( "Failed to load profile\n" );
320 ImageBackground = LoadImage( Config.PathBackground );
321 for (button_index=0; button_index<Config.PathButtons.size(); button_index++)
323 ImageButtons.at(button_index) = LoadImage( Config.PathButtons.at(button_index) );
327 if (Config.ShowPointer==true)
329 ImagePointer = LoadImage( Config.PathPointer );
330 if (ImagePointer == NULL)
332 SDL_ShowCursor( SDL_ENABLE );
336 SDL_ShowCursor( SDL_DISABLE );
341 SDL_ShowCursor( SDL_DISABLE );
344 // List selector pointer
345 ImageSelectPointer = LoadImage( Config.PathSelectPointer );
346 if (ImageSelectPointer == NULL)
348 ImageSelectPointer = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_MEDIUM), ENTRY_ARROW, Config.Colors.at(COLOR_BLACK) );
352 text = string(APPNAME) + " " + string(APPVERSION);
353 if (Profile.TargetApp.length() > 0)
355 text += " for " + Profile.TargetApp;
357 ImageTitle = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_LARGE), text.c_str(), Config.Colors.at(Config.ColorFontFiles) );
358 if (ImageTitle == NULL)
360 Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() );
365 text = "Written by " + string(APPAUTHOR) + " " + string(APPCOPYRIGHT);
366 ImageAbout = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_SMALL), text.c_str(), Config.Colors.at(Config.ColorFontFiles) );
367 if (ImageAbout == NULL)
369 Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() );
377 void CSelector::CloseResources( int8_t result )
379 uint8_t button_index;
383 Config.Save( ConfigPath );
384 Profile.Save( ProfilePath, Config.Delimiter );
387 if (Config.UseZipSupport == true)
389 Profile.Minizip.SaveUnzipList( ZipListPath );
393 if (Joystick != NULL)
395 Log( "Closing SDL Joystick.\n" );
396 SDL_JoystickClose( Joystick );
401 Log( "Closing TTF fonts.\n" );
402 if (Fonts.at(FONT_SIZE_SMALL) != NULL)
404 TTF_CloseFont( Fonts.at(FONT_SIZE_SMALL) );
405 Fonts.at(FONT_SIZE_SMALL) = NULL;
407 if (Fonts.at(FONT_SIZE_MEDIUM) != NULL)
409 TTF_CloseFont( Fonts.at(FONT_SIZE_MEDIUM) );
410 Fonts.at(FONT_SIZE_MEDIUM) = NULL;
412 if (Fonts.at(FONT_SIZE_LARGE) != NULL)
414 TTF_CloseFont( Fonts.at(FONT_SIZE_LARGE) );
415 Fonts.at(FONT_SIZE_LARGE) = NULL;
419 FREE_IMAGE( ImageBackground );
420 FREE_IMAGE( ImagePointer );
421 FREE_IMAGE( ImageSelectPointer );
422 FREE_IMAGE( ImagePreview );
423 FREE_IMAGE( ImageTitle );
424 FREE_IMAGE( ImageAbout );
425 FREE_IMAGE( ImageFilePath );
426 FREE_IMAGE( ImageFilter );
427 FREE_IMAGE( ImageIndex );
428 FREE_IMAGE( ImageZipMode );
430 FREE_IMAGE( ImageDebug );
432 for (button_index=0; button_index<ImageButtons.size(); button_index++)
434 FREE_IMAGE( ImageButtons.at(button_index) );
437 Log( "Quitting TTF.\n" );
440 Log( "Quitting SDL.\n" );
443 // Flush all std buffers before exit
448 int16_t CSelector::DisplayScreen( void )
450 while (IsEventOff(EVENT_QUIT) == true && (IsEventOff(EVENT_SELECT) == true || Mode != MODE_SELECT_ENTRY) )
461 // Configure the buttons according to the mode
462 if (ConfigureButtons())
468 if (DisplaySelector())
477 if (IsEventOn( EVENT_QUIT ) == true)
479 // Detete any files exracted from zip
480 Profile.Minizip.DelUnzipFiles();
486 return DisplayList.at(MODE_SELECT_ENTRY).absolute;
490 void CSelector::UpdateRect( int16_t x, int16_t y, int16_t w, int16_t h )
494 if (Config.ScreenFlip == false)
500 Log( "ERROR: UpdateRect X was out of bounds\n" );
506 Log( "ERROR: UpdateRect Y was out of bounds\n" );
512 Log( "ERROR: UpdateRect X was out of bounds\n" );
518 Log( "ERROR: UpdateRect Y was out of bounds\n" );
521 if( x > Config.ScreenWidth )
523 x = Config.ScreenWidth-1;
524 Log( "ERROR: UpdateRect X was out of bounds\n" );
527 if( y > Config.ScreenHeight )
529 y = Config.ScreenHeight-1;
530 Log( "ERROR: UpdateRect Y was out of bounds\n" );
533 if( x + w > Config.ScreenWidth )
535 w = Config.ScreenWidth-x;
536 Log( "ERROR: UpdateRect W was out of bounds\n" );
539 if( y + h > Config.ScreenHeight )
541 h = Config.ScreenHeight-y;
542 Log( "ERROR: UpdateRect H was out of bounds\n" );
550 ScreenRectsDirty.push_back( rect );
554 void CSelector::UpdateScreen( void )
556 #if defined(DEBUG_FORCE_REDRAW)
560 if (SkipFrame == false && Redraw == true)
562 if (Config.ScreenFlip == true)
564 if (SDL_Flip( Screen ) != 0)
566 Log( "Failed to swap the buffers: %s\n", SDL_GetError() );
571 SDL_UpdateRects( Screen, ScreenRectsDirty.size(), &ScreenRectsDirty[0] );
579 if (SkipFrame == true)
588 ScreenRectsDirty.clear();
590 FrameEndTime = SDL_GetTicks();
591 FrameDelay = (MS_PER_SEC/FRAMES_PER_SEC) - (FrameEndTime - FrameStartTime);
593 #if defined(DEBUG_FPS)
594 LoopTimeAverage = (LoopTimeAverage + (FrameEndTime - FrameStartTime))/2;
599 if (FramesSkipped/FramesDrawn < FRAME_SKIP_RATIO)
603 else // Force a frame to be drawn
611 SDL_Delay( MIN(FrameDelay, MS_PER_SEC) );
613 FrameStartTime = SDL_GetTicks();
615 #if defined(DEBUG_FPS)
616 if (FrameStartTime - FrameCountTime >= MS_PER_SEC)
618 FrameCountTime = FrameStartTime;
619 FPSDrawn = FramesDrawn;
620 FPSSkip = FramesSkipped;
621 FPSSleep = FramesSleep;
626 cout << "DEBUG total " << i_to_a(FPSDrawn+FPSSkip+FPSSleep)
627 << " fps " << i_to_a(FPSDrawn) << " skip " << i_to_a(FPSSkip) << " slp " << i_to_a(FPSSleep)
628 << " loop " << i_to_a(LoopTimeAverage) << endl;
633 void CSelector::SelectMode( void )
641 case MODE_SELECT_ENTRY:
642 if (IsEventOn( EVENT_CFG_ITEM ) == true)
644 if (ItemsEntry.size()>0)
646 if (ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Type == TYPE_FILE )
647 // || (ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Type == TYPE_DIR && Profile.LaunchableDirs == true))
649 // Profile.ScanRomPlugins(Profile.FilePath+ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Name, ItemsRomOption);
650 // Per Rom Plugin selection. Find ROMCRC and Load Plugins for this rom
651 Mode = MODE_ROM_OPTION;
655 else if (IsEventOn( EVENT_CFG_APP ) == true)
657 Mode = MODE_SELECT_OPTION;
660 case MODE_SELECT_ARGUMENT:
661 if (IsEventOn( EVENT_BACK ) == true)
663 Mode = MODE_SELECT_ENTRY;
665 if (IsEventOn( EVENT_SELECT ) == true)
667 Mode = MODE_SELECT_VALUE;
670 case MODE_SELECT_VALUE:
671 if (IsEventOn( EVENT_BACK ) == true)
673 Mode = MODE_SELECT_ARGUMENT;
676 case MODE_SELECT_OPTION:
677 if (IsEventOn( EVENT_BACK ) == true)
679 Mode = MODE_SELECT_ENTRY;
681 if (IsEventOn( EVENT_SELECT ) == true)
683 WhichPlugin = DisplayList.at(MODE_SELECT_OPTION).absolute;
684 Mode = MODE_SELECT_PLUGIN;
687 case MODE_ROM_OPTION:
688 if (IsEventOn( EVENT_BACK ) == true)
690 Mode = MODE_SELECT_ENTRY;
692 if (IsEventOn( EVENT_SELECT ) == true)
694 WhichPlugin = DisplayList.at(MODE_ROM_OPTION).absolute;
695 Mode = MODE_ROM_PLUGIN;
698 case MODE_SELECT_PLUGIN:
699 if (IsEventOn( EVENT_BACK ) == true)
701 Mode = MODE_SELECT_OPTION;
703 if (IsEventOn( EVENT_SELECT ) == true)
705 Profile.SaveDef1Plugin(WhichPlugin, DisplayList.at(MODE_SELECT_PLUGIN).absolute);
706 Mode = MODE_SELECT_OPTION;
709 case MODE_ROM_PLUGIN:
710 if (IsEventOn( EVENT_BACK ) == true)
712 Mode = MODE_ROM_OPTION;
714 if (IsEventOn( EVENT_SELECT ) == true)
716 Profile.SaveRom1Plugin(WhichPlugin, ItemsRomPlugin[DisplayList.at(MODE_ROM_PLUGIN).absolute].Entry);
717 Mode = MODE_ROM_OPTION;
721 Mode = MODE_SELECT_ENTRY;
722 Log( "Error: Unknown Mode\n" );
726 if (Mode != old_mode)
728 DrawState_ButtonL = true;
729 DrawState_ButtonR = true;
734 int8_t CSelector::DisplaySelector( void )
736 SDL_Rect rect_pos = { Config.EntryXOffset, Config.EntryYOffset, 0 ,0 };
748 DrawState_Index = true;
753 if (Redraw == true || CurScrollPause != 0 || CurScrollSpeed != 0 || TextScrollOffset != 0)
755 if (Config.ScreenFlip == true)
757 DrawState_Title = true;
758 DrawState_About = true;
759 DrawState_Filter = true;
760 DrawState_FilePath = true;
761 DrawState_Index = true;
762 DrawState_ZipMode = true;
763 DrawState_Preview = true;
764 DrawState_ButtonL = true;
765 DrawState_ButtonR = true;
767 #if defined(DEBUG_DRAW_STATES)
771 << " " << i_to_a(DrawState_Title)
772 << " " << i_to_a(DrawState_About)
773 << " " << i_to_a(DrawState_Filter)
774 << " " << i_to_a(DrawState_FilePath)
775 << " " << i_to_a(DrawState_Index)
776 << " " << i_to_a(DrawState_ZipMode)
777 << " " << i_to_a(DrawState_Preview)
778 << " " << i_to_a(DrawState_ButtonL)
779 << " " << i_to_a(DrawState_ButtonR) << endl;
783 // Draw background or clear screen
786 // Draw text titles to the screen
787 if (DrawText( rect_pos ))
792 // Draw the buttons for touchscreen
793 if (DrawButtons( rect_pos ))
798 // Draw the names for the items for display
799 if (DrawNames( rect_pos ))
804 // Custom mouse pointer
805 if (Config.ShowPointer == true && ImagePointer != NULL)
807 ApplyImage( Mouse.x, Mouse.y, ImagePointer, Screen, NULL );
814 void CSelector::DirectoryUp( void )
816 if (Profile.FilePath.length() > 0)
818 if (Profile.FilePath.at( Profile.FilePath.length()-1) == '/')
820 Profile.FilePath.erase( Profile.FilePath.length()-1 );
822 Profile.FilePath = Profile.FilePath.substr( 0, Profile.FilePath.find_last_of('/', Profile.FilePath.length()-1) ) + '/';
823 DrawState_FilePath = true;
828 Log( "Error: Filepath is empty\n" );
832 void CSelector::DirectoryDown( void )
834 if (DisplayList.at(MODE_SELECT_ENTRY).absolute < (int16_t)ItemsEntry.size() )
836 if (ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Type == TYPE_DIR )
838 Profile.FilePath += ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Name + '/';
839 DrawState_FilePath = true;
842 EventPressCount.at(EVENT_SELECT) = EVENT_LOOPS_OFF;
847 Log( "Error: Item index of %d too large for size of scanitems %d\n", DisplayList.at(MODE_SELECT_ENTRY).absolute, ItemsEntry.size() );
851 void CSelector::ZipUp( void )
853 DrawState_FilePath = true;
854 DrawState_ZipMode = true;
855 DrawState_ButtonL = true;
857 Profile.ZipFile = "";
860 void CSelector::ZipDown( void )
862 DrawState_FilePath = true;
863 DrawState_ZipMode = true;
864 DrawState_ButtonL = true;
866 Profile.ZipFile = ItemsEntry.at(DisplayList.at(Mode).absolute).Name;
867 EventPressCount.at( EVENT_SELECT ) = EVENT_LOOPS_OFF;
870 void CSelector::RescanItems( void )
876 case MODE_SELECT_ENTRY:
877 Profile.ScanDir( Profile.FilePath, Config.ShowHidden, Config.UseZipSupport, ItemsEntry );
878 total = ItemsEntry.size();
880 case MODE_SELECT_ARGUMENT:
881 Profile.ScanEntry( ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute), ItemsArgument );
882 total = ItemsArgument.size();
884 case MODE_SELECT_VALUE:
885 Profile.ScanArgument( ItemsArgument.at(DisplayList.at(MODE_SELECT_ARGUMENT).absolute), ItemsValue );
886 total = ItemsValue.size();
888 case MODE_SELECT_OPTION:
889 //Profile.ScanOptions( ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute), ItemsArgument );
890 Profile.ScanDefPlugins( ItemsArgument );
891 total = ItemsArgument.size();
893 case MODE_ROM_OPTION:
894 //Profile.ScanOptions( ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute), ItemsArgument );
895 Profile.ScanRomPlugins(Profile.FilePath+ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Name, ItemsRomOption);
896 total = ItemsRomOption.size();
898 case MODE_SELECT_PLUGIN:
899 //Profile.ScanOptions( ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute), ItemsArgument );
900 Profile.ScanDef1Plugins( WhichPlugin, ItemsDefPlugin );
901 total = ItemsDefPlugin.size();
903 case MODE_ROM_PLUGIN:
904 //Profile.ScanOptions( ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute), ItemsArgument );
905 Profile.ScanRom1Plugins( WhichPlugin, ItemsRomPlugin );
906 total = ItemsRomPlugin.size();
910 Log( "Error: Unknown Mode\n" );
914 if (total > Config.MaxEntries)
916 RectEntries.resize( Config.MaxEntries );
920 RectEntries.resize( total );
922 ListNames.resize( RectEntries.size() );
924 DisplayList.at(Mode).absolute = 0;
925 DisplayList.at(Mode).relative = 0;
926 DisplayList.at(Mode).first = 0;
927 DisplayList.at(Mode).last = 0;
928 DisplayList.at(Mode).total = total;
931 void CSelector::PopulateList( void )
934 SelectionLimits( DisplayList.at( Mode ) );
938 case MODE_SELECT_ENTRY:
941 case MODE_SELECT_ARGUMENT:
944 case MODE_SELECT_VALUE:
947 case MODE_SELECT_OPTION:
950 case MODE_ROM_OPTION:
953 case MODE_SELECT_PLUGIN:
956 case MODE_ROM_PLUGIN:
960 Log( "Error: CSelector::PopulateList Unknown Mode\n" );
965 void CSelector::PopModeEntry( void )
970 for (i=0; i<ListNames.size(); i++)
972 index = DisplayList.at( MODE_SELECT_ENTRY ).first+i;
973 if (CheckRange( index, ItemsEntry.size() ))
975 ListNames.at(i).text.clear();
976 if (ItemsEntry.at(index).Entry >= 0)
978 ListNames.at(i).text = Profile.Entries.at(ItemsEntry.at(index).Entry).Alias;
980 if (ListNames.at(i).text.length() == 0)
982 ListNames.at(i).text = ItemsEntry.at(index).Name;
985 if (Config.ShowExts == false)
987 ListNames.at(i).text = ListNames.at(i).text.substr( 0, ListNames.at(i).text.find_last_of(".") );
989 ListNames.at(i).text = ListNames.at(i).text;
991 if (index == DisplayList.at(Mode).absolute)
993 ListNames.at(i).font = FONT_SIZE_LARGE;
994 LoadPreview( ListNames.at(i).text ); // Load preview
998 ListNames.at(i).font = FONT_SIZE_MEDIUM;
1001 ListNames.at(i).color = Config.ColorFontFiles;
1002 if (ItemsEntry.at(index).Type == TYPE_DIR)
1004 ListNames.at(i).color = Config.ColorFontFolders;
1009 Log( "Error: CSelector::PopulateModeSelectEntry Index Error\n" );
1014 void CSelector::PopModeArgument( void )
1019 for (i=0; i<ListNames.size(); i++)
1021 index = DisplayList.at(MODE_SELECT_ARGUMENT).first+i;
1023 if (CheckRange( index, ItemsArgument.size() ))
1025 ListNames.at(i).text = ItemsArgument.at(index).Name;
1027 if (i == DisplayList.at(MODE_SELECT_ARGUMENT).absolute)
1029 ListNames.at(i).font = FONT_SIZE_LARGE;
1033 ListNames.at(i).font = FONT_SIZE_MEDIUM;
1036 ListNames.at(i).color = Config.ColorFontFiles;
1040 Log( "Error: PopModeArgument index is out of range\n" );
1045 void CSelector::PopModeValue( void )
1051 listoption_t argument;
1053 if (CheckRange(DisplayList.at(MODE_SELECT_ARGUMENT).absolute, ItemsArgument.size() ))
1055 argument = ItemsArgument.at(DisplayList.at(MODE_SELECT_ARGUMENT).absolute);
1057 for (i=0; i<ListNames.size(); i++)
1059 index = DisplayList.at(MODE_SELECT_VALUE).first+i;
1061 if (CheckRange( index, ItemsValue.size() ))
1063 ListNames.at(i).text = ItemsValue.at(index);
1065 if (index == DisplayList.at(MODE_SELECT_VALUE).absolute)
1067 ListNames.at(i).font = FONT_SIZE_LARGE;
1071 ListNames.at(i).font = FONT_SIZE_MEDIUM;
1074 // Detect the default value
1075 if (ItemsArgument.at(DisplayList.at(MODE_SELECT_ARGUMENT).absolute).Command >= 0)
1077 if (SetAllEntryValue == true)
1079 Profile.Commands.at(argument.Command).Arguments.at(argument.Argument).Default = DisplayList.at(MODE_SELECT_VALUE).absolute;
1081 defvalue = Profile.Commands.at(argument.Command).Arguments.at(argument.Argument).Default;
1085 if (SetAllEntryValue == true)
1087 Profile.Extensions.at(argument.Extension).Arguments.at(argument.Argument).Default = DisplayList.at(MODE_SELECT_VALUE).absolute;
1089 defvalue = Profile.Extensions.at(argument.Extension).Arguments.at(argument.Argument).Default;
1091 if (index==defvalue)
1093 ListNames.at(i).text += '*';
1096 // Set the color for the selected item for the entry
1097 ListNames.at(i).color = Config.ColorFontFiles;
1098 if (ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry<0)
1100 // A custom value has been selected, so create a new entry
1101 if (SetOneEntryValue == true)
1103 entry = Profile.AddEntry( argument, ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Name );
1106 ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry = entry;
1110 Log( "Error: Could not create new entry\n" );
1113 else if (index==defvalue)
1115 ListNames.at(i).color = COLOR_RED;
1119 if (ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry>=0)
1121 if (ItemsArgument.at(DisplayList.at(MODE_SELECT_ARGUMENT).absolute).Command >= 0)
1123 if (SetOneEntryValue == true || SetAllEntryValue == true)
1125 Profile.Entries.at(ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry).CmdValues.at(argument.Command+argument.Argument) = DisplayList.at(MODE_SELECT_VALUE).absolute;
1127 if (index == Profile.Entries.at(ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry).CmdValues.at(argument.Command+argument.Argument))
1129 ListNames.at(i).color = COLOR_RED;
1134 if (SetOneEntryValue == true || SetAllEntryValue == true)
1136 Profile.Entries.at(ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry).ArgValues.at(argument.Argument) = DisplayList.at(MODE_SELECT_VALUE).absolute;
1138 if (index == Profile.Entries.at(ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry).ArgValues.at(argument.Argument))
1140 ListNames.at(i).color = COLOR_RED;
1147 Log( "Error: PopModeValue index is out of range\n" );
1153 Log( "Error: PopModeValue argument index out of range\n" );
1157 void CSelector::PopModeOption( void )
1162 for (i=0; i<ListNames.size(); i++)
1164 index = DisplayList.at(MODE_SELECT_OPTION).first+i;
1166 if (CheckRange( index, ItemsArgument.size() ))
1168 ListNames.at(i).text = ItemsArgument.at(index).Name;
1170 if (i == DisplayList.at(MODE_SELECT_OPTION).absolute)
1172 ListNames.at(i).font = FONT_SIZE_LARGE;
1176 ListNames.at(i).font = FONT_SIZE_MEDIUM;
1179 ListNames.at(i).color = Config.ColorFontFiles;
1183 Log( "Error: PopModeOption index is out of range\n" );
1188 void CSelector::PopModePlugin( void )
1193 for (i=0; i<ListNames.size(); i++)
1195 index = DisplayList.at(MODE_SELECT_PLUGIN).first+i;
1197 if (CheckRange( index, ItemsDefPlugin.size() ))
1199 ListNames.at(i).text = ItemsDefPlugin.at(index).Name;
1201 if (i == DisplayList.at(MODE_SELECT_PLUGIN).absolute)
1203 ListNames.at(i).font = FONT_SIZE_LARGE;
1207 ListNames.at(i).font = FONT_SIZE_MEDIUM;
1210 if (ItemsDefPlugin.at(index).Type == TYPE_DIR)
1211 ListNames.at(i).color = COLOR_RED;
1213 ListNames.at(i).color = Config.ColorFontFiles;
1217 Log( "Error: PopModePlugin index is out of range\n" );
1221 void CSelector::PopModeRomOption( void )
1226 for (i=0; i<ListNames.size(); i++)
1228 index = DisplayList.at(MODE_ROM_OPTION).first+i;
1230 if (CheckRange( index, ItemsRomOption.size() ))
1232 ListNames.at(i).text = ItemsRomOption.at(index).Name;
1234 if (i == DisplayList.at(MODE_ROM_OPTION).absolute)
1236 ListNames.at(i).font = FONT_SIZE_LARGE;
1240 ListNames.at(i).font = FONT_SIZE_MEDIUM;
1243 ListNames.at(i).color = Config.ColorFontFiles;
1247 Log( "Error: PopModeOption index is out of range\n" );
1252 void CSelector::PopModeRomPlugin( void )
1257 for (i=0; i<ListNames.size(); i++)
1259 index = DisplayList.at(MODE_ROM_PLUGIN).first+i;
1261 if (CheckRange( index, ItemsRomPlugin.size() ))
1263 ListNames.at(i).text = ItemsRomPlugin.at(index).Name;
1265 if (i == DisplayList.at(MODE_ROM_PLUGIN).absolute)
1267 ListNames.at(i).font = FONT_SIZE_LARGE;
1271 ListNames.at(i).font = FONT_SIZE_MEDIUM;
1274 if (ItemsRomPlugin.at(index).Type == TYPE_DIR)
1275 ListNames.at(i).color = COLOR_RED;
1277 ListNames.at(i).color = Config.ColorFontFiles;
1281 Log( "Error: PopModePlugin index is out of range\n" );
1286 void CSelector::LoadPreview( const string& name )
1289 SDL_Surface* preview = NULL;
1291 if (ImagePreview != NULL)
1293 DrawState_Preview = true;
1296 FREE_IMAGE( ImagePreview );
1298 filename = Config.PreviewsPath + "/" + name.substr( 0, name.find_last_of(".")) + ".png";
1299 preview = LoadImage( filename.c_str() );
1300 if (preview != NULL)
1302 ImagePreview = ScaleSurface( preview, Config.PreviewWidth, Config.PreviewHeight );
1303 FREE_IMAGE( preview );
1304 DrawState_Preview = true;
1308 int8_t CSelector::DrawNames( SDL_Rect& location )
1310 uint16_t entry_index;
1311 uint16_t startx, starty;
1314 SDL_Surface* text_surface = NULL;
1316 if (Config.AutoLayout == false)
1318 location.x = Config.PosX_ListNames;
1319 location.y = Config.PosY_ListNames;
1322 startx = location.x;
1323 starty = location.y;
1325 if (ListNames.size() <= 0)
1327 // Empty directories or zip files
1328 if (Config.UseZipSupport == true && Profile.ZipFile.length() > 0)
1330 text_surface = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_MEDIUM), EMPTY_ZIP_LABEL, Config.Colors.at(COLOR_BLACK) );
1334 text_surface = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_MEDIUM), EMPTY_DIR_LABEL, Config.Colors.at(COLOR_BLACK) );
1337 if (text_surface != NULL)
1339 location.x += ImageSelectPointer->w;
1343 rect_clip.w = Config.DisplayListMaxWidth-location.x;
1344 rect_clip.h = text_surface->h;
1346 ApplyImage( location.x, location.y, text_surface, Screen, &rect_clip );
1348 ListNameHeight = MAX(ListNameHeight, location.y+text_surface->h );
1349 location.x -= ImageSelectPointer->w;
1350 location.y += text_surface->h + Config.EntryYDelta;
1352 FREE_IMAGE( text_surface );
1356 Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() );
1362 for (entry_index=0; entry_index<ListNames.size(); entry_index++)
1366 // Draw the selector pointer
1367 if (entry_index == DisplayList.at(Mode).relative)
1369 ApplyImage( location.x, location.y, ImageSelectPointer, Screen, NULL );
1371 // Reset scroll settings
1372 if (entry_index != LastSelectedEntry)
1376 TextScrollOffset = 0;
1377 TextScrollDir = true;
1379 LastSelectedEntry = entry_index;
1382 text_surface = TTF_RenderText_Solid( Fonts.at(ListNames.at(entry_index).font), ListNames.at(entry_index).text.c_str(), Config.Colors.at(ListNames.at(entry_index).color) );
1384 if (text_surface != NULL)
1386 location.x += ImageSelectPointer->w;
1387 RectEntries.at(entry_index).x = location.x;
1388 RectEntries.at(entry_index).y = location.y;
1389 RectEntries.at(entry_index).w = text_surface->w;
1390 RectEntries.at(entry_index).h = text_surface->h;
1392 if (text_surface->w > (Config.DisplayListMaxWidth-location.x) )
1394 RectEntries.at(entry_index).w = Config.DisplayListMaxWidth-location.x;
1396 if (Config.TextScrollOption == true && DisplayList.at(Mode).relative == entry_index)
1398 offset = TextScrollOffset;
1400 if (CurScrollPause > 1)
1403 if (CurScrollPause >= Config.ScrollPauseSpeed)
1411 if (CurScrollSpeed >= Config.ScrollSpeed)
1414 if (TextScrollDir == true)
1416 TextScrollOffset += Config.ScreenRatioW;
1420 TextScrollOffset -= Config.ScreenRatioW;
1425 if (RectEntries.at(entry_index).w+TextScrollOffset >= text_surface->w)
1427 TextScrollDir = false;
1430 else if (TextScrollOffset <= 0)
1432 TextScrollDir = true;
1439 rect_clip.w = Config.DisplayListMaxWidth-location.x;
1440 rect_clip.h = text_surface->h;
1441 rect_clip.x = offset;
1444 ApplyImage( location.x, location.y, text_surface, Screen, &rect_clip );
1446 ListNameHeight = MAX(ListNameHeight, location.y+text_surface->h );
1447 location.x -= ImageSelectPointer->w;
1448 location.y += text_surface->h + Config.EntryYDelta;
1450 FREE_IMAGE( text_surface );
1454 Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() );
1460 UpdateRect( startx, starty, Config.DisplayListMaxWidth-startx, ListNameHeight-starty );
1465 void CSelector::SelectionLimits( item_pos_t& pos )
1467 if (pos.absolute <= pos.first)
1470 if (pos.absolute < 0)
1475 pos.first = pos.absolute;
1476 if (pos.total < Config.MaxEntries)
1478 pos.last = (pos.total-1);
1482 pos.last = pos.absolute+(Config.MaxEntries-1);
1485 else if (pos.absolute >= pos.last)
1487 if (pos.absolute > (int16_t)(pos.total-1))
1489 pos.absolute = (pos.total-1);
1492 pos.first = pos.absolute-(Config.MaxEntries-1);
1493 pos.last = pos.absolute;
1494 if (pos.total < Config.MaxEntries)
1496 pos.relative = (pos.total-1);
1500 pos.relative = Config.MaxEntries-1;
1510 void CSelector::DrawBackground( void )
1512 if (ImageBackground != NULL)
1514 ApplyImage( 0, 0, ImageBackground, Screen, NULL );
1518 SDL_FillRect( Screen, NULL, rgb_to_int(Config.Colors.at(Config.ColorBackground)) );
1522 int8_t CSelector::ConfigureButtons( void )
1526 // Common button mappings
1527 ButtonModesLeft.at(0) = EVENT_ONE_UP;
1528 ButtonModesLeft.at(1) = EVENT_PAGE_UP;
1529 ButtonModesLeft.at(2) = EVENT_PAGE_DOWN;
1530 ButtonModesLeft.at(3) = EVENT_ONE_DOWN;
1532 ButtonModesRight.at(0) = EVENT_QUIT;
1534 // Specific button mappings
1537 case MODE_SELECT_ENTRY:
1538 ButtonModesLeft.at(4) = EVENT_DIR_UP;
1539 ButtonModesLeft.at(5) = EVENT_DIR_DOWN;
1540 if (Config.UseZipSupport == true && Profile.ZipFile.length() > 0)
1542 ButtonModesLeft.at(6) = EVENT_ZIP_MODE;
1546 ButtonModesLeft.at(6) = EVENT_NONE;
1549 ButtonModesRight.at(1) = EVENT_SELECT;
1550 ButtonModesRight.at(2) = EVENT_CFG_ITEM;
1551 ButtonModesRight.at(3) = EVENT_NONE;
1552 ButtonModesRight.at(3) = EVENT_CFG_APP; // TODO
1554 case MODE_SELECT_ARGUMENT:
1555 ButtonModesLeft.at(4) = EVENT_NONE;
1556 ButtonModesLeft.at(5) = EVENT_NONE;
1557 ButtonModesLeft.at(6) = EVENT_NONE;
1559 ButtonModesRight.at(1) = EVENT_BACK;
1560 ButtonModesRight.at(2) = EVENT_SELECT;
1561 ButtonModesRight.at(3) = EVENT_NONE;
1563 case MODE_SELECT_VALUE:
1564 ButtonModesLeft.at(4) = EVENT_NONE;
1565 ButtonModesLeft.at(5) = EVENT_NONE;
1566 ButtonModesLeft.at(6) = EVENT_NONE;
1568 ButtonModesRight.at(1) = EVENT_BACK;
1569 ButtonModesRight.at(2) = EVENT_SET_ALL;
1570 ButtonModesRight.at(3) = EVENT_SET_ONE;
1572 case MODE_SELECT_OPTION:
1573 ButtonModesLeft.at(4) = EVENT_NONE;
1574 ButtonModesLeft.at(5) = EVENT_NONE;
1575 ButtonModesLeft.at(6) = EVENT_NONE;
1577 ButtonModesRight.at(1) = EVENT_BACK;
1578 ButtonModesRight.at(2) = EVENT_SELECT;
1579 ButtonModesRight.at(3) = EVENT_NONE;
1581 case MODE_SELECT_PLUGIN:
1582 ButtonModesLeft.at(4) = EVENT_NONE;
1583 ButtonModesLeft.at(5) = EVENT_NONE;
1584 ButtonModesLeft.at(6) = EVENT_NONE;
1586 ButtonModesRight.at(1) = EVENT_BACK;
1587 ButtonModesRight.at(2) = EVENT_SELECT;
1588 ButtonModesRight.at(3) = EVENT_NONE;
1590 case MODE_ROM_OPTION:
1591 ButtonModesLeft.at(4) = EVENT_NONE;
1592 ButtonModesLeft.at(5) = EVENT_NONE;
1593 ButtonModesLeft.at(6) = EVENT_NONE;
1595 ButtonModesRight.at(1) = EVENT_BACK;
1596 ButtonModesRight.at(2) = EVENT_SELECT;
1597 ButtonModesRight.at(3) = EVENT_NONE;
1599 case MODE_ROM_PLUGIN:
1600 ButtonModesLeft.at(4) = EVENT_NONE;
1601 ButtonModesLeft.at(5) = EVENT_NONE;
1602 ButtonModesLeft.at(6) = EVENT_NONE;
1604 ButtonModesRight.at(1) = EVENT_BACK;
1605 ButtonModesRight.at(2) = EVENT_SELECT;
1606 ButtonModesRight.at(3) = EVENT_NONE;
1609 Log( "Error: Unknown Mode\n" );
1614 // Overides for button driven by config options
1615 for (i=0; i<ButtonModesLeft.size(); i++ )
1617 if (Config.ButtonModesLeftEnable.at(i) == false)
1619 ButtonModesLeft.at(i) = EVENT_NONE;
1623 for (i=0; i<ButtonModesRight.size(); i++ )
1625 if (Config.ButtonModesRightEnable.at(i) == false)
1627 ButtonModesRight.at(i) = EVENT_NONE;
1634 int8_t CSelector::DrawButtons( SDL_Rect& location )
1639 if (Config.AutoLayout == false)
1641 location.x = Config.PosX_ButtonLeft;
1642 location.y = Config.PosY_ButtonLeft;
1645 // Draw buttons on left
1646 if (DrawState_ButtonL == true)
1648 for (button=0; button<BUTTONS_MAX_LEFT; button++)
1650 RectButtonsLeft.at(button).x = location.x;
1651 RectButtonsLeft.at(button).y = location.y+(Config.ButtonHeightLeft*button)+(Config.EntryYOffset*button);
1652 RectButtonsLeft.at(button).w = Config.ButtonWidthLeft;
1653 RectButtonsLeft.at(button).h = Config.ButtonHeightLeft;
1655 if (ButtonModesLeft.at(button) != EVENT_NONE)
1657 if (DrawButton( ButtonModesLeft.at(button), Fonts.at(FONT_SIZE_LARGE), RectButtonsLeft.at(button) ))
1662 UpdateRect( RectButtonsLeft.at(button).x, RectButtonsLeft.at(button).y, RectButtonsLeft.at(button).w, RectButtonsLeft.at(button).h );
1664 DrawState_ButtonL = false;
1666 location.x += Config.ButtonWidthLeft + Config.EntryXOffset;
1668 // Draw buttons on right
1669 if (DrawState_ButtonR == true)
1671 for (button=0; button<BUTTONS_MAX_RIGHT; button++)
1673 if (Config.AutoLayout == false)
1675 RectButtonsRight.at(button).x = Config.PosX_ButtonRight;
1676 RectButtonsRight.at(button).y = Config.PosY_ButtonRight-(Config.ButtonHeightRight*(button+1))-(Config.EntryYOffset*(button+3));
1680 RectButtonsRight.at(button).x = Config.ScreenWidth-Config.ButtonWidthRight-Config.EntryXOffset;
1681 RectButtonsRight.at(button).y = Config.ScreenHeight-(Config.ButtonHeightRight*(button+1))-(Config.EntryYOffset*(button+3));
1683 RectButtonsRight.at(button).w = Config.ButtonWidthRight;
1684 RectButtonsRight.at(button).h = Config.ButtonHeightRight;
1686 if (ButtonModesRight.at(button) != EVENT_NONE)
1688 if (DrawButton( ButtonModesRight.at(button), Fonts.at(FONT_SIZE_LARGE), RectButtonsRight.at(button) ))
1693 UpdateRect( RectButtonsRight.at(button).x, RectButtonsRight.at(button).y, RectButtonsRight.at(button).w, RectButtonsRight.at(button).h );
1695 DrawState_ButtonR = false;
1698 //Display the preview graphic
1699 if (Mode == MODE_SELECT_ENTRY && DrawState_Preview == true)
1701 preview.x = Config.ScreenWidth-Config.PreviewWidth-Config.EntryXOffset;
1702 preview.y = Config.ScreenHeight-Config.PreviewHeight-(Config.ButtonHeightRight*3)-(Config.EntryYOffset*6);
1704 if (ImagePreview != NULL)
1706 ApplyImage( preview.x, preview.y, ImagePreview, Screen, NULL );
1708 UpdateRect( preview.x, preview.y, Config.PreviewWidth, Config.PreviewHeight );
1709 DrawState_Preview = false;
1715 int8_t CSelector::DrawButton( uint8_t button, TTF_Font* font, SDL_Rect& location )
1717 SDL_Surface* text_surface = NULL;
1720 if (ImageButtons.at(button) != NULL)
1722 ApplyImage( location.x, location.y, ImageButtons.at(button), Screen, NULL );
1726 SDL_FillRect( Screen, &location, rgb_to_int(Config.Colors.at(Config.ColorButton)) );
1730 if (Config.ShowLabels == true)
1732 text_surface = TTF_RenderText_Solid( font, LabelButtons.at(button).c_str(), Config.Colors.at(Config.ColorFontButton) );
1734 rect_text.x = location.x + ((location.w-text_surface->w)/2);
1735 rect_text.y = location.y + ((location.h-text_surface->h)/2);
1737 if (text_surface != NULL)
1739 ApplyImage( rect_text.x, rect_text.y, text_surface, Screen, NULL );
1741 FREE_IMAGE( text_surface );
1745 Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() );
1752 int8_t CSelector::DrawText( SDL_Rect& location )
1756 int16_t prev_height;
1764 if (Config.AutoLayout == false)
1766 location.x = Config.PosX_Title;
1767 location.y = Config.PosY_Title;
1771 if (ImageTitle != NULL)
1773 if (DrawState_Title == true)
1775 ApplyImage( location.x, location.y, ImageTitle, Screen, NULL );
1776 UpdateRect( location.x, location.y, ImageTitle->w, ImageTitle->h );
1777 DrawState_Title = false;
1779 location.y += ImageTitle->h + Config.EntryYDelta;
1782 // Entry Filter and Filepath (they can overlap so both are drawn when either change)
1783 if (Mode == MODE_SELECT_ENTRY)
1785 if (DrawState_FilePath == true || DrawState_Filter == true )
1788 if (ImageFilter != NULL)
1790 prev_width = ImageFilter->w;
1791 prev_height = ImageFilter->h;
1798 max_height = prev_height;
1800 FREE_IMAGE( ImageFilter );
1802 if (Profile.EntryFilter.length() > 0)
1804 ImageFilter = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_MEDIUM), Profile.EntryFilter.c_str(), Config.Colors.at(Config.ColorFontFiles) );
1805 if (ImageFilter != NULL)
1809 clip.w = Config.FilePathMaxWidth;
1810 clip.h = ImageFilter->h;
1811 if (ImageFilter->w > Config.FilePathMaxWidth)
1813 clip.x = ImageFilter->w-Config.FilePathMaxWidth;
1816 location.x = Config.ScreenWidth - ImageFilter->w - Config.EntryXOffset;
1818 ApplyImage( location.x, location.y, ImageFilter, Screen, &clip );
1820 max_height = MAX( max_height, ImageFilePath->h );
1824 Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() );
1828 location.x = Config.EntryXOffset;
1831 if (ImageFilePath != NULL)
1833 prev_width = ImageFilePath->w;
1834 prev_height = ImageFilePath->h;
1841 max_height = MAX( max_height, prev_height );
1843 FREE_IMAGE(ImageFilePath);
1845 text = Profile.FilePath;
1846 if (Profile.ZipFile.length())
1848 text += "->" + Profile.ZipFile;
1851 ImageFilePath = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_MEDIUM), text.c_str(), Config.Colors.at(Config.ColorFontFiles) );
1852 if (ImageFilePath != NULL)
1856 clip.w = Config.FilePathMaxWidth;
1857 clip.h = ImageFilePath->h;
1859 if (ImageFilePath->w > Config.FilePathMaxWidth)
1861 clip.x = ImageFilePath->w-Config.FilePathMaxWidth;
1864 ApplyImage( location.x, location.y, ImageFilePath, Screen, &clip );
1866 max_height = MAX( max_height, ImageFilePath->h );
1870 Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() );
1874 UpdateRect( 0, location.y, Config.ScreenWidth, max_height );
1876 DrawState_FilePath = false;
1877 DrawState_Filter = false;
1881 if (ImageFilePath != NULL)
1883 location.y += ImageFilePath->h + Config.EntryYOffset;
1887 if (ImageAbout != NULL)
1889 if (DrawState_About == true)
1891 box.x = Config.ScreenWidth - ImageAbout->w - Config.EntryXOffset;
1892 box.y = Config.ScreenHeight - ImageAbout->h - Config.EntryYOffset;
1893 ApplyImage( box.x, box.y, ImageAbout, Screen, NULL );
1894 UpdateRect( box.x, box.y, ImageAbout->w, ImageAbout->h );
1895 DrawState_About = false;
1902 case MODE_SELECT_ENTRY:
1903 total = ItemsEntry.size();
1905 case MODE_SELECT_ARGUMENT: // fall through
1906 case MODE_SELECT_OPTION:
1907 total = ItemsArgument.size();
1909 case MODE_SELECT_VALUE:
1910 total = ItemsValue.size();
1912 case MODE_SELECT_PLUGIN:
1913 total = ItemsDefPlugin.size();
1917 text = "Error: Unknown mode";
1922 if (DrawState_Index == true)
1924 if (ImageIndex != NULL)
1926 prev_width = ImageIndex->w;
1927 prev_height = ImageIndex->h;
1935 FREE_IMAGE( ImageIndex );
1940 text = i_to_a(DisplayList.at(Mode).absolute+1) + " of " + i_to_a(total);
1942 ImageIndex = TTF_RenderText_Solid(Fonts.at(FONT_SIZE_SMALL), text.c_str(), Config.Colors.at(Config.ColorFontFiles));
1944 if (ImageIndex != NULL)
1946 box.x = Config.EntryXOffset;
1947 box.y = Config.ScreenHeight - ImageIndex->h - Config.EntryYOffset;
1949 ApplyImage( box.x, box.y, ImageIndex, Screen, NULL );
1950 UpdateRect( box.x, box.y, MAX(ImageIndex->w, prev_width), MAX(ImageIndex->h, prev_height) );
1954 Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError());
1957 DrawState_Index = false;
1960 // Zip extract option
1961 if (DrawState_ZipMode == true)
1963 if (Config.UseZipSupport == true && Profile.ZipFile.length() > 0)
1965 if (ImageZipMode != NULL)
1967 prev_width = ImageZipMode->w;
1968 prev_height = ImageZipMode->h;
1976 FREE_IMAGE( ImageZipMode );
1978 if (ExtractAllFiles == true)
1980 text = "Extract All";
1984 text = "Extract Selection";
1987 ImageZipMode = TTF_RenderText_Solid(Fonts.at(FONT_SIZE_SMALL), text.c_str(), Config.Colors.at(Config.ColorFontFiles));
1988 if (ImageZipMode == NULL)
1990 Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError());
1995 if (ImageZipMode != NULL)
1997 box.x = 5*Config.EntryXOffset;
1998 box.y = Config.ScreenHeight - ImageZipMode->h - Config.EntryYOffset;
2000 if (Config.UseZipSupport == true && Profile.ZipFile.length() > 0)
2002 ApplyImage( box.x, box.y, ImageZipMode, Screen, NULL );
2004 UpdateRect( box.x, box.y, MAX(ImageZipMode->w, prev_width), MAX(ImageZipMode->h, prev_height) );
2006 DrawState_ZipMode = false;
2010 if (ImageDebug != NULL)
2012 prev_width = ImageDebug->w;
2013 prev_height = ImageDebug->h;
2021 FREE_IMAGE( ImageDebug );
2023 text = "DEBUG abs " + i_to_a(DisplayList.at(Mode).absolute) + " rel " + i_to_a(DisplayList.at(Mode).relative)
2024 + " F " + i_to_a(DisplayList.at(Mode).first) + " L " + i_to_a(DisplayList.at(Mode).last)
2025 + " T " + i_to_a(DisplayList.at(Mode).total)
2026 + " fps " + i_to_a(FPSDrawn) + " skp " + i_to_a(FPSSkip) + " slp " + i_to_a(FPSSleep)
2027 + " lp " + i_to_a(LoopTimeAverage);
2029 ImageDebug = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_SMALL), text.c_str(), Config.Colors.at(Config.ColorFontFiles) );
2031 if (ImageDebug != NULL)
2033 box.x = Config.EntryXOffset;
2034 box.y = Config.ScreenHeight - ImageDebug->h;
2036 ApplyImage( box.x, box.y, ImageDebug, Screen, NULL );
2037 UpdateRect( box.x, box.y, MAX(ImageDebug->w, prev_width), MAX(ImageDebug->h, prev_height) );
2041 Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() );
2049 int8_t CSelector::RunExec( uint16_t selection )
2059 string cmdpath, cmdname;
2060 entry_t* entry = NULL;
2061 argforce_t* argforce = NULL;
2062 exeforce_t* exeforce = NULL;
2063 argument_t* argument = NULL;
2065 // Find a entry for argument values
2066 entry_found = false;
2068 if (!CheckRange( selection, ItemsEntry.size() ))
2070 Log( "Error: RunExec selection is out of range\n" );
2074 if (ItemsEntry.at(selection).Entry >= 0)
2076 entry = &Profile.Entries.at(ItemsEntry.at(selection).Entry);
2080 // Find a executable for file extension
2081 filename = ItemsEntry.at(selection).Name;
2082 if (ItemsEntry.at(selection).Type == TYPE_DIR)
2084 extension = EXT_DIRS;
2088 extension = filename.substr( filename.find_last_of(".")+1 );
2091 ext_index = Profile.FindExtension( extension );
2093 if (CheckRange( ext_index, Profile.Extensions.size() ))
2098 if (Config.UseZipSupport == true && Profile.ZipFile.length() > 0)
2100 mkdir( Config.ZipPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
2101 if (ExtractAllFiles == true) // Extract all
2103 Profile.Minizip.ExtractFiles( Profile.FilePath + Profile.ZipFile, Config.ZipPath );
2107 Profile.Minizip.ExtractFile( Profile.FilePath + Profile.ZipFile, Config.ZipPath, filename );
2110 filepath = Config.ZipPath + "/";
2114 filepath = Profile.FilePath;
2119 for (i=0; i<Profile.Commands.size(); i++)
2121 command += "cd " + Profile.Commands.at(i).Path + "; ";
2122 command += Profile.Commands.at(i).Command;
2124 for (j=0; j<Profile.Commands.at(i).Arguments.size(); j++)
2126 if (Profile.Commands.at(i).Arguments.at(j).Flag.compare(VALUE_NOVALUE) != 0)
2128 command += " " + Profile.Commands.at(i).Arguments.at(j).Flag;
2131 if (Profile.Commands.at(i).Arguments.at(j).Flag.compare(VALUE_FLAGONLY) !=0 )
2133 if (entry_found==true)
2135 command += " " + Profile.Commands.at(i).Arguments.at(j).Values.at(entry->CmdValues.at(j));
2139 command += " " + Profile.Commands.at(i).Arguments.at(j).Values.at(Profile.Commands.at(i).Arguments.at(j).Default);
2147 cmdpath = Profile.Extensions.at(ext_index).exePath;
2148 cmdname = Profile.Extensions.at(ext_index).exeName;
2149 for (j=0; j<Profile.Extensions.at(ext_index).ExeForces.size(); j++)
2151 exeforce = &Profile.Extensions.at(ext_index).ExeForces.at(j);
2152 for (k=0; k<exeforce->Files.size(); k++)
2154 if (exeforce->Files.at(k).compare( lowercase(filename) ) == 0)
2156 cmdpath = exeforce->exePath;
2157 cmdname = exeforce->exeName;
2163 // Add Executable to command
2164 command += "cd " + cmdpath + "; ";
2165 command += "LD_LIBRARY_PATH=./; export LD_LIBRARY_PATH; ";
2166 command += "./" + cmdname;
2169 for (i=0; i<Profile.Extensions.at(ext_index).Arguments.size(); i++)
2172 argument = &Profile.Extensions.at(ext_index).Arguments.at(i);
2175 for (j=0; j<Profile.Extensions.at(ext_index).ArgForces.size(); j++)
2177 argforce = &Profile.Extensions.at(ext_index).ArgForces.at(j);
2178 if (argforce->Path.compare( Profile.FilePath ) == 0)
2180 if (i == argforce->Argument)
2182 Log( "Setting argforce on arg %d\n", i );
2183 value = argforce->Value;
2188 // Check arguments for default value or custom entry value
2189 if (value.length() <= 0 )
2191 if (entry_found==true)
2193 if (CheckRange( i, entry->ArgValues.size() ))
2195 value = argument->Values.at( entry->ArgValues.at(i) );
2199 Log( "Error: RunExec i is out of range\n" );
2205 if (CheckRange( argument->Default, argument->Values.size() ))
2207 value = argument->Values.at( argument->Default );
2211 Log( "Error: RunExec argument->Default is out of range\n" );
2216 // Add the argument if used
2217 if (value.length() > 0)
2219 if (value.compare( VALUE_NOVALUE ) != 0 )
2221 command += " " + argument->Flag + " ";
2223 if (value.compare( VALUE_FLAGONLY ) !=0 )
2225 if (value.compare( VALUE_FILENAME ) == 0)
2227 if (Config.FilenameArgNoExt == true)
2229 filename = filename.substr( 0, filename.find_last_of(".") );
2232 if (entry_found==true)
2235 if (Config.FilenameAbsPath == true)
2237 command += entry->Path;
2239 command += entry->Name + '\"';
2244 if (Config.FilenameAbsPath == true)
2246 command += filepath;
2248 command += filename + '\"';
2262 Log( "Warning no extension was found for this file type\n" );
2266 command += "; sync;";
2267 if (Config.ReloadLauncher == true)
2269 command += " cd " + Profile.LauncherPath + ";";
2270 command += " exec ./" + Profile.LauncherName ;
2272 command += " " + string(ARG_PROFILE) + " " + ProfilePath;
2273 command += " " + string(ARG_CONFIG) + " " + ConfigPath;
2274 command += " " + string(ARG_ZIPLIST) + " " + ZipListPath;
2277 Log( "Running command: '%s'\n", command.c_str());
2281 execlp( "/bin/sh", "/bin/sh", "-c", command.c_str(), NULL );
2283 //if execution continues then something went wrong and as we already called SDL_Quit we cannot continue, try reloading
2284 Log( "Error executing selected application, re-launching %s\n", APPNAME);
2286 chdir( Profile.LauncherPath.c_str() );
2287 execlp( Profile.LauncherName.c_str(), Profile.LauncherName.c_str(), NULL );
2292 int8_t CSelector::PollInputs( void )
2299 for (index=0; index<EventReleased.size(); index++)
2301 if (EventReleased.at(index) == true)
2303 EventReleased.at(index) = false;
2304 EventPressCount.at(index) = EVENT_LOOPS_OFF;
2306 //Log( "DEBUG EventReleased %d\n", index );
2309 else if (EventPressCount.at(index) != EVENT_LOOPS_OFF)
2311 EventPressCount.at(index)--;
2312 if (EventPressCount.at(index) < EVENT_LOOPS_ON)
2314 EventPressCount.at(index) = EVENT_LOOPS;
2320 if (!CheckRange( Mode, DisplayList.size() ))
2322 Log( "Error: PollInputs Mode out of range\n" );
2326 while (SDL_PollEvent( &event ))
2328 switch( event.type )
2331 keyname = SDL_GetKeyName( event.key.keysym.sym );
2332 if (keyname.length() == 1 || event.key.keysym.sym == SDLK_BACKSPACE)
2334 if (Config.EntryFastMode == ENTRY_FAST_MODE_ALPHA)
2336 DisplayList.at(Mode).absolute = Profile.AlphabeticIndices.at(event.key.keysym.sym-SDLK_a);
2337 Profile.EntryFilter.clear();
2339 else if (Config.EntryFastMode == ENTRY_FAST_MODE_FILTER)
2341 if (event.key.keysym.sym==SDLK_BACKSPACE || event.key.keysym.sym==SDLK_DELETE)
2343 if (Profile.EntryFilter.length() > 0)
2345 Profile.EntryFilter.erase( Profile.EntryFilter.length()-1 );
2350 Profile.EntryFilter += keyname;
2352 DrawState_Filter = true;
2359 for (index=0; index<EventPressCount.size(); index++)
2361 if (event.key.keysym.sym == Config.KeyMaps.at(index))
2363 EventPressCount.at(index) = EVENT_LOOPS_ON;
2367 // some hardcoded aternates keys
2370 if (event.key.keysym.sym == SDLK_END)
2372 EventPressCount.at(EVENT_SELECT) = EVENT_LOOPS_ON;
2376 if (!used && Config.UnusedKeysLaunch)
2378 EventPressCount.at(EVENT_SELECT) = EVENT_LOOPS_ON;
2386 for (index=0; index<EventReleased.size(); index++)
2388 if (event.key.keysym.sym == Config.KeyMaps.at(index))
2390 EventReleased.at(index) = true;
2394 // some hardcoded aternates keys
2397 if (event.key.keysym.sym == SDLK_END)
2399 EventReleased.at(EVENT_SELECT) = true;
2403 if (!used && Config.UnusedKeysLaunch)
2405 EventReleased.at(EVENT_SELECT) = true;
2410 case SDL_JOYBUTTONDOWN:
2411 for (index=0; index<EventPressCount.size(); index++)
2413 if (event.jbutton.button == Config.JoyMaps.at(index))
2415 EventPressCount.at(index) = EVENT_LOOPS_ON;
2417 else if (Config.UnusedJoysLaunch)
2419 EventPressCount.at(EVENT_SELECT) = EVENT_LOOPS_ON;
2424 case SDL_JOYBUTTONUP:
2425 for (index=0; index<EventReleased.size(); index++)
2427 if (event.jbutton.button == Config.JoyMaps.at(index))
2429 EventReleased.at(index) = true;
2431 else if (Config.UnusedJoysLaunch)
2433 EventReleased.at(EVENT_SELECT) = true;
2438 case SDL_JOYAXISMOTION:
2439 if (event.jaxis.value < -Config.AnalogDeadZone)
2441 if (event.jaxis.axis == 0)
2443 if (IsEventOff(EVENT_PAGE_UP))
2445 EventPressCount.at(EVENT_PAGE_UP) = EVENT_LOOPS_ON;
2447 EventReleased.at(EVENT_PAGE_DOWN) = true;
2450 if (event.jaxis.axis == 1)
2452 if (IsEventOff(EVENT_ONE_UP))
2454 EventPressCount.at(EVENT_ONE_UP) = EVENT_LOOPS_ON;
2456 EventReleased.at(EVENT_ONE_DOWN) = true;
2459 else if (event.jaxis.value > Config.AnalogDeadZone)
2461 if (event.jaxis.axis == 0)
2463 if (IsEventOff(EVENT_PAGE_DOWN))
2465 EventPressCount.at(EVENT_PAGE_DOWN) = EVENT_LOOPS_ON;
2467 EventReleased.at(EVENT_PAGE_UP) = true;
2470 if (event.jaxis.axis == 1)
2472 if (IsEventOff(EVENT_ONE_DOWN))
2474 EventPressCount.at(EVENT_ONE_DOWN) = EVENT_LOOPS_ON;
2476 EventReleased.at(EVENT_ONE_UP) = true;
2481 EventReleased.at(EVENT_ONE_UP) = true;
2482 EventReleased.at(EVENT_ONE_DOWN) = true;
2483 EventReleased.at(EVENT_PAGE_UP) = true;
2484 EventReleased.at(EVENT_PAGE_DOWN) = true;
2488 case SDL_MOUSEMOTION:
2489 Mouse.x = event.motion.x;
2490 Mouse.y = event.motion.y;
2492 for (index=0; index<RectEntries.size(); index++)
2494 if (CheckRectCollision( &Mouse, &RectEntries.at(index) ))
2496 // Determine item being hovered over by the pointer
2497 newsel = DisplayList.at(Mode).first+index;
2498 // Only need to refresh the names when a new entry is hovered
2499 if (newsel != DisplayList.at(Mode).absolute)
2501 DisplayList.at(Mode).absolute = newsel;
2502 DisplayList.at(Mode).relative = index;
2510 case SDL_MOUSEBUTTONDOWN:
2511 switch (event.button.button)
2513 case SDL_BUTTON_LEFT:
2514 case SDL_BUTTON_MIDDLE:
2515 case SDL_BUTTON_RIGHT:;
2516 Mouse.x = event.button.x;
2517 Mouse.y = event.button.y;
2518 for (index=0; index<RectButtonsLeft.size(); index++)
2520 if (ButtonModesLeft.at(index)!=EVENT_NONE)
2522 if (CheckRectCollision( &Mouse, &RectButtonsLeft.at(index) ))
2524 EventPressCount.at(ButtonModesLeft.at(index)) = EVENT_LOOPS_ON;
2526 Log( "DEBUG LeftButton Active %d %d\n", ButtonModesLeft.at(index), index );
2531 for (index=0; index<RectButtonsRight.size(); index++)
2533 if (ButtonModesRight.at(index)!=EVENT_NONE)
2535 if (CheckRectCollision( &Mouse, &RectButtonsRight.at(index) ))
2537 EventPressCount.at(ButtonModesRight.at(index)) = EVENT_LOOPS_ON;
2539 Log( "DEBUG RightButton Active %d %d\n", ButtonModesRight.at(index), index );
2545 case SDL_BUTTON_WHEELUP:
2546 EventPressCount.at(EVENT_ONE_UP) = EVENT_LOOPS_ON;
2548 case SDL_BUTTON_WHEELDOWN:
2549 EventPressCount.at(EVENT_ONE_DOWN) = EVENT_LOOPS_ON;
2555 case SDL_MOUSEBUTTONUP:
2556 switch (event.button.button)
2558 case SDL_BUTTON_LEFT:
2559 case SDL_BUTTON_MIDDLE:
2560 case SDL_BUTTON_RIGHT:
2561 case SDL_BUTTON_WHEELUP:
2562 case SDL_BUTTON_WHEELDOWN:
2563 Mouse.x = event.button.x;
2564 Mouse.y = event.button.y;
2566 for (index=0; index<EventReleased.size(); index++)
2568 EventReleased.at(index) = true;
2571 Log( "DEBUG Releasing all events\n" );
2584 if (IsEventOn(EVENT_ONE_UP)==true)
2586 DisplayList.at(Mode).absolute--;
2587 DisplayList.at(Mode).relative--;
2590 if (IsEventOn(EVENT_ONE_DOWN)==true)
2592 DisplayList.at(Mode).absolute++;
2593 DisplayList.at(Mode).relative++;
2596 if (IsEventOn(EVENT_PAGE_UP)==true)
2598 DisplayList.at(Mode).absolute -= Config.MaxEntries;
2599 DisplayList.at(Mode).relative = 0;
2602 if (IsEventOn(EVENT_PAGE_DOWN)==true)
2604 DisplayList.at(Mode).absolute += Config.MaxEntries;
2605 DisplayList.at(Mode).relative = Config.MaxEntries-1;
2610 if (Mode == MODE_SELECT_ENTRY)
2613 if (Rescan == false && IsEventOn(EVENT_DIR_UP) == true)
2615 if (Config.UseZipSupport == 1 && Profile.ZipFile.length() > 0)
2621 if (Profile.LaunchableDirs == false)
2628 // Go down into a dir
2629 if (Rescan == false && ((IsEventOn(EVENT_DIR_DOWN) == true) || (IsEventOn(EVENT_SELECT) == true)))
2631 if (ItemsEntry.size()>0)
2633 if (ItemsEntry.at(DisplayList.at(Mode).absolute).Type == TYPE_DIR)
2635 if (Profile.LaunchableDirs == false)
2640 else if (Config.UseZipSupport == 1 && ItemsEntry.at(DisplayList.at(Mode).absolute).Type == TYPE_ZIP)
2647 EventPressCount.at( EVENT_SELECT ) = EVENT_LOOPS_OFF;
2652 // Value configuration
2653 if (Mode == MODE_SELECT_VALUE)
2655 SetOneEntryValue = false;
2656 SetAllEntryValue = false;
2657 if (IsEventOn(EVENT_SET_ONE) == true)
2660 SetOneEntryValue = true;
2662 if (IsEventOn(EVENT_SET_ALL) == true)
2665 SetAllEntryValue = true;
2669 if (IsEventOn(EVENT_ZIP_MODE) == true)
2672 DrawState_ZipMode = true;
2673 ExtractAllFiles = !ExtractAllFiles;