--[[
 ################################## 
 #Source code for AnyLanguageStudy#
 #Copyright Nakano 2011.          #
 #                                #
 ######## VERSION HISTORY #########
 # V0.1 02/27/2011 (by nakano)    #
 # * Initial release              #
 # V0.2 03/02/2011 (by nakano)    #
 # * Increased stability          #
 # * Bug fixes                    # 
 # * Optimizations for showing    #
 #   long phrases.                #
 # V0.3 03/05/2011 (by nakano)    #
 # * Question font size can be    #
 #   increased                    #
 # * Added options menu           #
 # * If user answers wrong, right #
 #   answer is given (option)     #
 # * User may set delay before    #
 #   answers are shown (option)   #
 # V0.4 03/08/2011 (by nakano)    #
 # * Support for picture word list#
 # * Added range (option)         #
 # * Example sentences (option)   #
 # * Keys menu                    #
 # * Minor bug fixes and          #
 #   other optimizations          #
 # V0.5 03/13/2011 (by nakano)    #
 # * A possibility to search      #
 #   English definitions.         #
 # * Added an option to           #
 #   wait after the right choice  #
 # * Added an option to change    #
 #   font color 				  #
 # * Fixed a typo sring to string,#
 #   which caused crash in certain#
 #   situation                    #
 # * Slight text changes          #
 # * Modified logic, if word was  #
 #   not known immediately. Now   #
 #   it's not marked right when   #
 #   you correct yourself         #
 # V0.6 04/22/2011 (by nakano)    #
 # * Added analog support for     #
 #   selection a file etc.        #
 # * Fixed a bug of strange circle#
 #   and a bug with storing       #
 #   sentences.                   #
 # * Better Japanese sentence     #
 #   newline support.             #
 # * Zoom support for sentences.  #
 # V0.7 05/01/2011 (by nakano)    #
 # * Added a support for audio    #
 #   files with sentences.        #
 # * A better support for non-    #
 #   Japanese languages.          #
 # V0.8 05/04/2011 (by nakano)    #
 # * A possibility to group       #
 #   word lists.                  #
 # * Remembers the last word list.#
 # * Some code rewrite.           #
 # * Fixed a freezing bug caused  #
 #   by a bug in Euphoria V8.     #
 # * Now search not only search   #
 #   definition but translation   #
 #   too.                         #
 # V0.9 05/14/2011 (by nakano)    #
 # * Fixed a bug if list path had #
 #   no slash                     #
 # * Made possible that e.g.      #
 #   Koreans can study Chinese.   #
 # * Several optimizations for    #
 #   making the experience better #
 #   (linebreak length, avoid re- #
 #    loading of same dictionary, #
 #   avoid flip within draw)      #
 # * Custom Japanese search OSK.  #
 # V1.0 05/28/2011 (by nakano)    #
 # * When a known list is cleared,#
 #   it will only clear the       #
 #   current range.               #
 # V2.0 08/06/2011 (by nakano)    #
 # * Remembers question, range and#
 #   mode after quiting.          #
 # * Now search can be done with  #
 #   characters ä, ö...           #
 # V3.0 09/14/2011 (by nakano)    #
 # * Added Quick Jump Menu        #
 # * Support for custom styles.   #
 # * Possibility to determine 1)  #
 #   Image location, 2) Word list #
 #   break points and names, 3)   #
 #   Set button position/order and#
 #   4) determine text positions. #
 ##################################
]]

math.randomseed( os.time() ); -- random seed

-- COLORS
gray = Color.new(180, 180, 180);
white = Color.new(255, 255, 255);
darkgray = Color.new(100, 100, 100, 128);
lime = Color.new(50,205,50);
red = Color.new(255,0,0);
lightblue = Color.new(64,255,255);
yellow = Color.new(255,215,0);
blue = Color.new(65, 105, 225);
currentColor = white; -- for switching between font color

-- ALL IMAGES
--logo = Image.load("images/logo.png");
-- other images are loaded in showLogo (gives more time for logo; see loadImages-function)

-- FONTS
ifontLtn = IntraFont.load("flash0:/font/ltn0.pgf", IntraFont.STRING_UTF8);
ifontJpn = IntraFont.load("flash0:/font/jpn0.pgf", IntraFont.STRING_UTF8);
prevFont1 = ""; -- used for optimization
prevFont2 = ""; -- used for optimization

-- GLOBAL VARIABLES OF SELECTING FILE
selection = 1;
page = 0;

-- FONT SIZE SMALLER / BREAK TO SEPARATE LINES LIMITS
SMALLFONTLIMIT = 40;
LINEBREAKLIMIT = 72;

sentence = {}; -- example sentences are stored here of selected language
currentSentencePath = "none"; -- path without file where example sentences are previously found

askLevel = 0;
previousSearch = ""; -- currently not in use, Euphoria bug
previousWordList = ""; -- for optimization when goto menu
keyboardType = 0; -- tell whether to use normal osk or Hiragana/Katakana keyboard
hiraganaMode = true; -- tell the mode of Japanese keyboard
currentMouseX = 10;
currentMouseY = 10;

breakList = {{}}  -- askMin / askMax if [break] selected
nameList = {}
listName = "";

coordinateList = {} -- starting index, x, y (read from end)
imageX = 0;
imageY = 0;

questionStartTime = 0;
questionEndTime = 0;
questionTotalTime = {0,0}; -- total time used ; number of questions answered right

-- button config
button1 = "triangle";
button2 = "square";
button3 = "circle";
button4 = "cross";

triangleX = 30;
triangleY = 116;
squareX = 30;
squareY = 146;
circleX = 30;
circleY = 176; -- 174
crossX = 30;
crossY = 206; -- 202

textAlign = IntraFont.ALIGN_CENTER;
wordX = 240;

--[[ 
Show right answer after wrong true/false
Show sentence after answer true/false
Wait press after right answer
Wait before choices 0 (never), 3 (seconds), 5 (seconds), 10 (seconds), 100 (press)
Set range 0 (ALL), 10, 20, 50, 100 (max)
Font color white, blue (lightblue), yellow, green (lime), red
Style <number>
]]
userOptions = {"true", "true", "true", "0", "0", "white", "1"}

-- FUNCTIONS

freeImages = function()
	Image.free(background)
	Image.free(square)
	Image.free(triangle)
	Image.free(circle)
	Image.free(cross)
	Image.free(right)
	Image.free(options)
	Image.free(longbutton)
	Image.free(shortbutton)
	Image.free(sentencebox)
	Image.free(searchScreen)
	Image.free(mouse)
end

loadImages = function()
	background = Image.load("images/style" .. userOptions[7] .. "/background.png")
	square = Image.load("images/style" .. userOptions[7] .. "/square.png")
	triangle = Image.load("images/style" .. userOptions[7] .. "/triangle.png")
	circle = Image.load("images/style" .. userOptions[7] .. "/circle.png")
	cross = Image.load("images/style" .. userOptions[7] .. "/cross.png")
	right = Image.load("images/style" .. userOptions[7] .. "/right.png")
	options = Image.load("images/style" .. userOptions[7] .. "/options.png")
	longbutton = Image.load("images/style" .. userOptions[7] .. "/longbutton.png")
	shortbutton = Image.load("images/style" .. userOptions[7] .. "/shortbutton.png")
	sentencebox = Image.load("images/style" .. userOptions[7] .. "/sentence.png")
	searchScreen = Image.load("images/style" .. userOptions[7] .. "/search.png")
	mouse = Image.load("images/style" .. userOptions[7] .. "/mouse.png")
end

function round(number)

	local seconds = string.format("%.2f", number)
	local minutes = math.floor(number / 60);
	
	if (minutes > 0) then
		return minutes .. "min " .. string.format("%.0f", (tonumber(seconds) - (minutes * 60))) .. "s";
	end
	
	return seconds .. "s";
	
end


getImageXY = function(questionIndex)
	local j = #coordinateList;
	
	imageX = 0;
	imageY = 0;
	
	while (j > 0) do
		if (questionIndex >= coordinateList[j][1]) then
			imageX = coordinateList[j][2]
			imageY = coordinateList[j][3]
			break;
		end
		
		j = j - 1;
	end
	
end

loadCharset = function(dictionaryFont, secondaryFont)
	
	if (prevFont1 == dictionaryFont and prevFont2 == secondaryFont) then
		return; -- no need for reload
	end
	
	if (ifont ~= nil) then
		ifont:unload()
	end
	
	prevFont1 = dictionaryFont;
	prevFont2 = secondaryFont;
	local fontPath1 = "flash0:/font/" .. dictionaryFont;
	local fontPath2 = "flash0:/font/" .. secondaryFont;
	ifont = IntraFont.load(fontPath1, IntraFont.STRING_UTF8);
	ifontSecondary = IntraFont.load(fontPath2, IntraFont.STRING_UTF8);
	IntraFont.setAltFont(ifont, ifontSecondary); -- secondary font if primary font doesn't support all ltn0 characters (like Chinese font)
end

showLogo = function()
	--System.draw();
	--screen:blit(0, 0, logo);
	--System.endDraw();
	--screen.flip()
	loadImages()
	--screen.waitVblankStart(150);
	--Image.free(logo) -- free more memory
end

string.split = function(str, pattern)
	pattern = pattern or "[^%s]+"
	if pattern:len() == 0 then pattern = "[^%s]+" end
	local parts = {__index = table.insert}
	setmetatable(parts, parts)
	str:gsub(pattern, parts)
	setmetatable(parts, nil)
	parts.__index = nil
	table.insert(parts, "false"); -- not quessed yet
	return parts
end

string.splitOptions = function(str, pattern)
	pattern = pattern or "[^%s]+"
	if pattern:len() == 0 then pattern = "[^%s]+" end
	local parts = {__index = table.insert}
	setmetatable(parts, parts)
	str:gsub(pattern, parts)
	setmetatable(parts, nil)
	parts.__index = nil
	return parts
end

string.splitSentences = function(str, pattern)
	pattern = pattern or "[^%s]+"
	if pattern:len() == 0 then pattern = "[^%s]+" end
	local parts = {__index = table.insert}
	setmetatable(parts, parts)
	str:gsub(pattern, parts)
	setmetatable(parts, nil)
	parts.__index = nil
	return parts
end

function trim (str)
	return (string.gsub(str, "^%s*(.-)%s*$", "%1"))
end

function table.copy(t)
  local t2 = {}
  for k,v in pairs(t) do
    t2[k] = v
  end
  return t2
end

setFontColor = function()
	if (userOptions[6] == "white") then
		currentColor = white;
	elseif (userOptions[6] == "blue") then
		currentColor = blue;
	elseif (userOptions[6] == "yellow") then
		currentColor = yellow;
	elseif (userOptions[6] == "green") then
		currentColor = lime;
	else
		currentColor = red;
	end
end

saveSelection = function()
	local lastFile = "last";
	local file = io.open(lastFile,"w")				
	file:write(dictionary[selection][3]); -- path to the file	
	file:close();
end

-- note should still remove last same entry
saveQuestionList = function(dictionaryName, question, first, second, third, fourth, show, askLevel, mode)

	--local copyFile = copyQuestionList(dictionaryName); -- this technique won't work... Must append, file is going to grow long...
	
	local questionListFile = "questionList";
	local file = io.open(questionListFile,"a")
	
	file:write(dictionaryName .. ";" .. question .. ";" .. first .. ";" .. second .. ";" .. third .. ";" .. fourth .. ";" .. show .. ";" .. askLevel .. ";" .. mode .. "\n");
	file:close()
end

-- this function should only be called after saveSelection
saveQuestion = function(question, first, second, third, fourth, show, askLevel, mode)
	local questionFile = "question";
	file = io.open(questionFile,"w")
	file:write(question .. ";" .. first .. ";" .. second .. ";" .. third .. ";" .. fourth .. ";" .. show .. ";" .. askLevel .. ";" .. mode);
	file:close()
end

canGetLastQuestion = function(dictionaryName)
	local file = io.open("questionList", "r");
	local line = ""
	local entryFound = false; -- need this as dictionary entry is always the last.
	
	if file then
		for line in file:lines() do
		
			if (line ~= nil) then
				local questionData = line:splitOptions("[^;]+");
		
				if (#questionData == 9 and dictionaryName == questionData[1]) then
					saveQuestion(questionData[2], questionData[3], questionData[4], questionData[5], questionData[6], questionData[7], questionData[8], questionData[9])
					entryFound = true;
				end
			end
		end
		
		file:close()
	end
	
	if (entryFound) then
		return true;
	end
	
	return false; -- no previous questions
end

getLastQuestion = function()
	local file = io.open("question", "r");
	local line = file:read();
	local questionData = line:splitOptions("[^;]+");
	
	question = tonumber(questionData[1]);
	first = tonumber(questionData[2]);
	second = tonumber(questionData[3]);
	third = tonumber(questionData[4]);
	fourth = tonumber(questionData[5]);
	show = tonumber(questionData[6]);
	askLevel = tonumber(questionData[7]);
	mode = tonumber(questionData[8]);
	file:close()
end

getLastFile = function()

	local lastFileSubset = 1;
	local lastFileSelection = 1;
	local lastFilePage = 0;
	local subsetFormed = false;
	local file = io.open("last", "r");

	if file then
		-- no previous last file stored
		lastFile = file:read();	
		file:close();
		
		-- Find selection, page and currentSubset
		local j = 0;
		local lastFileSubsetName = "";
		while (j < #allDictionary) do
			j = j + 1;
		
			if (allDictionary[j][3] == lastFile) then
				-- entry was found
				lastFileSubsetName = allDictionary[j][4];
				break;
			end
		end
			
		j = 0;
		local subsetFound = false;
		while (j < #dictionarySubset) do
			j = j + 1;
			if (lastFileSubsetName == dictionarySubset[j]) then
				subsetFound = true;
				lastFileSubset = j;
				break;
			end
		end
			
		if (subsetFound) then
			-- calculate selection and page
			subsetFormed = true;
			currentSubset = lastFileSubset;
			dictionary = formSubset()
			
			j = 0;
			while (j < #dictionary) do
				j = j + 1;
				if (dictionary[j][3] == lastFile) then
					lastFileSelection = j;
					lastFilePage = math.floor(lastFileSelection / 10)
					if (math.floor(lastFileSelection % 10) == 0) then
						lastFilePage = lastFilePage - 1
					end
					break;
				end
			end
		end		
	end
	
return lastFileSelection, lastFilePage, lastFileSubset, subsetFormed

end

search = function()

local currentX = 1;
local searchIndexList = {}
local currentIndex = 0;
local extraFont = 0;

	while true do

	System.draw()
	screen:blit(0, 0, searchScreen);
	ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
	ifontLtn:print(240, 22, "Search (" .. currentIndex .. " / " .. #searchIndexList .. ")");
	ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
	if (keyboardType == 0) then
		ifontLtn:print(25, 230, "Osk: Normal");
	elseif (keyboardType == 1) then
		ifontLtn:print(25, 230, "Osk: Hiragana");
		hiraganaMode = true;
	elseif (keyboardType == 2) then
		ifontLtn:print(25, 230, "Osk: Katakana");
		hiraganaMode = false;
	end
	ifontLtn:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);

	-- SHOW SELECTOR
	if (currentX == 1) then
		screen:blit(140,240, longbutton);
	else
		screen:blit(262,240, longbutton);
	end

	-- SHOW SEARCH RESULT
	if (#searchIndexList > 0) then
		if (#searchIndexList > 1) then
			ifontLtn:print(30, 20, "< L");
			ifontLtn:print(450, 20, "R >");
		end
		
		ifont:setStyle(1.0 + extraFont, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		ifontSecondary:setStyle(1.0 + extraFont, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		local i = 0;
		local itemList = {}
		
		while (i < #word[searchIndexList[currentIndex]]) do
			i = i + 1;
			local currentFound = word[searchIndexList[currentIndex]][i];
			
			if (currentFound == true or currentFound == false) then
				-- ignore
			else
				if (string.len(currentFound) > SMALLFONTLIMIT) then
					ifont:setStyle(0.6 + extraFont, currentColor, darkgray, IntraFont.ALIGN_CENTER);
					ifontSecondary:setStyle(0.6 + extraFont, currentColor, darkgray, IntraFont.ALIGN_CENTER);
				end
		
				if (string.len(currentFound) > LINEBREAKLIMIT) then
					local beginning = string.sub(currentFound, 1, LINEBREAKLIMIT);
					local ending = string.sub(currentFound, LINEBREAKLIMIT + 1);
					currentFound = beginning .. " \n " .. ending; -- note: breaks a multibyte character if concenating is done in the middle of a byte; a solution would be use arrays instead of strings or use sub-method that knows how to handle multibytes (1-4).
				end
			
				if (i == #word[searchIndexList[currentIndex]]) then
					local text = "Yes";
					if (currentFound == "false") then
						text = "No";
					end
					table.insert(itemList, "Known: " .. text);
				else
					table.insert(itemList, currentFound);
				end
			end
		end
		i = 0;
		while (i < #itemList) do
			i = i + 1;
			ifont:print(240, 22 + i * 35, itemList[i])
		end
		ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		ifontSecondary:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
	end
	
	local pad = Controls.readPeek()
		
	if (pad:cross() or pad:triangle() or pad:circle() or pad:square()) then

		if (currentX == 1) then
			if (keyboardType == 0) then
			searchWord, result = System.osk("Search definition", "", System.OSK_INPUTTYPE_ALL) -- EUPHORIA V8 has a bug, which may cause a freeze if we user previousSearch instead of "" (tested N5, car, kuruma --> Tatoeba1: clear previousSearch and find. To avoid this, changed to "".
			else
				searchWord = showKeyboard() -- Using Japanese keyboard
			end
			
			-- user searched
			if (result==System.OSK_RESULT_CHANGED or keyboardType ~= 0) then
				
				local i = 0;
				currentIndex = 0;
				searchIndexList = {} -- clear current list
				
				-- only allow character conversion in normal osk mode, otherwise kana search fail
				if (keyboardType == 0) then
					searchWord = convertSearchWord(searchWord)
				end
				
				searchWord = string.lower(searchWord)
				previousSearch = searchWord;
				
				while (i < #word) do
					i = i + 1;
					
					-- search all (definition and others)
					local level = #word[i]; -- defition when - 1
					while (level > 1) do
						level = level - 1;
			
						foundWord = word[i][level]; -- some strange occasions there may be boolean, do extra check
						if (foundWord == true or foundWord == false) then
							-- move on
						else
							foundWord = string.lower(foundWord);
							searchIndex = string.find(foundWord, searchWord);
							if (searchIndex ~= nil or foundWord == searchWord) then
								table.insert(searchIndexList, i)
								currentIndex = 1;
								break;
							end
						end
					end
				end
			end
			screen.waitVblankStart(20);
		
		else
			screen.waitVblankStart(20);
			break;
		end

	elseif pad:up() then
		keyboardType = keyboardType + 1;
		if (keyboardType > 2) then
			keyboardType = 0;
		end
		screen.waitVblankStart(20);
	elseif pad:down() then
		keyboardType = keyboardType - 1;
		if (keyboardType < 0) then
			keyboardType = 2;
		end
		screen.waitVblankStart(20);
	elseif pad:right() then
		currentX = currentX + 1;
		if (currentX > 2) then
			currentX = 1;
		end
		screen.waitVblankStart(20);

	elseif pad:left() then
		currentX = currentX - 1;
		if (currentX < 1) then
			currentX = 2;
		end
		screen.waitVblankStart(20);

	elseif (pad:analogY() < -100 ) then
		screen.waitVblankStart(1); -- added
		extraFont = extraFont + 0.1;
		if (extraFont > 1.3) then
			extraFont = 1.3;
		end
		
	elseif (pad:analogY() > 100 ) then
		screen.waitVblankStart(1); -- added
		extraFont = extraFont - 0.1
		if (extraFont < 0) then
			extraFont = 0
		end
		
	elseif pad:r() or pad:analogX() > 100 then
		currentIndex = currentIndex + 1;
	
		if (currentIndex > #searchIndexList) then
			currentIndex = 1;
		end
		screen.waitVblankStart(10);

	elseif pad:l() or pad:analogX() < -100 then
		currentIndex = currentIndex - 1;
	
		if (currentIndex < 1) then
			currentIndex = #searchIndexList;
		end
		screen.waitVblankStart(10);
	
	elseif pad:select() then
		screen.waitVblankStart(20);
		if (questionImage ~= nil and questionImage ~= false) then -- free memory
			Image.free(questionImage)
		end
		askLevel = 0;
		selectDictionary();
			
	elseif pad:start() then
		screen.waitVblankStart(20);
		openOptions();	

	elseif pad:home() then
		break; -- if no wait force exit
	end

	System.endDraw()
	screen.flip()
	collectgarbage()
	end
end

calculateEstimation = function(answerAverage)
	local stillLeft = 0;
	
	local i = askMin;
	
	while (i < askMax) do
		i = i + 1;
		if (word[i][#word[1]] == "false") then
			stillLeft = stillLeft + 1;
		end
	end
	
	if (stillLeft ~= 0) then
		return stillLeft * answerAverage
	end
	
	return 0; -- all is right within the range
	
end

waitPress = function()
	local questionTime = questionEndTime - questionStartTime;
	questionTotalTime[1] = questionTotalTime[1] + questionTime;
	questionTotalTime[2] = questionTotalTime[2] + 1;
	local answerAverage = questionTotalTime[1] / questionTotalTime[2];
	local estimationTime = calculateEstimation(answerAverage);
while true do
		
		-- Show questions
        System.draw();
		screen:blit(0, 0, background);
		--screen:blit(30, 118, square);
		--screen:blit(30, 146, triangle);
		
		if (question == first) then
			screen:blit(60, 116, right);
		elseif (question == second) then
			screen:blit(60, 146, right);
		elseif (question == third) then
			screen:blit(60, 176, right);
		else
			screen:blit(60, 206, right);
		end
		
		screen:blit(triangleX, triangleY, triangle);
		screen:blit(squareX, squareY, square);
		screen:blit(circleX, circleY, circle);
		screen:blit(crossX, crossY, cross);

		ifontLtn:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		ifont:setStyle(1.0 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		ifontSecondary:setStyle(1.0 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		if (mode == 1) then
		
		-- if too long text, should smallen the font
		question1 = trim(word[question][#word[question] - 1]);
		if (string.len(question1) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			ifontSecondary:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		if (string.len(question1) > LINEBREAKLIMIT) then
			local beginning = string.sub(question1, 1, LINEBREAKLIMIT);
			local ending = string.sub(question1, LINEBREAKLIMIT + 1);
			question1 = beginning .. " \n " .. ending;
		end
		
		if (string.find(question1, ".png")) then -- image query
			if (imageLoaded == false) then
			
				local file8 = io.open(question1);
				if (file8 == nil ) then
					questionImage = false;
				else
					questionImage = Image.load(question1);
					imageLoaded = true;
					file8:close()
					getImageXY(question);
				end
			end
			if (questionImage == false) then
				ifontLtn:print(240, 56, "Not found: " .. question1);
			else
				screen:blit(imageX,imageY,questionImage) -- image was found, show it
				--screen:blit(30, 118, square);
				--screen:blit(30, 146, triangle);
				
				if (question == first) then
					screen:blit(60, 116, right);
				elseif (question == second) then
					screen:blit(60, 146, right);
				elseif (question == third) then
					screen:blit(60, 176, right);
				else
					screen:blit(60, 206, right);
				end
				
				screen:blit(triangleX, triangleY, triangle);
				screen:blit(squareX, squareY, square);
				screen:blit(circleX, circleY, circle);
				screen:blit(crossX, crossY, cross);
			end
	
		else
			ifont:print(240, 56, question1); -- translation
		end
		
		ifontSecondary:setStyle(1.0, currentColor, darkgray, IntraFont.ALIGN_CENTER); -- do not allow zoom of answers
		word1 = trim(word[first][show]);
		word2 = trim(word[second][show]);
		word3 = trim(word[third][show]);
		word4 = trim(word[fourth][show]);
		
		-- If item has no text, show it in another format if possible
		counts = #word[1] - 2;
		counter = 0;
		tempShow = show;
		
		while (counter < counts) do
		
			if (string.len(word1) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[first] - 2;
				end
			
				word1 = trim(word[first][tempShow])
				counter = counter + 1;
	
			else
				break;
			end
		end
		
		counter = 0;
		
		while (counter <= counts) do
		
			if (string.len(word2) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[second] - 2;
				end
			
				word2 = trim(word[second][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
		counter = 0;
		
		while (counter <= counts) do
		
			if (string.len(word3) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[third] - 2;
				end
			
				word3 = trim(word[third][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
		counter = 0;
		
		while (counter <= counts) do
		
			if (string.len(word4) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[fourth] - 2;
				end
			
				word4 = trim(word[fourth][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
			ifont:setStyle(1.0, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
			if (string.len(word1) > SMALLFONTLIMIT) then
				ifont:setStyle(0.6, currentColor, darkgray, textAlign);
				ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
			end
			
			-- optimizing for japanese strings, if too long line break
			if (string.len(word1) > LINEBREAKLIMIT) then
				local beginning = string.sub(word1, 1, LINEBREAKLIMIT);
				local ending = string.sub(word1, LINEBREAKLIMIT + 1);
				word1 = beginning .. " \n " .. ending;
			end

			ifont:print(wordX, 136, word1); -- answer1
		
			ifont:setStyle(1.0, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
			if (string.len(word2) > SMALLFONTLIMIT) then
				ifont:setStyle(0.6, currentColor, darkgray, textAlign);
				ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
			end
			
			-- optimizing for japanese strings, if too long line break
			if (string.len(word2) > LINEBREAKLIMIT) then
				local beginning = string.sub(word2, 1, LINEBREAKLIMIT);
				local ending = string.sub(word2, LINEBREAKLIMIT + 1);
				word2 = beginning .. " \n " .. ending;
			end
		
			ifont:print(wordX, 166, word2); -- answer2
		
			ifont:setStyle(1.0, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
			if (string.len(word3) > SMALLFONTLIMIT) then
				ifont:setStyle(0.6, currentColor, darkgray, textAlign);
				ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
			end
		
			-- optimizing for japanese strings, if too long line break
			if (string.len(word3) > LINEBREAKLIMIT) then
				local beginning = string.sub(word3, 1, LINEBREAKLIMIT);
				local ending = string.sub(word3, LINEBREAKLIMIT + 1);
				word3 = beginning .. " \n " .. ending;
			end
		
			ifont:print(wordX, 196, word3); -- answer3
		
			ifont:setStyle(1.0, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
			if (string.len(word4) > SMALLFONTLIMIT) then
				ifont:setStyle(0.6, currentColor, darkgray, textAlign);
				ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
			end
			
			-- optimizing for japanese strings, if too long line break
			if (string.len(word4) > LINEBREAKLIMIT) then
				local beginning = string.sub(word4, 1, LINEBREAKLIMIT);
				local ending = string.sub(word4, LINEBREAKLIMIT + 1);
				word4 = beginning .. " \n " .. ending;
			end
		
			ifont:print(wordX, 226, word4); -- answer4
		
			ifont:setStyle(1.0, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			ifontSecondary:setStyle(1.0, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		
		elseif (mode == 2) then
		
		question1 = trim(word[question][show]);
		
		-- if wrong mode (comes from mode 2 to picture questionaire)
		if (string.find(question1, ".png")) then -- image query
			mode = 1;
			randomize();
		end
		
		-- If item has no text, show it in another format if possible
		counts = #word[1] - 2;
		counter = 0;
		tempShow = show;
		
		while (counter <= counts) do
		
			if (string.len(question1) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[question] - 2;
				end
			
				question1 = trim(word[question][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
		if (string.len(question1) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			ifontSecondary:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(question1) > LINEBREAKLIMIT) then
			local beginning = string.sub(question1, 1, LINEBREAKLIMIT);
			local ending = string.sub(question1, LINEBREAKLIMIT + 1);
			question1 = beginning .. " \n " .. ending;
		end
		
		ifont:print(240, 56, question1);
		
		word1 = trim(word[first][#word[first] - 1]);
		word2 = trim(word[second][#word[second] - 1]);
		word3 = trim(word[third][#word[third] - 1]);
		word4 = trim(word[fourth][#word[fourth] - 1]);
		
		ifont:setStyle(1.0, currentColor, darkgray, textAlign);
		ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign); -- do not allow zoom of answers
		
		if (string.len(word1) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word1) > LINEBREAKLIMIT) then
			local beginning = string.sub(word1, 1, LINEBREAKLIMIT);
			local ending = string.sub(word1, LINEBREAKLIMIT + 1);
			word1 = beginning .. " \n " .. ending;
		end
		
		ifont:print(wordX, 136, word1); -- translation
		
		ifont:setStyle(1.0, currentColor, darkgray, textAlign);
		ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
		if (string.len(word2) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word2) > LINEBREAKLIMIT) then
			local beginning = string.sub(word2, 1, LINEBREAKLIMIT);
			local ending = string.sub(word2, LINEBREAKLIMIT + 1);
			word2 = beginning .. " \n " .. ending;
		end
		
		ifont:print(wordX, 166, word2); -- translation
		
		ifont:setStyle(1.0, currentColor, darkgray, textAlign);
		ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
		if (string.len(word3) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word3) > LINEBREAKLIMIT) then
			local beginning = string.sub(word3, 1, LINEBREAKLIMIT);
			local ending = string.sub(word3, LINEBREAKLIMIT + 1);
			word3 = beginning .. " \n " .. ending;
		end
		
		ifont:print(wordX, 196, word3); -- translation
		
		ifont:setStyle(1.0, currentColor, darkgray, textAlign);
		ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
		if (string.len(word4) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word4) > LINEBREAKLIMIT) then
			local beginning = string.sub(word4, 1, LINEBREAKLIMIT);
			local ending = string.sub(word4, LINEBREAKLIMIT + 1);
			word4 = beginning .. " \n " .. ending;
		end
		
		ifont:print(wordX, 226, word4); -- translation
		
		ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		ifontSecondary:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		end

		-- Show right answer
		--[[if (userOptions[1] == "true" and showAnswer) then
			if (question == first) then
				screen:blit(60, 116, right);
			elseif (question == second) then
				screen:blit(60, 146, right);
			elseif (question == third) then
				screen:blit(60, 176, right);
			else
				screen:blit(60, 206, right);
			end
		end]]
		
		-- ANSWERING TIMES
		ifontLtn:setStyle(1.0, gray, darkgray, IntraFont.ALIGN_CENTER);
		ifontLtn:print(240, 86, "Press CROSS to continue.");
		
		ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(107, 100, "Answering time: " .. round(questionTime) .. " / Average: " .. round(answerAverage) );
		ifontLtn:print(107, 115, "Total time: " .. round(questionTotalTime[1]) .. " / Estimation left: " .. round(estimationTime));
		
		ifontLtn:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		ifontLtn:print(100, 255, "Mode: " .. mode .. " / Show: " .. show ); -- show mode and show
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(10, 267, "Range: " .. askMin .. "-" .. askMax .. " / " .. #word .. " " .. listName); -- show range
		ifontLtn:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		if (allKnown == 1) then
			ifontLtn:print(395, 260, "All once correct");
		elseif (setKnown == 1) then
			ifontLtn:print(395, 260, "Set once correct");
		end

local pad = Controls.readPeek()
		
		if (pad:cross() or pad:triangle() or pad:circle() or pad:square()) then
			screen.waitVblankStart(20);
			break;
		
		elseif pad:right() then
			if (show == #word[1] - 2) then
				show = 1;
				screen.flip();
				screen.waitVblankStart(20);
			else
				show = show + 1;
				screen.flip();
				screen.waitVblankStart(20);
			end
				
		elseif pad:left() then
			if (show == 1) then
				show = #word[1] - 2;
				screen.flip();
				screen.waitVblankStart(20);
			else
				show = show - 1;
				screen.flip();
				screen.waitVblankStart(20);
			end

		elseif (pad:analogY() < -100 ) then
			screen.waitVblankStart(1); -- added
			extraQ = extraQ + 0.1;
			if (extraQ > 2) then
				extraQ = 2;
			end
		
		elseif (pad:analogY() > 100 ) then
			screen.waitVblankStart(1); -- added
			extraQ = extraQ - 0.1
			if (extraQ < 0) then
				extraQ = 0
			end
		
		elseif (pad:analogX() < - 100 and userOptions[5] ~= "0") then
			askLevel = askLevel - 1;
			if (userOptions[5] ~= "break") then
				if (askLevel < 0) then
					askLevel = math.ceil(#word / userOptions[5]) - 1;
				end
			else
				if (askLevel < 0) then
					askLevel = #breakList - 1;
				end
			end
			
			calculateMinMax()
			screen.waitVblankStart(20);
			
		elseif (pad:analogX() > 100 and userOptions[5] ~= "0") then
			askLevel = askLevel + 1;
			if (userOptions[5] ~= "break") then
				if (askLevel > (math.ceil(#word / userOptions[5]) - 1)) then
					askLevel = 0;
				end
			else
				if (askLevel + 1 > #breakList) then
					askLevel = 0
				end
			end
			calculateMinMax()
			screen.waitVblankStart(20);	
		
		elseif pad:select() then
			save(question, first, second, third, fourth, show, askLevel, mode)
			screen.waitVblankStart(20);
			if (questionImage ~= nil and questionImage ~= false) then -- free memory
				Image.free(questionImage)
			end
			askLevel = 0;
			--initialize();
			selectDictionary()
		
		elseif pad:start() then
			save(question, first, second, third, fourth, show, askLevel, mode)
			screen.waitVblankStart(20);
			openOptions();
			
		elseif pad:r() then
			result = System.msgDialog("Do you want to clear current known list? (Range " .. askMin .. "-" .. askMax .. ")", true, drawFunc)
			if (result==System.MSGDIALOG_RESULT_YES) then
				clearResults(word, askMin, askMax);
				allKnown = 0;
				setKnown = 0;
				save(question, first, second, third, fourth, show, askLevel, mode);
			end
			
		elseif pad:l() then
			screen.waitVblankStart(20);
			save(question, first, second, third, fourth, show, askLevel, mode)
			search()
		
		elseif pad:home() then
				break; -- if no wait force exit
		end
		
		System.endDraw()
		screen.flip()
end

end

showSentence = function(PrimarySearch, SecondarySearch, questionFontSize)
	local i = 0;
	local showedSentence = "";
	local sentenceIndexList = {}
	local bigStyle = true;

	while (i < #sentence) do
		i = i + 1
		searchIndexPrimary = string.find(string.lower(sentence[i][1]), string.lower(PrimarySearch));
		if (searchIndexPrimary ~= nil or string.lower(sentence[i][1]) == string.lower(PrimarySearch)) then -- added or for utf-8 string comparision
			table.insert(sentenceIndexList, i)
		end
	end
	
	i = 0;
	
	if (#sentenceIndexList == 0) then
		while (i < #sentence) do
			i = i + 1
			searchIndexSecondary = string.find(string.lower(sentence[i][2]), string.lower(SecondarySearch));
			if (searchIndexSecondary ~= nil or string.lower(sentence[i][2]) == string.lower(SecondarySearch)) then
				table.insert(sentenceIndexList, i);
			end
		end
	end
	
	-- Choose sentence
	if (#sentenceIndexList ~= 0) then
		sentenceIndex = math.random(1,#sentenceIndexList); -- 1..n
		sentenceIndex = sentenceIndexList[sentenceIndex]; 	-- get i value
	
		sentence1 = trim(sentence[sentenceIndex][1]);
			if (string.len(sentence1) > SMALLFONTLIMIT) then
				bigStyle = false;
			end
		
			-- two ways to break sentence (Japanese sentence optimaztion with 【 character)
			local specialIndex = string.find(sentence1, "【")
			if (specialIndex ~= nil) then
				bigStyle = true;
				local beginning = string.sub(sentence1, 1, specialIndex);
				local ending = string.sub(sentence1, specialIndex);
				sentence1 = beginning .. " \n\n " .. ending; -- spaces are needed, otherwise strange circle will show up.
			else
			
				if (string.len(sentence1) > LINEBREAKLIMIT) then
					local beginning = string.sub(sentence1, 1, LINEBREAKLIMIT);
					local ending = string.sub(sentence1, LINEBREAKLIMIT + 1);
					sentence1 = beginning .. " \n " .. ending;
				end
			end
			
			sentence2 = trim(sentence[sentenceIndex][2]);
			if (string.len(sentence2) > SMALLFONTLIMIT) then
				bigStyle = false;
			end
		
			if (string.len(sentence2) > LINEBREAKLIMIT) then
				local beginning = string.sub(sentence2, 1, LINEBREAKLIMIT);
				local ending = string.sub(sentence2, LINEBREAKLIMIT + 1);
				sentence2 = beginning .. " \n " .. ending;
			end
			
			showedSentence = sentence1 .. "\n\n" .. sentence2;
	end
	
	-- Show sentence if exist
	if (showedSentence ~= "") then
		local extraFont = 0;
		local playWav = false;
		
		-- Play sound
		if (sentence[sentenceIndex][3] ~= nil) then -- if sound file location is told (location is same as sentence.csv)
			
			local soundFile = currentSentencePath .. trim(sentence[sentenceIndex][3]) .. ".wav";
			local file9 = io.open(soundFile, "r");

			if file9 ~= nil then -- file exist sound file may be played
				Wav.load(soundFile, 0)
				Wav.play(false, 0)
				playWav = true;
				file9:close()
			end
		end
	
		while true do
			System.draw()
			
			-- additional logic to avoid flickery
		System.draw()
		screen:blit(0, 0, background);

		if (userOptions[3] == "true") then
			ifontLtn:setStyle(1.0, gray, darkgray, IntraFont.ALIGN_CENTER);
			ifontLtn:print(240, 86, "Press CROSS to continue."); -- translation
		end

		ifont:setStyle(1.0 + questionFontSize, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		ifontSecondary:setStyle(1.0 + questionFontSize, currentColor, darkgray, IntraFont.ALIGN_CENTER);

		if (mode == 1) then
		
			-- if too long text, should smallen the font
			question1 = trim(word[question][#word[question] - 1]);
			if (string.len(question1) > SMALLFONTLIMIT) then
				ifont:setStyle(0.6 + questionFontSize, currentColor, darkgray, IntraFont.ALIGN_CENTER);
				ifontSecondary:setStyle(0.6 + questionFontSize, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			end
		
			if (string.len(question1) > LINEBREAKLIMIT) then
				local beginning = string.sub(question1, 1, LINEBREAKLIMIT);
				local ending = string.sub(question1, LINEBREAKLIMIT + 1);
				question1 = beginning .. " \n " .. ending;
			end
		
			if (string.find(question1, ".png")) then -- image query
				if (imageLoaded == false) then
			
					local file8 = io.open(question1);
					if (file8 == nil ) then
						questionImage = false;
					else
						questionImage = Image.load(question1);
						imageLoaded = true;
						file8:close()
						getImageXY(question);
					end
				end
				if (questionImage == false) then
					ifontLtn:print(240, 56, "Not found: " .. question1);
				else
					screen:blit(imageX,imageY,questionImage) -- image was found, show it
					--screen:blit(30, 118, square);
					--screen:blit(30, 146, triangle);
					--screen:blit(30, 174, circle);
					--screen:blit(30, 202, cross);
				end
	
			else
				ifont:print(240, 56, question1); -- translation
			end
		elseif (mode == 2) then
		
			question1 = trim(word[question][show]);
		
			-- if wrong mode (comes from mode 2 to picture questionaire)
			if (string.find(question1, ".png")) then -- image query
				mode = 1;
				randomize();
			end
		
			-- If item has no text, show it in another format if possible
			counts = #word[1] - 2;
			counter = 0;
			tempShow = show;
		
			while (counter <= counts) do
		
				if (string.len(question1) == 0 ) then
			
					tempShow = tempShow - 1;
					if (tempShow == 0) then
						tempShow = #word[question] - 2;
					end
			
					question1 = trim(word[question][tempShow])
					counter = counter + 1;
				else
					break;
				end
			end
		
			if (string.len(question1) > SMALLFONTLIMIT) then
				ifont:setStyle(0.6 + questionFontSize, currentColor, darkgray, IntraFont.ALIGN_CENTER);
				ifontSecondary:setStyle(0.6 + questionFontSize, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			end
		
			-- optimizing for japanese strings, if too long line break
			if (string.len(question1) > LINEBREAKLIMIT) then
				local beginning = string.sub(question1, 1, LINEBREAKLIMIT);
				local ending = string.sub(question1, LINEBREAKLIMIT + 1);
				question1 = beginning .. " \n " .. ending;
			end
		
			ifont:print(240, 56, question1);
		
		end
		-- additional logic ends
			
			screen:blit(0, 116, sentencebox);
			screen:blit(199,238, longbutton);
			
			-- Show a key of replay
			if (playWav) then
				ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
				ifontLtn:print(10, 236, "Press Square to \n replay sound");
			end
			
			if (bigStyle) then
				ifont:setStyle(1.0 + extraFont, currentColor, darkgray, IntraFont.ALIGN_CENTER);
				ifontSecondary:setStyle(1.0 + extraFont, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			else
				ifont:setStyle(0.6 + extraFont, currentColor, darkgray, IntraFont.ALIGN_CENTER);
				ifontSecondary:setStyle(0.6 + extraFont, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			end
			
			ifont:print(240, 146, showedSentence);
			System.endDraw()
			screen.flip()
			
			local pad = Controls.readPeek()
		
			if (pad:triangle() or pad:circle() or pad:cross()) then
			
				if (playWav) then -- free memory
					Wav.unload(0);
				end
			
				screen.waitVblankStart(20);
				break;
			elseif (pad:square()) then
				screen.waitVblankStart(20);
				if (playWav) then
					Wav.play(false, 0)
				else
					break; -- if now wav-file return
				end
			
			elseif (pad:analogY() < -100) then
				screen.waitVblankStart(1); -- added
				extraFont = extraFont + 0.1;
				if (extraFont > 0.4) then
					extraFont = 0.4;
				end
				if (bigStyle and extraFont > 0) then
					extraFont = 0;
				end
				
			elseif (pad:analogY() > 100) then
				screen.waitVblankStart(1); -- added
				extraFont = extraFont - 0.1;
				if (bigStyle and extraFont < -0.4) then
					extraFont = -0.4;
				end
				
				if (bigStyle == false and extraFont < 0) then
					extraFont = 0;
				end
				
			elseif pad:home() then
				break; -- if no wait force exit
			end
		end
	end
end

storeSentences = function(path) -- path include file name also
	local reversePath = string.reverse(path);
	local reverseIndex = string.find(reversePath, "/")
	local fileName = "sentence.csv"
	
	if (reverseIndex == nil) then -- path is root of AnyLanguageStudy
		-- fileName is sentence.csv then
		if (currentSentencePath == "") then -- no need reload sentence.csv it's already loaded
			return;
		end
		currentSentencePath = ""; -- root
	else
		local trueIndex = string.len(path) - reverseIndex + 1;
		
		if (currentSentencePath == string.sub(path, 0, trueIndex)) then
			return; -- no need for reloading
		end
		
		currentSentencePath = string.sub(path, 0, trueIndex);
		fileName = string.sub(path, 0, trueIndex) .. "sentence.csv";
	end
	
	-- clear current sentence list
	sentence = {}
	
	file7 = io.open(fileName);
	
	if (file7 == nil ) then
		-- no sentences for current set
		currentSentencePath = "none";
		return
	end
	
	-- Parse sentences
	i = 1;
for line in file7:lines() do

	if (line ~= nil and string.len(trim(line)) > 0 and string.sub(line, 1, 1) ~= "#" and string.find(line, ";") ~= nil) then -- ignore empty sentences and commented lines or sentences without ;
	
	local index = 1;
	local str = line;
	local tempLine = "";
	
	while index ~= nil do
		index = string.find(str, ";", index)
	
		if (index == 1) then
			tempLine = tempLine .. " ";
		end
	
		tempLine = tempLine .. str:sub(1, index);
		
		if (index ~= nil) then
			str = str:sub(index + 1);
			index = 1;
		end
	end
  
	line = tempLine;
  
	sentence[i] = line:splitSentences("[^;]+");
	
	i = i + 1;
	end
end

	file7:close()
	
end

checkKnownWords = function()
if (userOptions[5] == "0") then
	allKnown = 1 -- 1 all is learned; 0 all is not learned
	setKnown = 0
	i = 0;
	while (i < #word) do
		i = i + 1;
		if (word[i][#word[1]] == "false") then
			allKnown = 0;
			break;
		end
	end
else
	allKnown = 0;
	setKnown = 1;
	i = askMin;
	
	while (i < askMax) do
		i = i + 1;
		if (word[i][#word[1]] == "false") then
			setKnown = 0;
			break;
		end
	end
end

end

saveOptions = function()

	optionFile = "options.ini";
	file6 = io.open(optionFile,"w")
				
	i = 0;
	while (i < #userOptions) do
		i = i + 1;
		file6:write(userOptions[i] .. ";");
	end
				
	file6:close();

end

loadOptions = function()
	local file6 = io.open("options.ini", "r");

	if not file6 then
		return; -- no options file stored
	end
	
	local line = file6:read();
	
	userOptions = line:splitOptions("[^;]+");
	
	if (#userOptions ~= 7) then
		-- corrupted data
		userOptions = {"true", "true", "true", "0", "0", "white", "1"}
	end
	
	file6:close();
	setFontColor()
end

waitShowAnswer = function(waitLimit)

local waitEternity = false
local imageLoaded = false;
questionImage = nil;

if (waitLimit == 100) then
	waitEternity = true
end

local starttime = os.clock()
--screen:clear()
while os.clock() - starttime < waitLimit or waitEternity do
System.draw()

screen:blit(0, 0, background);
--screen:blit(30, 118, square);
--screen:blit(30, 146, triangle);
screen:blit(triangleX, triangleY, triangle);
screen:blit(squareX, squareY, square);
screen:blit(circleX, circleY, circle);
screen:blit(crossX, crossY, cross);

	if (mode == 1) then
		-- if too long text, should smallen the font
		question1 = trim(word[question][#word[question] - 1]);
		if (string.len(question1) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			ifontSecondary:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		if (string.len(question1) > LINEBREAKLIMIT) then
			local beginning = string.sub(question1, 1, LINEBREAKLIMIT);
			local ending = string.sub(question1, LINEBREAKLIMIT + 1);
			question1 = beginning .. " \n " .. ending;
		end
		
		if (string.find(question1, ".png")) then -- image query
			if (imageLoaded == false) then
			
				local file8 = io.open(question1);
				if (file8 == nil ) then
					questionImage = false;
				else
					questionImage = Image.load(question1);
					imageLoaded = true;
					file8:close()
					getImageXY(question);
				end
			end
			if (questionImage == false) then
				ifontLtn:print(240, 56, "Not found: " .. question1);
			else
				screen:blit(imageX,imageY,questionImage) -- image was found, show it
				--screen:blit(30, 118, square);
				--screen:blit(30, 146, triangle);
				screen:blit(triangleX, triangleY, triangle);
				screen:blit(squareX, squareY, square);
				screen:blit(circleX, circleY, circle);
				screen:blit(crossX, crossY, cross);
			end
	
		else
			ifont:print(240, 56, question1); -- translation
		end
		
	elseif (mode == 2) then
		
		question1 = trim(word[question][show]);
		
		-- if wrong mode (comes from mode 2 to picture questionaire)
		if (string.find(question1, ".png")) then -- image query
			mode = 1;
			randomize();
		end
		
		-- If item has no text, show it in another format if possible
		counts = #word[1] - 2;
		counter = 0;
		tempShow = show;
		
		while (counter <= counts) do
		
			if (string.len(question1) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[question] - 2;
				end
			
				question1 = trim(word[question][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
		if (string.len(question1) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			ifontSecondary:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(question1) > LINEBREAKLIMIT) then
			local beginning = string.sub(question1, 1, LINEBREAKLIMIT);
			local ending = string.sub(question1, LINEBREAKLIMIT + 1);
			question1 = beginning .. " \n " .. ending;
		end
		
		ifont:print(240, 56, question1);
		
	end
	ifontLtn:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
	ifontLtn:print(100, 255, "Mode: " .. mode .. " / Show: " .. show ); -- show mode and show
	ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
	ifontLtn:print(10, 267, "Range: " .. askMin .. "-" .. askMax .. " / " .. #word .. " " .. listName); -- show range
	ifontLtn:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
	if (allKnown == 1) then
			ifontLtn:print(395, 260, "All once correct");
	elseif (setKnown == 1) then
			ifontLtn:print(395, 260, "Set once correct");
	end
	
	local pad = Controls.readPeek()
		
		if (pad:cross() or pad:triangle() or pad:circle() or pad:square()) then
			ifont:setStyle(1.0 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			ifontSecondary:setStyle(1.0 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			screen.waitVblankStart(20);
			break;
		elseif pad:right() then
			if (show == #word[1] - 2) then
				show = 1;
				screen.flip();
				screen.waitVblankStart(20);
			else
				show = show + 1;
				screen.flip();
				screen.waitVblankStart(20);
			end
				
		elseif pad:left() then
			if (show == 1) then
				show = #word[1] - 2;
				screen.flip();
				screen.waitVblankStart(20);
			else
				show = show - 1;
				screen.flip();
				screen.waitVblankStart(20);
			end
		
		elseif pad:up() and imageLoaded == false then
			if (mode == 1) then
				save(question, first, second, third, fourth, show, askLevel, mode);
				mode = 2;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				starttime = os.clock()
				screen.waitVblankStart(20);
			else
				save(question, first, second, third, fourth, show, askLevel, mode);
				mode = 1;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				starttime = os.clock()
				screen.waitVblankStart(20);
			end;
			
		elseif pad:down() and imageLoaded == false then
			if (mode == 1) then
				save(question, first, second, third, fourth, show, askLevel, mode);
				mode = 2;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				starttime = os.clock()
				screen.waitVblankStart(20);
			else
				save(question, first, second, third, fourth, show, askLevel, mode);
				mode = 1;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				starttime = os.clock()
				screen.waitVblankStart(20);
			end;
		
		elseif (pad:analogY() < -100 ) then
			screen.waitVblankStart(1); -- added
			extraQ = extraQ + 0.1;
			if (extraQ > 2) then
				extraQ = 2;
			end
		
		elseif (pad:analogY() > 100 ) then
			screen.waitVblankStart(1); -- added
			extraQ = extraQ - 0.1
			if (extraQ < 0) then
				extraQ = 0
			end
		
		elseif (pad:analogX() < - 100 and userOptions[5] ~= "0") then
			askLevel = askLevel - 1;
			if (userOptions[5] ~= "break") then
				if (askLevel < 0) then
					askLevel = math.ceil(#word / userOptions[5]) - 1;
				end
			else
				if (askLevel < 0) then
					askLevel = #breakList - 1;
				end
			end
			
			calculateMinMax()
			screen.waitVblankStart(20);
			
		elseif (pad:analogX() > 100 and userOptions[5] ~= "0") then
			askLevel = askLevel + 1;
			if (userOptions[5] ~= "break") then
				if (askLevel > (math.ceil(#word / userOptions[5]) - 1)) then
					askLevel = 0;
				end
			else
				if (askLevel + 1 > #breakList) then
					askLevel = 0;
				end
			end
			calculateMinMax()
			screen.waitVblankStart(20);	
		
		elseif pad:select() then
			save(question, first, second, third, fourth, show, askLevel, mode)
			screen.waitVblankStart(20);
			if (questionImage ~= nil and questionImage ~= false) then -- free memory
				Image.free(questionImage)
			end
			askLevel = 0;
			--initialize();
			selectDictionary()
		
		elseif pad:home() then
				break; -- if no wait force exit
		
        elseif pad:start() then
			save(question, first, second, third, fourth, show, askLevel, mode)
			screen.waitVblankStart(20);
			openOptions();
			
		elseif pad:r() then
			result = System.msgDialog("Do you want to clear current known list? (Range " .. askMin .. "-" .. askMax .. ")", true, drawFunc)
			if (result==System.MSGDIALOG_RESULT_YES) then
				clearResults(word, askMin, askMax);
				allKnown = 0;
				setKnown = 0;
				save(question, first, second, third, fourth, show, askLevel, mode);
			end
			
		elseif pad:l() then
			screen.waitVblankStart(20);
			save(question, first, second, third, fourth, show, askLevel, mode)
			search()
		end
	
	ifont:setStyle(1.0 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
	ifontSecondary:setStyle(1.0 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
    System.endDraw();
    screen.flip();
	
end
	
end

waitBeforeShowing = function()
	if (userOptions[4] == "0") then
		-- don't wait
	
	elseif (userOptions[4] == "3") then
		-- wait 3 secs
		waitShowAnswer(3)
	elseif (userOptions[4] == "5") then
		-- wait 5 secs
		waitShowAnswer(5)
	elseif (userOptions[4] == "10") then
		-- wait 10 secs
		waitShowAnswer(10)
	else
		-- wait press
		waitShowAnswer(100)
	end
	
end

loadSaveData = function(currentDictionary, word, mode)
saveDictionary = currentDictionary .. mode;
	-- check file exist
	file4 = io.open(saveDictionary)
	if (file4 ~= nil) then
		i = 1;
	
		for line in file4:lines() do
			if (i > #word) then
				break;
			end
			
			if (line == "false" or line == "true") then
				word[i][#word[1]] = line;
			else
				word[i][#word[1]] = false; -- if file is corrupted.
			end
			i = i + 1;	
		end
			
		file4:close();
	else
		clearResults(word);
	end
end

calculateMinMax = function()

-- Determine how many/which is asked at the same time
if (userOptions[5] == "0") then
	askLevel = 0;
	askMin = 1;
	askMax = #word;
elseif (userOptions[5] == "10") then
	askMin = 1 + askLevel * 10;
	askMax = 10 + askLevel * 10;
	if (askMax > #word) then
		askMax = #word
	end
elseif (userOptions[5] == "20") then
	askMin = 1 + askLevel * 20;
	askMax = 20 + askLevel * 20;
	if (askMax > #word) then
		askMax = #word
	end

elseif (userOptions[5] == "50") then
	askMin = 1 + askLevel * 50;
	askMax = 50 + askLevel * 50;
	if (askMax > #word) then
		askMax = #word
	end
elseif (userOptions[5] == "100") then
	askMin = 1 + askLevel * 100;
	askMax = 100 + askLevel * 100;
	if (askMax > #word) then
		askMax = #word
	end
else
	--if (breakList[askLevel + 1][1] ~= nil) then
	if (#breakList > 1) then
		askMin = breakList[askLevel + 1][1];
		askMax = breakList[askLevel + 1][2];
	else
		askLevel = 0;
		askMin = 1;
		askMax = #word;
	end
end

-- Get sub name for dictionary in break mode
listName = getNameList();

end

getNameList = function()
	if (userOptions[5] == "break") then
		if (nameList[askLevel + 1] ~= nil) then
			return nameList[askLevel + 1];
		end
	end
	
	return "";
end

randomize = function()

calculateMinMax()

first = math.random(askMin,askMax);

times = 0;

-- try to avoid offering same answers again and again.
if (word[first][#word[1]] == "true") then
	while (word[first][#word[1]] == "true" and times < 50) do
		first = math.random(askMin,askMax);
		times = times + 1;
	end
end

second = math.random(askMin,askMax);

times = 0;

-- try to avoid offering same answers again and again.
if (word[second][#word[1]] == "true") then
	while (word[second][#word[1]] == "true" and times < 50) do
		second = math.random(askMin,askMax);
		times = times + 1;
	end
end

times = 0;

while (second == first) do 
	second = math.random(askMin,askMax);
	if (times > 100) then -- this is needed as this may me an infinite loop
		second = first;
		break;
	end
	times = times + 1;
end

third = math.random(askMin,askMax);

times = 0;

-- try to avoid offering same answers again and again.
if (word[third][#word[1]] == "true") then
	while (word[third][#word[1]] == "true" and times < 50) do
		third = math.random(askMin,askMax);
		times = times + 1;
	end
end

times = 0;

while (third == second or third == first) do 
	third = math.random(askMin,askMax);
	if (times > 100) then -- this is needed as this may me an infinite loop
		third = first;
		break;
	end
	times = times + 1;
end

fourth = math.random(askMin,askMax);

times = 0;

-- try to avoid offering same answers again and again.
if (word[fourth][#word[1]] == "true") then
	while (word[fourth][#word[1]] == "true" and times < 50) do
		fourth = math.random(askMin,askMax);
		times = times + 1;
	end
end

times = 0;

while (fourth == third or fourth == second or fourth == first) do
	fourth = math.random(askMin,askMax);
	if (times > 100) then -- this is needed as this may me an infinite loop
		fourth = first;
		break;
	end
	times = times + 1;
end

times = 0;

while true do
question = math.random(1,4);

	if (question == 1) then
		if (word[first][#word[1]] == "false" or times == 50) then
			question = first;
			break;
		end
	elseif (question == 2) then
		if (word[second][#word[1]] == "false" or times == 50) then
			question = second;
			break;
		end
	elseif (question == 3) then
		if (word[third][#word[1]] == "false" or times == 50) then
			question = third;
			break;
		end
	else
		if (word[fourth][#word[1]] == "false" or times == 50) then
			question = fourth;
			break;
		end
	end
	
	times = times + 1;
end

checkKnownWords()

-- set start time how long answering takes
questionStartTime = os.clock();
questionEndTime = 0;
	
end

clearResults = function(word, askMin, askMax)

	if (askMin ~= nil and askMax ~= nil) then
	-- clear only specific range
		i = askMin;
		while (i <= askMax) do
			word[i][#word[i]] = "false";
			i = i + 1;
		end
	else
	-- clear all known words
		i = 1;
		while (i <= #word) do
			word[i][#word[i]] = "false";
			i = i + 1;
		end
	end

end

openOptions = function()

	local currentX = 1;
	local currentY = 1;
	previousOptions = table.copy(userOptions)
	
	previewStyle = background;
	previewShortbutton = shortbutton;
	previewLongbutton = longbutton;
	previewOptions = options;
	
	local freePreviewStyle = false;
	
	while true do
		local focus = {currentY,currentX} -- high level, selection
		local pad = Controls.readPeek()

		System.draw();
		screen:clear();
		screen:blit(0, 0, previewStyle);
		screen:blit(0, 0, previewOptions);
		
		ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
		ifontLtn:print(240, 42, "Global Options");
		
		-- SHOW SELECTOR
		if (focus[1] == 1) then
			if (focus[2] == 1) then
				screen:blit(240, 70, previewShortbutton)
			else
				screen:blit(270, 70, previewShortbutton)
			end
			
		elseif (focus[1] == 2) then
			if (focus[2] == 1) then
				screen:blit(240, 90, previewShortbutton)
			else
				screen:blit(270, 90, previewShortbutton)
			end
		
		elseif (focus[1] == 3) then
			if (focus[2] == 1) then
				screen:blit(240, 110, previewShortbutton)
			else
				screen:blit(270, 110, previewShortbutton)
			end
		
		elseif (focus[1] == 4) then
			if (focus[2] == 1) then
				screen:blit(240, 130, previewShortbutton)
			elseif(focus[2] == 2) then
				screen:blit(270, 130, previewShortbutton)
			elseif(focus[2] == 3) then
				screen:blit(300, 130, previewShortbutton)
			elseif(focus[2] == 4) then
				screen:blit(330, 130, previewShortbutton)
			else
				screen:blit(360, 130, previewShortbutton)
			end
		
		elseif (focus[1] == 5) then
			if (focus[2] == 1) then
				screen:blit(240, 150, previewShortbutton)
			elseif(focus[2] == 2) then
				screen:blit(270, 150, previewShortbutton)
			elseif(focus[2] == 3) then
				screen:blit(300, 150, previewShortbutton)
			elseif(focus[2] == 4) then
				screen:blit(330, 150, previewShortbutton)
			elseif(focus[2] == 5) then
				screen:blit(360, 150, previewShortbutton)
			else
				screen:blit(390, 150, previewShortbutton)
			end
		
		elseif (focus[1] == 6) then
			if (focus[2] == 1) then
				screen:blit(240, 170, previewShortbutton)
			elseif(focus[2] == 2) then
				screen:blit(278, 170, previewShortbutton)
			elseif(focus[2] == 3) then
				screen:blit(308, 170, previewShortbutton)
			elseif(focus[2] == 4) then
				screen:blit(350, 170, previewShortbutton)
			else
				screen:blit(390, 170, previewShortbutton)
			end
		
		elseif (focus[1] == 7) then
			screen:blit(240, 190, previewShortbutton)
		
		elseif (focus[1] == 8) then
			if (focus[2] == 1) then
				screen:blit(71, 238, previewLongbutton)
			elseif(focus[2] == 2) then
				screen:blit(186, 238, previewLongbutton)
			else
				screen:blit(302, 238, previewLongbutton)
			end
		end
		
		-- FIRST OPTION
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(40, 66, "Show right answer after wrong");
		
		if (userOptions[1] == "true") then
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		else
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
		end
	
		ifontLtn:print(240, 66, "YES");
		
		if (userOptions[1] == "true") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
		else
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		end
		
		ifontLtn:print(270, 66, "NO");
		-- SECOND OPTION
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);	
		ifontLtn:print(40, 86, "Show sentence after answer");
		
		if (userOptions[2] == "true") then
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		else
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
		end
	
		ifontLtn:print(240, 86, "YES");
		
		if (userOptions[2] == "true") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
		else
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		end
		
		ifontLtn:print(270, 86, "NO");
		
		-- THIRD OPTION
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(40, 106, "Wait press after right answer");
		
		if (userOptions[3] == "true") then
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		else
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
		end
	
		ifontLtn:print(240, 106, "YES");
		
		if (userOptions[3] == "true") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
		else
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		end
		
		ifontLtn:print(270, 106, "NO");
		
		-- FOURTH OPTION
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(40, 126, "Wait before choices");
		
		if (userOptions[4] == "0") then
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 126, "0s");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(270, 126, "3s");
			ifontLtn:print(300, 126, "5s");
			ifontLtn:print(330, 126, "10s");
			ifontLtn:print(360, 126, "Press");
		
		elseif (userOptions[4] == "3") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 126, "0s");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(270, 126, "3s");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(300, 126, "5s");
			ifontLtn:print(330, 126, "10s");
			ifontLtn:print(360, 126, "Press");
		
		elseif (userOptions[4] == "5") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 126, "0s");
			ifontLtn:print(270, 126, "3s");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(300, 126, "5s");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(330, 126, "10s");
			ifontLtn:print(360, 126, "Press");
			
		elseif (userOptions[4] == "10") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 126, "0s");
			ifontLtn:print(270, 126, "3s");
			ifontLtn:print(300, 126, "5s");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(330, 126, "10s");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(360, 126, "Press");
		else
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 126, "0s");
			ifontLtn:print(270, 126, "3s");
			ifontLtn:print(300, 126, "5s");
			ifontLtn:print(330, 126, "10s");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(360, 126, "Press");
		end
		-- FIFTH OPTION
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(40, 146, "Set range");
		
		if (userOptions[5] == "0") then
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 146, "ALL");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(270, 146, "10");
			ifontLtn:print(300, 146, "20");
			ifontLtn:print(330, 146, "50");
			ifontLtn:print(360, 146, "100");
			ifontLtn:print(390, 146, "[break]");
		
		elseif (userOptions[5] == "10") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 146, "ALL");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(270, 146, "10");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(300, 146, "20");
			ifontLtn:print(330, 146, "50");
			ifontLtn:print(360, 146, "100");
			ifontLtn:print(390, 146, "[break]");
		
		elseif (userOptions[5] == "20") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 146, "ALL");
			ifontLtn:print(270, 146, "10");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(300, 146, "20");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(330, 146, "50");
			ifontLtn:print(360, 146, "100");
			ifontLtn:print(390, 146, "[break]");
			
		elseif (userOptions[5] == "50") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 146, "ALL");
			ifontLtn:print(270, 146, "10");
			ifontLtn:print(300, 146, "20");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(330, 146, "50");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(360, 146, "100");
			ifontLtn:print(390, 146, "[break]");
		elseif (userOptions[5] == "100") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 146, "ALL");
			ifontLtn:print(270, 146, "10");
			ifontLtn:print(300, 146, "20");
			ifontLtn:print(330, 146, "50");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(360, 146, "100");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(390, 146, "[break]");
		else
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 146, "ALL");
			ifontLtn:print(270, 146, "10");
			ifontLtn:print(300, 146, "20");
			ifontLtn:print(330, 146, "50");
			ifontLtn:print(360, 146, "100");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(390, 146, "[break]");
		end
		
		-- SIXTH OPTION
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(40, 166, "Font color");
		
		if (userOptions[6] == "white") then
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 166, "White");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(278, 166, "Blue");
			ifontLtn:print(308, 166, "Yellow");
			ifontLtn:print(350, 166, "Green");
			ifontLtn:print(390, 166, "Red");
		
		elseif (userOptions[6] == "blue") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 166, "White");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(278, 166, "Blue");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(308, 166, "Yellow");
			ifontLtn:print(350, 166, "Green");
			ifontLtn:print(390, 166, "Red");
		
		elseif (userOptions[6] == "yellow") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 166, "White");
			ifontLtn:print(278, 166, "Blue");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(308, 166, "Yellow");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(350, 166, "Green");
			ifontLtn:print(390, 166, "Red");
			
		elseif (userOptions[6] == "green") then
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 166, "White");
			ifontLtn:print(278, 166, "Blue");
			ifontLtn:print(308, 166, "Yellow");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(350, 166, "Green");
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(390, 166, "Red");
		else
			ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(240, 166, "White");
			ifontLtn:print(278, 166, "Blue");
			ifontLtn:print(308, 166, "Yellow");
			ifontLtn:print(350, 166, "Green");
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			ifontLtn:print(390, 166, "Red");
		end
		
		-- SEVENTH OPTION
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(40, 186, "Style");
		
		
		ifontLtn:setStyle(0.6, red, darkgray, IntraFont.ALIGN_LEFT);
		
		if (userOptions[7] == previousOptions[7]) then
			ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
		end
		
		ifontLtn:print(240, 186, "<" .. userOptions[7] .. ">");
		
		ifontLtn:setStyle(0.6, lightblue, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(40, 203, "Select option with CROSS and press Save");
		
		if (pad:start()) then
			screen.waitVblankStart(20);
			userOptions = previousOptions;
			break;
		
		elseif pad:home() then
			--saveSelection()
			System.quit();
		
		elseif(pad:right() or pad:analogX() > 100) then
			currentX = currentX + 1;
			
			if ((currentY == 1 or currentY == 2 or currentY == 3) and currentX > 2) then
				currentX = 1;
			elseif((currentY == 4 or currentY == 6) and currentX > 5) then
				currentX = 1;
			elseif(currentY == 5 and currentX > 6) then
				currentX = 1;
			elseif(currentY == 7) then
				currentX = 1;
				userOptions[7] = tostring(tonumber(userOptions[7]) + 1);
				
				-- check folder exist by reading one image
				local file = io.open("images/style" .. userOptions[7] .. "/background.png", "r");
				
				if file then
				-- style change can be accepted
					if (freePreviewStyle) then
						Image.free(previewStyle)
						Image.free(previewShortbutton)
						Image.free(previewLongbutton)
						Image.free(previewOptions)
					end
				freePreviewStyle = true;
				previewStyle = Image.load("images/style" .. userOptions[7] .. "/background.png");
				previewShortbutton = Image.load("images/style" .. userOptions[7] .. "/shortbutton.png");
				previewLongbutton = Image.load("images/style" .. userOptions[7] .. "/longbutton.png");
				previewOptions = Image.load("images/style" .. userOptions[7] .. "/options.png");
				file:close()
				else
					userOptions[7] = tostring(tonumber(userOptions[7]) - 1);
				end
	
			elseif(currentY == 8 and currentX > 3) then
				currentX = 1;
			end
			screen.waitVblankStart(20);
		
		elseif(pad:left() or pad:analogX() < -100) then
			currentX = currentX - 1;
			
			if ((currentY == 1 or currentY == 2 or currentY == 3) and currentX < 1) then
				currentX = 2;
			elseif((currentY == 4 or currentY == 6) and currentX < 1) then
				currentX = 5;
			elseif(currentY == 5 and currentX < 1) then
				currentX = 6;
			elseif(currentY == 7) then
				currentX = 1;
				userOptions[7] = tostring(tonumber(userOptions[7]) - 1);
				if (userOptions[7] == "0") then
					userOptions[7] = "1";
				else
					-- assume new style exist
					if (freePreviewStyle) then
						Image.free(previewStyle)
						Image.free(previewShortbutton)
						Image.free(previewLongbutton)
						Image.free(previewOptions)
					end
					freePreviewStyle = true;
					previewStyle = Image.load("images/style" .. userOptions[7] .. "/background.png");
					previewShortbutton = Image.load("images/style" .. userOptions[7] .. "/shortbutton.png");
					previewLongbutton = Image.load("images/style" .. userOptions[7] .. "/longbutton.png");
					previewOptions = Image.load("images/style" .. userOptions[7] .. "/options.png");
				end
			elseif(currentY == 8 and currentX < 1) then
				currentX = 3;
			end
			screen.waitVblankStart(20);
		
		elseif(pad:down() or pad:analogY() > 100) then
			currentX = 1;
			currentY = currentY + 1;
			
			if (currentY > 8) then
				currentY = 1;
			end
			screen.waitVblankStart(20);
		
		elseif(pad:up() or pad:analogY() < -100) then
			currentX = 1;
			currentY = currentY - 1;
			
			if (currentY < 1) then
				currentY = 8;
			end
			screen.waitVblankStart(20);
		-- Choose option
		elseif(pad:cross() or pad:triangle() or pad:circle() or pad:square()) then
			if (currentX == 1 and currentY == 1) then
				userOptions[1] = "true";
			elseif (currentX == 2 and currentY == 1) then
				userOptions[1] = "false";
			elseif (currentX == 1 and currentY == 2) then
				userOptions[2] = "true";
			elseif (currentX == 2 and currentY == 2) then
				userOptions[2] = "false";
			elseif (currentX == 1 and currentY == 3) then
				userOptions[3] = "true";
			elseif (currentX == 2 and currentY == 3) then
				userOptions[3] = "false";	
			elseif (currentX == 1 and currentY == 4) then
				userOptions[4] = "0";
			elseif (currentX == 2 and currentY == 4) then
				userOptions[4] = "3";
			elseif (currentX == 3 and currentY == 4) then
				userOptions[4] = "5";
			elseif (currentX == 4 and currentY == 4) then
				userOptions[4] = "10";
			elseif (currentX == 5 and currentY == 4) then
				userOptions[4] = "100";
			elseif (currentX == 1 and currentY == 5) then
				userOptions[5] = "0";
			elseif (currentX == 2 and currentY == 5) then
				userOptions[5] = "10";
			elseif (currentX == 3 and currentY == 5) then
				userOptions[5] = "20";
			elseif (currentX == 4 and currentY == 5) then
				userOptions[5] = "50";
			elseif (currentX == 5 and currentY == 5) then
				userOptions[5] = "100";
			elseif (currentX == 6 and currentY == 5) then
				userOptions[5] = "break";
			elseif (currentX == 1 and currentY == 6) then
				userOptions[6] = "white";
			elseif (currentX == 2 and currentY == 6) then
				userOptions[6] = "blue";
			elseif (currentX == 3 and currentY == 6) then
				userOptions[6] = "yellow";
			elseif (currentX == 4 and currentY == 6) then
				userOptions[6] = "green";
			elseif (currentX == 5 and currentY == 6) then
				userOptions[6] = "red";	
			elseif (currentX == 1 and currentY == 8) then
				-- save options
				
				if (userOptions[5] ~= previousOptions[5]) then
					
					local questionFile = "questionList";
					file = io.open(questionFile,"w")
					file:write("");
					file:close()
					
					askLevel = 0;
					if (word ~= nil) then
						calculateMinMax()
						checkKnownWords()
					end
				end
				
				local changeStyle = false;
				
				if (previousOptions[7] ~= userOptions[7]) then
					-- new style must be loaded
					changeStyle = true;
				end
				
				previousOptions = userOptions;
				
				saveOptions() -- no need for parameters userOption is global
				setFontColor()
				
				if (changeStyle) then
					freeImages()
					loadImages()
				end
				
				screen.waitVblankStart(20);
				break;
			elseif (currentX == 2 and currentY == 8) then
				-- cancel
				screen.waitVblankStart(20);
				userOptions = previousOptions;
				break;
			elseif (currentX == 3 and currentY == 8) then
				-- default
				local questionFile = "question";
				file = io.open(questionFile,"w")
				file:write("");
				file:close()
				
				local changeStyle = false;
				
				if (userOptions[7] ~= "1") then
					changeStyle = true;
				end
				
				userOptions = {"true", "true", "true", "0", "0", "white", "1"}
				askLevel = 0;
				saveOptions()
				setFontColor()
				
				if (changeStyle) then
					freeImages()
					loadImages()
				end
				
				if (word ~= nil) then
					calculateMinMax()
					checkKnownWords()
				end
				screen.waitVblankStart(20);
				break;
			end
			screen.waitVblankStart(20);
		
		-- Open menu
		elseif pad:select() then
			userOptions = previousOptions;
			screen.waitVblankStart(20);
			if (questionImage ~= nil and questionImage ~= false) then -- free memory
				Image.free(questionImage)
			end
			askLevel = 0;
			--initialize();
			--saveSelection()
			selectDictionary()
		
		end
		
		System.endDraw();
		screen.flip();
	end

end

getFilename = function(fullPath)

local reversePath = string.reverse(fullPath);
local reverseIndex = string.find(reversePath, "/")
local nameIndex = 0;
if (reverseIndex ~= nil) then
	nameIndex = string.len(fullPath) - reverseIndex + 1;
end
local csvIndex = string.find(fullPath, ".csv")

	if (csvIndex ~= nil) then
		return string.sub(fullPath, nameIndex + 1, csvIndex - 1)
	else
		return string.sub(fullPath, nameIndex + 1)
	end

end

jumpMenu = function()
	
	local quickSelection = currentSubset;
	local extra = 0;
	local MAX = 10;
	
	if (quickSelection > MAX) then
		extra = quickSelection - MAX;
	end
	
	while true do
	
		System.draw()
		screen:fillRect(0,0,240,272,darkgray)

		ifontLtn:setStyle(0.6, lightblue, darkgray, IntraFont.ALIGN_LEFT);
	
		ifontLtn:print(20, 20, "Quick Jump Menu");
		ifontLtn:print(20, 240, "Cross  - Jump");
		ifontLtn:print(20, 260, "Circle - Cancel");
	
		local j = 0 + extra;
		while (j < #dictionarySubset and j < MAX + extra) do
			j = j + 1;
		
			if (j == quickSelection) then
				ifontLtn:setStyle(0.6, lime, darkgray, IntraFont.ALIGN_LEFT);
			else
				ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
			end
		
			ifontLtn:print(20, (j - extra) * 20 + 20, dictionarySubset[j]);
		end
				
		System.endDraw()
		screen.flip()
			
		local pad2 = Controls.readPeek()
				
		if (pad2:circle()) then
			screen.waitVblankStart(20);
			return;
		elseif pad2:cross() then
			screen.waitVblankStart(20);
			
			currentSubset = quickSelection
			dictionary = formSubset()
			selection = 1;
			page = 0;
			
			return;
		
		elseif pad2:r() then
			quickSelection = #dictionarySubset
			
			if (quickSelection > MAX) then
				extra = quickSelection - MAX;
			end
			
		elseif pad2:l() then
			quickSelection = 1;
			extra = 0;
		
		elseif pad2:up() or pad2:analogY() < -100 then
			quickSelection = quickSelection - 1;
		
			if (quickSelection < 1) then
				quickSelection = #dictionarySubset
			end
			
			if (quickSelection > MAX - extra) then
				extra = extra - 1;
			end
			
			if (extra < 0) then
				extra = #dictionarySubset - MAX;
			end
		
			screen.waitVblankStart(30);
		elseif pad2:down() or pad2:analogY() > 100 then
			quickSelection = quickSelection + 1;
		
			if (quickSelection > #dictionarySubset) then
				quickSelection = 1
				extra = 0;
			end
			
			if (quickSelection > MAX + extra) then
				extra = extra + 1;
			end
			
			screen.waitVblankStart(30);
		elseif pad2:home() then
			System.quit();
		end
	end
end

menu = function(--[[dictionary]])

	while true do
		
		i = 1 + (page * 10);
		local drawLevel = 1;
		
		ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
		System.draw();
		screen:blit(0, 0, background);
		
		ifontLtn:print(240, 22, "Select a word list");
		
		ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
		
		if (#dictionary > 10) then
			ifontLtn:print(30, 20, "< L");
			ifontLtn:print(450, 20, "R >");
		end
		
		while (i <= ((page + 1) * 10) and i <= #dictionary) do
			
			if (i == selection) then
				ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_CENTER);
			else
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
			end
			
			local name = getFilename(dictionary[i][3])
			ifontLtn:print(240, 20 * drawLevel + 30, name);
			i = i + 1;
			drawLevel = drawLevel + 1;
		end
		
		ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
		ifontLtn:print(400, 260, tostring(selection) .. "/" .. tostring(#dictionary));
		ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(10, 260, dictionary[selection][4]); -- show group name
		
		System.endDraw();
		screen.flip()
	
		local pad = Controls.readPeek()

        if pad:home() then
			--saveSelection()
			System.quit();
		
		elseif pad:start() then
			screen.waitVblankStart(20);
			openOptions();
			--i = 1 + (page * 10);
			--selection = i;
			screen.waitVblankStart(30);
		
		--[[elseif (pad:analogX() > 100 and #dictionarySubset > 1) then
			screen.waitVblankStart(30);
			currentSubset = currentSubset + 1;
			dictionary = formSubset()
			selection = 1;
			page = 0;]]
			
		--elseif (pad:r() or pad:right() or (pad:analogX() > 100 and #dictionarySubset == 1) ) then
		elseif (pad:r() or pad:right() or pad:analogX() > 100) then
			page = page + 1;
			if ((page * 10) + 1 > #dictionary) then
				-- next subset
				screen.waitVblankStart(30);
				currentSubset = currentSubset + 1;
				dictionary = formSubset()
				selection = 1;
				page = 0;
				
			end
			i = 1 + (page * 10);
			selection = i;
			screen.waitVblankStart(30);
		
		--[[elseif (pad:analogX() < -100 and #dictionarySubset > 1) then
			screen.waitVblankStart(30);
			currentSubset = currentSubset - 1;
			dictionary = formSubset()
			selection = 1;
			page = 0;]]
						
		--elseif (pad:l() or pad:left() or (pad:analogX() < -100 and #dictionarySubset == 1)) then
		elseif (pad:l() or pad:left() or pad:analogX() < -100) then
			page = page - 1;
			if (page < 0) then
				--[[page = math.floor(#dictionary / 10);
				if (math.floor(#dictionary % 10) == 0) then
					page = page - 1
				end]]
				
				-- previous subset
				screen.waitVblankStart(30);
				currentSubset = currentSubset - 1;
				dictionary = formSubset()
				--selection = 1;
				--page = 0;
				page = math.floor(#dictionary / 10);
				if (math.floor(#dictionary % 10) == 0) then
					page = page - 1
				end
				i = 1 + (page * 10);
				selection = i;
				
			end
			i = 1 + (page * 10);
			selection = i;
			screen.waitVblankStart(30);
			
		elseif pad:down() or pad:analogY() > 100 then
			i = 1 + (page * 10);
			selection = selection + 1;
			screen.waitVblankStart(30);
			
			if (selection == #dictionary + 1 or selection > ((page + 1) * 10)) then
				selection = 1 + (page * 10);
			end
			
		elseif pad:up() or pad:analogY() < -100 then
			i = 1 + (page * 10);
			selection = selection - 1;
			screen.waitVblankStart(30);
			
			if (selection < 1 or selection <= (page * 10)) then
				selection = (page + 1) * 10;
				if (selection > #dictionary) then
					selection = #dictionary;
				end
			end
		
		elseif pad:triangle() then
			-- quick jump menu
			jumpMenu()
			screen.waitVblankStart(20);
			screen.flip();
			
		elseif pad:square() or pad:circle() or pad:cross() then
		
			if (io.open(dictionary[selection][3]) == nil ) then
				-- dictionary was not found
				
				System.draw();
				screen:clear()
				screen:blit(0, 0, background);
				
				ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
				ifontLtn:print(240, 22, "Select a word list");
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				
				if (#dictionary > 10) then
					ifontLtn:print(30, 20, "< L");
					ifontLtn:print(450, 20, "R >");
				end
				
				ifontLtn:setStyle(1.0, red, darkgray, IntraFont.ALIGN_CENTER);
				ifontLtn:print(240, 260, "File not found");
				
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				
				drawLevel = 1;
				while (i <= ((page + 1) * 10) and i <= #dictionary) do
			
				if (i == selection) then
					ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_CENTER);
				else
					ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				end
			
				local name = getFilename(dictionary[i][3])
				ifontLtn:print(240, 20 * drawLevel + 30, name);
				i = i + 1;
				drawLevel = drawLevel + 1;
				end
		
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				ifontLtn:print(400, 260, tostring(selection) .. "/" .. tostring(#dictionary));
				ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_LEFT);
				ifontLtn:print(10, 260, dictionary[selection][4]); -- show group name
				
				System.endDraw();
				screen.flip();
				screen.waitVblankStart(30);
				
			else
				System.draw();
				--screen:clear();
				screen:blit(0, 0, background);
				
				ifontLtn:setStyle(1.0, lightblue, darkgray, IntraFont.ALIGN_CENTER);
				ifontLtn:print(240, 22, "Select a word list");
				
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				ifontLtn:print(242, 140, "Loading... Please wait.");
				
				if (#dictionary > 10) then
					ifontLtn:print(30, 20, "< L");
					ifontLtn:print(450, 20, "R >");
				end
				
				drawLevel = 1;
				while (i <= ((page + 1) * 10) and i <= #dictionary) do
			
				if (i == selection) then
					ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_CENTER);
				else
					ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				end
			
				local name = getFilename(dictionary[i][3])
				ifontLtn:print(240, 20 * drawLevel + 30, name);
				i = i + 1;
				drawLevel = drawLevel + 1;
				end
		
				ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
				ifontLtn:print(400, 260, tostring(selection) .. "/" .. tostring(#dictionary));
				ifontLtn:setStyle(0.8, lime, darkgray, IntraFont.ALIGN_LEFT);
				ifontLtn:print(10, 260, dictionary[selection][4]); -- show group name
				
				System.endDraw();
				screen.flip();
				
				-- store sentences
				storeSentences(dictionary[selection][3]);
				
				-- set charset
				loadCharset(dictionary[selection][1], dictionary[selection][2]);
				
				saveSelection() -- this was last studied list
				
				collectgarbage(); -- free memory of previous lists
				--screen.waitVblankStart(10);
				return dictionary[selection][3];
			end
		end
			
	end
end

groupDictionaries = function()
	dictionarySubset = {}
	local j = 0;
	
	local subset = "";
	
	while (j < #allDictionary) do
		j = j + 1;
		
		if (allDictionary[j][4] ~= nil) then
			subset = allDictionary[j][4];
		else
			subset = "";
		end
	
		local k = 0;
		local foundSubsetName = false;
		
		while (k < #dictionarySubset) do
			k = k + 1;
			if (dictionarySubset[k] == subset) then
				foundSubsetName = true;
			end
		end
		
		if (foundSubsetName == false) then
			-- subset name not yet added
			table.insert(dictionarySubset, subset);
		end
	end
	
	-- Organize lists alphabetically
	table.sort(dictionarySubset);
end

formSubset = function()
	dictionary = {}
	local j = 0;
	
	if (currentSubset < 1) then
		currentSubset = #dictionarySubset;
	elseif(currentSubset > #dictionarySubset) then
		currentSubset = 1;
	end
	
	local subsetName = dictionarySubset[currentSubset]
	
	while (j < #allDictionary) do
		j = j + 1;
		if (allDictionary[j][4] == subsetName) then
			table.insert(dictionary, allDictionary[j]); -- form a subset dictionary
		end
	end
	
	return dictionary;
end

initialize = function()

allDictionary = {};
i = 1;
file = io.open("dictionary.ini", "r");

if not file then
	-- dictionary.ini missing
	ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
	System.draw();
	ifontLtn:print(240, 150, "Root folder did not have dictionary.ini file. It is required!");
	System.endDraw()
	screen.flip()
	screen.waitVblankStart(150);
	System.quit();
end

for line in file:lines() do
	if ( line ~= nil and string.len(trim(line)) ~= 0 and string.sub(line, 1, 1) ~= "#") then -- dont allow spaces only or commented files
		line = line:gsub(string.char(13),""); -- file name may have unnecessary characters. If so it cannot be opened.
		local currentArray = line:splitSentences("[^;]+") -- first two are charset, then the path
		if (#currentArray > 2) then -- add only if both given, may have also group name
		
			if (#currentArray < 4) then
				table.insert(currentArray, "Unknown");
			end
		
			allDictionary[i] = currentArray;
			i = i + 1;
		end
	end
end
file:close();

if (#allDictionary == 0) then
	ifontLtn:setStyle(0.8, white, darkgray, IntraFont.ALIGN_CENTER);
	System.draw();
	ifontLtn:print(240, 150, "File dictionary.ini is empty or format is invalid.");
	System.endDraw()
	screen.flip()
	screen.waitVblankStart(150);
	System.quit();
end

groupDictionaries()
currentSubset = 1;
selection, page, currentSubset, subsetFormed = getLastFile()

if (subsetFormed == false) then
	dictionary = formSubset()
end

selectDictionary()
end

selectDictionary = function()
selectedDictionary = menu(--[[dictionary]]); -- Show items.

local normalStart = true;

if (selectedDictionary ~= previousWordList) then
previousWordList = selectedDictionary;
file2 = io.open(selectedDictionary);

i = 1;
word = {};

breakList = {};
local lastBreak = 1;

nameList = {}
listName = "";

coordinateList = {}
imageX = 0;
imageY = 0;

questionTotalTime = {0, 0}

triangleX = 30;
squareX = 30;
circleX = 30;
crossX = 30;
textAlign = IntraFont.ALIGN_CENTER;
wordX = 240;

-- Parse words
for line in file2:lines() do

	if (line ~= nil and string.len(trim(line)) > 0 and string.sub(line, 1, 1) ~= "#" and string.find(line, ";") ~= nil) then -- ignore empty words and commented lines or words without ;
	
	-- Add space if only ;a;a -situation.
	local index = 1;
	local str = line;
	local tempLine = "";
	
	while index ~= nil do
		index = string.find(str, ";", index)
	
		if (index == 1) then
			tempLine = tempLine .. " ";
		end
	
		tempLine = tempLine .. str:sub(1, index);
		
		if (index ~= nil) then
			str = str:sub(index + 1);
			index = 1;
		end
	end
  
	line = tempLine;
  
	word[i] = line:split( "[^;]+" )
	i = i + 1;
	elseif(line ~= nil and string.len(trim(line)) == 7 and trim(line) == "[break]") then
		if (lastBreak ~= i) then
			breakList[#breakList + 1] = {lastBreak, i - 1};
			lastBreak = i;
		end
	
	elseif(line ~= nil and string.len(trim(line)) >= 7 and string.find(line, "=") and string.sub(trim(line), 1, 5) == "[name" and string.sub(trim(line), string.len(trim(line))) == "]") then
		table.insert(nameList, string.sub(trim(line), string.find(trim(line), "=") + 1, string.len(trim(line)) - 1))
	elseif (line ~= nil and string.find(line, "|") and string.sub(trim(line), 1, 1) == "[" and string.sub(trim(line), string.len(trim(line))) == "]") then
		coordinateList[#coordinateList + 1] = {i, tonumber(string.sub(trim(line), 2, string.find(line, "|") - 1)), tonumber(string.sub(trim(line), string.find(line, "|") + 1, string.len(trim(line)) - 1))} -- start index, x, y
	elseif(line ~= nil and string.len(trim(line)) >= 10 and string.find(line, "=") and string.sub(trim(line), 1, 10) == "[triangleX" and string.sub(trim(line), string.len(trim(line))) == "]") then
		triangleX = tonumber(string.sub(trim(line), string.find(trim(line), "=") + 1, string.len(trim(line)) - 1));
	elseif(line ~= nil and string.len(trim(line)) >= 8 and string.find(line, "=") and string.sub(trim(line), 1, 8) == "[squareX" and string.sub(trim(line), string.len(trim(line))) == "]") then
		squareX = tonumber(string.sub(trim(line), string.find(trim(line), "=") + 1, string.len(trim(line)) - 1));
	elseif(line ~= nil and string.len(trim(line)) >= 8 and string.find(line, "=") and string.sub(trim(line), 1, 8) == "[circleX" and string.sub(trim(line), string.len(trim(line))) == "]") then
		circleX = tonumber(string.sub(trim(line), string.find(trim(line), "=") + 1, string.len(trim(line)) - 1));
	elseif(line ~= nil and string.len(trim(line)) >= 7 and string.find(line, "=") and string.sub(trim(line), 1, 7) == "[crossX" and string.sub(trim(line), string.len(trim(line))) == "]") then
		crossX = tonumber(string.sub(trim(line), string.find(trim(line), "=") + 1, string.len(trim(line)) - 1));
	elseif(line ~= nil and string.len(trim(line)) >= 6 and string.find(line, "=") and string.sub(trim(line), 1, 6) == "[wordX" and string.sub(trim(line), string.len(trim(line))) == "]") then
		wordX = tonumber(string.sub(trim(line), string.find(trim(line), "=") + 1, string.len(trim(line)) - 1));
	elseif(line ~= nil and string.len(trim(line)) >= 6 and string.find(line, "=") and string.sub(trim(line), 1, 6) == "[align" and string.sub(trim(line), string.len(trim(line))) == "]") then
		local align = string.lower((string.sub(trim(line), string.find(trim(line), "=") + 1, string.len(trim(line)) - 1)));
		
		if (align == "align_left") then
			textAlign = IntraFont.ALIGN_LEFT;
		elseif (align == "align_right") then
			textAlign = IntraFont.ALIGN_RIGHT;
		elseif (align == "align_center") then
			textAlign = IntraFont.ALIGN_CENTER;
		elseif (align == "align_full") then
			textAlign = IntraFont.ALIGN_FULL;
		end
	end
end
breakList[#breakList + 1] = {lastBreak, i - 1}; -- add final break
file2:close();

if (#word < 4) then
	ifontLtn:setStyle(0.8, red, darkgray, IntraFont.ALIGN_CENTER);
	System.draw();
	screen:clear()
	screen:blit(0, 0, background);
	ifontLtn:print(240, 260, "Selected list has not enough words. 4 is minimum.");
	System.endDraw();
	screen.flip()
	screen.waitVblankStart(100);
	--initialize();
	selectDictionary();
end

elseif (canGetLastQuestion(selectedDictionary)) then
	normalStart = false;
end

if (canGetLastQuestion(selectedDictionary)) then
	normalStart = false;
end

start(normalStart);

end

start = function(normalStart)

ifont:setStyle(1.0, currentColor, darkgray, IntraFont.ALIGN_CENTER);
ifontSecondary:setStyle(1.0, currentColor, darkgray, IntraFont.ALIGN_CENTER);

if (normalStart) then
	show = 1;
	mode = 1; -- translation is question. If 2 answer is question.
	randomize();
else
	getLastQuestion();
	calculateMinMax()
	checkKnownWords()
end

extraQ = 0; -- with analog user may increase the font size of question.
showAnswer = false; -- for showing answer is user has guessed wrong.
local waited = false; -- for waiting only one time
local imageLoaded = false; -- for picture dictionary
local immediatelyRight = true; -- only mark word as known if you know it right away
questionImage = nil;
local flipWait = false; -- avoid unnecessary screen flip where possible
loadSaveData(selectedDictionary, word, mode);

questionStartTime = os.clock();
questionEndTime = 0;

while true do
		-- Show questions
        System.draw();
		screen:blit(0, 0, background);
		--screen:blit(30, 118, square);
		--screen:blit(30, 146, triangle);
		
		-- Show right answer
		if (userOptions[1] == "true" and showAnswer) then
			if (question == first) then
				screen:blit(60, 116, right);
			elseif (question == second) then
				screen:blit(60, 146, right);
			elseif (question == third) then
				screen:blit(60, 176, right);
			else
				screen:blit(60, 206, right);
			end
		end
		
		screen:blit(triangleX, triangleY, triangle);
		screen:blit(squareX, squareY, square);
		screen:blit(circleX, circleY, circle);
		screen:blit(crossX, crossY, cross);
		
		if (waited == false) then
			waitBeforeShowing(); -- USER SET WAIT TIME
			waited = true;
		end
		
		if (mode == 1) then
		
		-- if too long text, should smallen the font
		question1 = trim(word[question][#word[question] - 1]);
		if (string.len(question1) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			ifontSecondary:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		if (string.len(question1) > LINEBREAKLIMIT) then
			local beginning = string.sub(question1, 1, LINEBREAKLIMIT);
			local ending = string.sub(question1, LINEBREAKLIMIT + 1);
			question1 = beginning .. " \n " .. ending;
		end
		
		if (string.find(question1, ".png")) then -- image query
			if (imageLoaded == false) then
			
				local file8 = io.open(question1);
				if (file8 == nil ) then
					questionImage = false;
				else
					questionImage = Image.load(question1);
					imageLoaded = true;
					file8:close()
					getImageXY(question);
				end
			end
			if (questionImage == false) then
				ifontLtn:print(240, 56, "Not found: " .. question1);
			else
				screen:blit(imageX,imageY,questionImage) -- image was found, show it
				--screen:blit(30, 118, square);
				--screen:blit(30, 146, triangle);
				
				if (userOptions[1] == "true" and showAnswer) then
					if (question == first) then
						screen:blit(60, 116, right);
					elseif (question == second) then
						screen:blit(60, 146, right);
					elseif (question == third) then
						screen:blit(60, 176, right);
					else
						screen:blit(60, 206, right);
					end
				end
				
				screen:blit(triangleX, triangleY, triangle);
				screen:blit(squareX, squareY, square);
				screen:blit(circleX, circleY, circle);
				screen:blit(crossX, crossY, cross);
			end
	
		else
			ifont:print(240, 56, question1); -- translation
		end
		
		word1 = trim(word[first][show]);
		word2 = trim(word[second][show]);
		word3 = trim(word[third][show]);
		word4 = trim(word[fourth][show]);
		
		-- If item has no text, show it in another format if possible
		counts = #word[1] - 2;
		counter = 0;
		tempShow = show;
		
		while (counter < counts) do
		
			if (string.len(word1) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[first] - 2;
				end
			
				word1 = trim(word[first][tempShow])
				counter = counter + 1;
	
			else
				break;
			end
		end
		
		counter = 0;
		
		while (counter <= counts) do
		
			if (string.len(word2) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[second] - 2;
				end
			
				word2 = trim(word[second][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
		counter = 0;
		
		while (counter <= counts) do
		
			if (string.len(word3) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[third] - 2;
				end
			
				word3 = trim(word[third][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
		counter = 0;
		
		while (counter <= counts) do
		
			if (string.len(word4) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[fourth] - 2;
				end
			
				word4 = trim(word[fourth][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
			ifont:setStyle(1.0, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
			if (string.len(word1) > SMALLFONTLIMIT) then
				ifont:setStyle(0.6, currentColor, darkgray, textAlign);
				ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
			end
			
			-- optimizing for japanese strings, if too long line break
			if (string.len(word1) > LINEBREAKLIMIT) then
				local beginning = string.sub(word1, 1, LINEBREAKLIMIT);
				local ending = string.sub(word1, LINEBREAKLIMIT + 1);
				word1 = beginning .. " \n " .. ending;
			end

			ifont:print(wordX, 136, word1); -- answer1
		
			ifont:setStyle(1.0, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
			if (string.len(word2) > SMALLFONTLIMIT) then
				ifont:setStyle(0.6, currentColor, darkgray, textAlign);
				ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
			end
			
			-- optimizing for japanese strings, if too long line break
			if (string.len(word2) > LINEBREAKLIMIT) then
				local beginning = string.sub(word2, 1, LINEBREAKLIMIT);
				local ending = string.sub(word2, LINEBREAKLIMIT + 1);
				word2 = beginning .. " \n " .. ending;
			end
		
			ifont:print(wordX, 166, word2); -- answer2
		
			ifont:setStyle(1.0, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
			if (string.len(word3) > SMALLFONTLIMIT) then
				ifont:setStyle(0.6, currentColor, darkgray, textAlign);
				ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
			end
		
			-- optimizing for japanese strings, if too long line break
			if (string.len(word3) > LINEBREAKLIMIT) then
				local beginning = string.sub(word3, 1, LINEBREAKLIMIT);
				local ending = string.sub(word3, LINEBREAKLIMIT + 1);
				word3 = beginning .. " \n " .. ending;
			end
		
			ifont:print(wordX, 196, word3); -- answer3
		
			ifont:setStyle(1.0, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
			if (string.len(word4) > SMALLFONTLIMIT) then
				ifont:setStyle(0.6, currentColor, darkgray, textAlign);
				ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
			end
			
			-- optimizing for japanese strings, if too long line break
			if (string.len(word4) > LINEBREAKLIMIT) then
				local beginning = string.sub(word4, 1, LINEBREAKLIMIT);
				local ending = string.sub(word4, LINEBREAKLIMIT + 1);
				word4 = beginning .. " \n " .. ending;
			end
		
			ifont:print(wordX, 226, word4); -- answer4
		
			ifont:setStyle(1.0, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			ifontSecondary:setStyle(1.0, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		
		elseif (mode == 2) then
		
		question1 = trim(word[question][show]);
		
		-- if wrong mode (comes from mode 2 to picture questionaire)
		if (string.find(question1, ".png")) then -- image query
			mode = 1;
			randomize();
		end
		
		-- If item has no text, show it in another format if possible
		counts = #word[1] - 2;
		counter = 0;
		tempShow = show;
		
		while (counter <= counts) do
		
			if (string.len(question1) == 0 ) then
			
				tempShow = tempShow - 1;
				if (tempShow == 0) then
					tempShow = #word[question] - 2;
				end
			
				question1 = trim(word[question][tempShow])
				counter = counter + 1;
			else
				break;
			end
		end
		
		if (string.len(question1) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
			ifontSecondary:setStyle(0.6 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(question1) > LINEBREAKLIMIT) then
			local beginning = string.sub(question1, 1, LINEBREAKLIMIT);
			local ending = string.sub(question1, LINEBREAKLIMIT + 1);
			question1 = beginning .. " \n " .. ending;
		end
		
		ifont:print(240, 56, question1);
		
		word1 = trim(word[first][#word[first] - 1]);
		word2 = trim(word[second][#word[second] - 1]);
		word3 = trim(word[third][#word[third] - 1]);
		word4 = trim(word[fourth][#word[fourth] - 1]);
		
		ifont:setStyle(1.0, currentColor, darkgray, textAlign);
		ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
		if (string.len(word1) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word1) > LINEBREAKLIMIT) then
			local beginning = string.sub(word1, 1, LINEBREAKLIMIT);
			local ending = string.sub(word1, LINEBREAKLIMIT + 1);
			word1 = beginning .. " \n " .. ending;
		end
		
		ifont:print(wordX, 136, word1); -- translation
		
		ifont:setStyle(1.0, currentColor, darkgray, textAlign);
		ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
		if (string.len(word2) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word2) > LINEBREAKLIMIT) then
			local beginning = string.sub(word2, 1, LINEBREAKLIMIT);
			local ending = string.sub(word2, LINEBREAKLIMIT + 1);
			word2 = beginning .. " \n " .. ending;
		end
		
		ifont:print(wordX, 166, word2); -- translation
		
		ifont:setStyle(1.0, currentColor, darkgray, textAlign);
		ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
		if (string.len(word3) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word3) > LINEBREAKLIMIT) then
			local beginning = string.sub(word3, 1, LINEBREAKLIMIT);
			local ending = string.sub(word3, LINEBREAKLIMIT + 1);
			word3 = beginning .. " \n " .. ending;
		end
		
		ifont:print(wordX, 196, word3); -- translation
		
		ifont:setStyle(1.0, currentColor, darkgray, textAlign);
		ifontSecondary:setStyle(1.0, currentColor, darkgray, textAlign);
		
		if (string.len(word4) > SMALLFONTLIMIT) then
			ifont:setStyle(0.6, currentColor, darkgray, textAlign);
			ifontSecondary:setStyle(0.6, currentColor, darkgray, textAlign);
		end
		
		-- optimizing for japanese strings, if too long line break
		if (string.len(word4) > LINEBREAKLIMIT) then
			local beginning = string.sub(word4, 1, LINEBREAKLIMIT);
			local ending = string.sub(word4, LINEBREAKLIMIT + 1);
			word4 = beginning .. " \n " .. ending;
		end
		
		ifont:print(wordX, 226, word4); -- translation
		
		ifont:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		ifontSecondary:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		end

		ifontLtn:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		ifontLtn:print(100, 255, "Mode: " .. mode .. " / Show: " .. show ); -- show mode and show
		ifontLtn:setStyle(0.6, white, darkgray, IntraFont.ALIGN_LEFT);
		ifontLtn:print(10, 267, "Range: " .. askMin .. "-" .. askMax .. " / " .. #word .. " " .. listName); -- show range
		ifontLtn:setStyle(1.0, white, darkgray, IntraFont.ALIGN_CENTER);
		
		if (allKnown == 1) then
			ifontLtn:print(395, 260, "All once correct");
		elseif (setKnown == 1) then
			ifontLtn:print(395, 260, "Set once correct");
		end
		
        local pad = Controls.readPeek()

        --if pad:square() then
		--if pad:triangle() then
		if ((pad:triangle() and button1 == "triangle") or (pad:square() and button1 == "square") or (pad:circle() and button1 == "circle") or (pad:cross() and button1 == "cross")) then
				if (mode == 1 and (question == first or string.lower(trim(word[question][show])) == string.lower(word1))) then -- there may be multiple same answers that's why or
					-- Right answer
					ifontLtn:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Right")
					System.endDraw()
					screen.flip();
					System.draw();
					screen.waitVblankStart(20);
					
					if (immediatelyRight) then
						word[question][#word[1]] = "true";
					end
					immediatelyRight = true;
					
					if (userOptions[3] == "true") then
						questionEndTime = os.clock();
						waitPress()
					end
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					imageLoaded = false;
					if (questionImage ~= nil and questionImage ~= false) then -- free memory
						Image.free(questionImage)
					end
					
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(word1, question1, extraQ)
					end
					randomize();
				elseif(mode == 2 and (question == first or string.lower(trim(word[question][#word[question] - 1])) == string.lower(word1))) then
					-- Right answer
					ifontLtn:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Right")
					System.endDraw()
					screen.flip();
					System.draw();
					screen.waitVblankStart(20);
					
					if (immediatelyRight) then
						word[question][#word[1]] = "true";
					end
					immediatelyRight = true;
					
					if (userOptions[3] == "true") then
						questionEndTime = os.clock();
						waitPress()
					end
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(question1, word1, extraQ)
					end
					randomize();
				else
					ifontLtn:setStyle(1.0, red, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Wrong")
					--screen.flip();
					--screen.waitVblankStart(30);
					flipWait = true;
					showAnswer = true;
					immediatelyRight = false;
				end
				
		--elseif pad:triangle() then
		--elseif pad:square() then
		elseif ((pad:triangle() and button2 == "triangle") or (pad:square() and button2 == "square") or (pad:circle() and button2 == "circle") or (pad:cross() and button2 == "cross")) then
				if (mode == 1 and (question == second or string.lower(trim(word[question][show])) == string.lower(word2))) then
					-- Right answer
					ifontLtn:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Right")
					System.endDraw()
					screen.flip();
					System.draw();
					screen.waitVblankStart(20);
					
					if (immediatelyRight) then
						word[question][#word[1]] = "true";
					end
					immediatelyRight = true;
					
					if (userOptions[3] == "true") then
						questionEndTime = os.clock();
						waitPress()
					end
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					imageLoaded = false;
					if (questionImage ~= nil and questionImage ~= false) then -- free memory
						Image.free(questionImage)
					end
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(word2, question1, extraQ)
					end
					randomize();
				elseif(mode == 2 and (question == second or string.lower(trim(word[question][#word[question] - 1])) == string.lower(word2))) then
					-- Right answer
					ifontLtn:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Right")
					System.endDraw()
					screen.flip();
					System.draw();
					screen.waitVblankStart(20);
					
					if (immediatelyRight) then
						word[question][#word[1]] = "true";
					end
					immediatelyRight = true;
					
					if (userOptions[3] == "true") then
						questionEndTime = os.clock();
						waitPress()
					end
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					imageLoaded = false;
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(question1, word2, extraQ)
					end
					randomize();
				else
					ifontLtn:setStyle(1.0, red, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Wrong")
					--screen.flip();
					--screen.waitVblankStart(30);
					flipWait = true;
					showAnswer = true;
					immediatelyRight = false;
				end
				
		--elseif pad:circle() then
		elseif ((pad:triangle() and button3 == "triangle") or (pad:square() and button3 == "square") or (pad:circle() and button3 == "circle") or (pad:cross() and button3 == "cross")) then
				if (mode == 1 and (question == third or string.lower(trim(word[question][show])) == string.lower(word3))) then
					-- Right answer
					ifontLtn:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Right")
					System.endDraw()
					screen.flip();
					System.draw();
					screen.waitVblankStart(20);
					
					if (immediatelyRight) then
						word[question][#word[1]] = "true";
					end
					immediatelyRight = true;
					
					if (userOptions[3] == "true") then
						questionEndTime = os.clock();
						waitPress()
					end
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					imageLoaded = false;
					if (questionImage ~= nil and questionImage ~= false) then -- free memory
						Image.free(questionImage)
					end
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(word3, question1, extraQ)
					end
					randomize();
				elseif(mode == 2 and (question == third or string.lower(trim(word[question][#word[question] - 1])) == string.lower(word3))) then
					-- Right answer
					ifontLtn:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Right")
					System.endDraw()
					screen.flip();
					System.draw();
					screen.waitVblankStart(20);
					
					if (immediatelyRight) then
						word[question][#word[1]] = "true";
					end
					immediatelyRight = true;
					
					if (userOptions[3] == "true") then
						questionEndTime = os.clock();
						waitPress()
					end
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(question1, word3, extraQ)
					end
					randomize();
				else
					ifontLtn:setStyle(1.0, red, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Wrong")
					--screen.flip();
					--screen.waitVblankStart(30);
					flipWait = true;
					showAnswer = true;
					immediatelyRight = false;
				end
				
		--elseif pad:cross() then
		elseif ((pad:triangle() and button4 == "triangle") or (pad:square() and button4 == "square") or (pad:circle() and button4 == "circle") or (pad:cross() and button4 == "cross")) then
				if (mode == 1 and (question == fourth or string.lower(trim(word[question][show])) == string.lower(word4))) then
					-- Right answer
					ifontLtn:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Right")
					System.endDraw()
					screen.flip();
					System.draw();
					screen.waitVblankStart(20);
					
					if (immediatelyRight) then
						word[question][#word[1]] = "true";
					end
					immediatelyRight = true;
					
					if (userOptions[3] == "true") then
						questionEndTime = os.clock();
						waitPress()
					end
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					imageLoaded = false;
					if (questionImage ~= nil and questionImage ~= false) then -- free memory
						Image.free(questionImage)
					end
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(word4, question1, extraQ)
					end
					randomize();
				elseif(mode == 2 and (question == fourth or string.lower(trim(word[question][#word[question] - 1])) == string.lower(word4))) then
					-- Right answer
					ifontLtn:setStyle(1.0, lime, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Right")
					System.endDraw()
					screen.flip();
					System.draw();
					screen.waitVblankStart(20);
					
					if (immediatelyRight) then
						word[question][#word[1]] = "true";
					end
					immediatelyRight = true;
					
					if (userOptions[3] == "true") then
						questionEndTime = os.clock();
						waitPress()
					end
					second = first;
					third = first;
					fourth = first;
					showAnswer = false;
					waited = false;
					if (currentSentencePath ~= "none" and  userOptions[2] == "true") then
						showSentence(question1, word4, extraQ)
					end
					randomize();
				else
					ifontLtn:setStyle(1.0, red, darkgray, IntraFont.ALIGN_CENTER);
					ifontLtn:print(240, 260, "Wrong")
					--screen.flip();
					--screen.waitVblankStart(30);
					flipWait = true;
					showAnswer = true;
					immediatelyRight = false;
				end	
				
		elseif pad:right() then
				if (show == #word[1] - 2) then
					show = 1;
					screen.waitVblankStart(20);
				else
					show = show + 1;
					screen.waitVblankStart(20);
				end
				
		elseif pad:left() then
				if (show == 1) then
					show = #word[1] - 2;
					screen.waitVblankStart(20);
				else
					show = show - 1;
					screen.waitVblankStart(20);
				end
				
		elseif pad:up() and imageLoaded == false then -- these buttons cannot be used with picture dictionaries
			if (mode == 1) then
				save(question, first, second, third, fourth, show, askLevel, mode);
				mode = 2;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				screen.waitVblankStart(20);
			else
				save(question, first, second, third, fourth, show, askLevel, mode);
				mode = 1;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				screen.waitVblankStart(20);
			end;
			
		elseif pad:down() and imageLoaded == false then
			if (mode == 1) then
				save(question, first, second, third, fourth, show, askLevel, mode);
				mode = 2;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				screen.waitVblankStart(20);
			else
				save(question, first, second, third, fourth, show, askLevel, mode);
				mode = 1;
				showAnswer = false;
				waited = false;
				loadSaveData(selectedDictionary, word, mode);
				randomize();
				screen.waitVblankStart(20);
			end;
		
		elseif (pad:analogY() < -100 ) then
			screen.waitVblankStart(1); -- added
			extraQ = extraQ + 0.1;
			if (extraQ > 2) then
				extraQ = 2;
			end
		
		elseif (pad:analogY() > 100 ) then
			screen.waitVblankStart(1); -- added
			extraQ = extraQ - 0.1
			if (extraQ < 0) then
				extraQ = 0
			end
		
		elseif (pad:analogX() < - 100 and userOptions[5] ~= "0") then
			askLevel = askLevel - 1;
			if (userOptions[5] ~= "break") then
				if (askLevel < 0) then
					askLevel = math.ceil(#word / userOptions[5]) - 1;
				end
			else
				if (askLevel < 0) then
					askLevel = #breakList - 1;
				end
			end
			
			calculateMinMax()
			checkKnownWords()
			screen.waitVblankStart(20);
			
		elseif (pad:analogX() > 100 and userOptions[5] ~= "0") then
			askLevel = askLevel + 1;
			if (userOptions[5] ~= "break") then
				if (askLevel > (math.ceil(#word / userOptions[5]) - 1)) then
					askLevel = 0;
				end
			else
				if (askLevel + 1 > #breakList) then
					askLevel = 0;
				end
			end
			calculateMinMax()
			checkKnownWords()
			screen.waitVblankStart(20);	
		
		elseif pad:select() then
			save(question, first, second, third, fourth, show, askLevel, mode)
			screen.waitVblankStart(20);
			if (questionImage ~= nil and questionImage ~= false) then -- free memory
				Image.free(questionImage)
			end
			askLevel = 0;
			--initialize();
			selectDictionary()
		
		elseif pad:home() then
				break;
		
        elseif pad:start() then
			save(question, first, second, third, fourth, show, askLevel, mode)
			screen.waitVblankStart(20);
			openOptions();
			
		elseif pad:r() then
			result = System.msgDialog("Do you want to clear current known list? (Range " .. askMin .. "-" .. askMax .. ")", true, drawFunc)
			if (result==System.MSGDIALOG_RESULT_YES) then
				clearResults(word, askMin, askMax);
				allKnown = 0;
				setKnown = 0;
				save(question, first, second, third, fourth, show, askLevel, mode);
			end
		elseif pad:l() then
			screen.waitVblankStart(20);
			save(question, first, second, third, fourth, show, askLevel, mode)
			search()
		end
		
		ifont:setStyle(1.0 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
		ifontSecondary:setStyle(1.0 + extraQ, currentColor, darkgray, IntraFont.ALIGN_CENTER);
        System.endDraw();
        screen.flip();
		if (flipWait) then -- to avoid annoying screen update inside draw
			screen.waitVblankStart(30);
			flipWait = false;
		end
end

save(question, first, second, third, fourth, show, askLevel, mode) -- switched save here
--saveSelection() -- save the last list that was studied
ifont:unload();
ifontLtn:unload(); -- ifontSecondary is free with this

System.quit(); -- Quit the application

end

save = function(question, first, second, third, fourth, show, askLevel, mode)
	saveFile = selectedDictionary .. mode;
	file3 = io.open(saveFile,"w")
				
	i = 0;
	while (i < #word) do
		i = i + 1;
		if (word[i][#word[1]] ~= nil) then
			result = tostring(word[i][#word[1]]) .. "\n";
		else
			result = "\n";
		end
		file3:write(result);
	end
				
	file3:close();
	
	-- Save latest question too.
	saveQuestionList(selectedDictionary, question, first, second, third, fourth, show, askLevel, mode)
	
end

initializeButtons = function()
	local buttonsFile = "buttons.ini"
	local file = io.open(buttonsFile, "r")
	local buttonNumber = 0;
	local triangleSet = false;
	local squareSet = false;
	local circleSet = false;
	local crossSet = false;
	local buttonError = false;
	
	if file then
		local line = "";
		
		for line in file:lines() do
			line = trim(string.lower(line));
			if (line ~= nil and (line == "triangle" or line == "square" or line == "circle" or line == "cross")) then
				if (line == "triangle" and triangleSet == false) then
					triangleSet = true;
					triangleY = 116 + buttonNumber * 30;
					
					if (buttonNumber == 0) then
						button1 = "triangle";
					elseif (buttonNumber == 1) then
						button2 = "triangle";
					elseif (buttonNumber == 2) then
						button3 = "triangle";
					elseif (buttonNumber == 3) then
						button4 = "triangle";
					end
					
				elseif (line == "square" and squareSet == false) then
					squareSet = true;
					squareY = 116 + buttonNumber * 30;
					
					if (buttonNumber == 0) then
						button1 = "square";
					elseif (buttonNumber == 1) then
						button2 = "square";
					elseif (buttonNumber == 2) then
						button3 = "square";
					elseif (buttonNumber == 3) then
						button4 = "square";
					end
					
				elseif (line == "circle" and circleSet == false) then
					circleSet = true;
					circleY = 116 + buttonNumber * 30;
					
					if (buttonNumber == 0) then
						button1 = "circle";
					elseif (buttonNumber == 1) then
						button2 = "circle";
					elseif (buttonNumber == 2) then
						button3 = "circle";
					elseif (buttonNumber == 3) then
						button4 = "circle";
					end
					
				elseif (line == "cross" and crossSet == false) then
					crossSet = true;
					crossY = 116 + buttonNumber * 30;
					
					if (buttonNumber == 0) then
						button1 = "cross";
					elseif (buttonNumber == 1) then
						button2 = "cross";
					elseif (buttonNumber == 2) then
						button3 = "cross";
					elseif (buttonNumber == 3) then
						button4 = "cross";
					end
					
				else
					buttonError = true;
					break;
				end
				
				buttonNumber = buttonNumber + 1;
			end
		end
		
		file:close()
	end
	
	if (buttonError or (triangleSet == false) or (squareSet == false) or (circleSet == false) or (crossSet == false)) then
		triangleY = 116;
		squareY = 146;
		circleY = 176;
		crossY = 206;
		
		button1 = "triangle";
		button2 = "square";
		button3 = "circle";
		button4 = "cross";
	end
end

-- PROGRAM STARTS
loadOptions(); -- get user saved options
showLogo();
initializeButtons();
dofile("keyboard.lua")
dofile("osk_char_converter.lua")
initialize(); -- calls start