diff --git a/inputbox.lua b/inputbox.lua index 923194854..10e0c2467 100644 --- a/inputbox.lua +++ b/inputbox.lua @@ -6,7 +6,6 @@ require "graphics" ---------------------------------------------------- -- General inputbox ---------------------------------------------------- - InputBox = { -- Class vars: h = 100, @@ -25,9 +24,7 @@ InputBox = { fheight = 25, fwidth = 15, commands = nil, - initialized = false, - - -- NuPogodi, 25.05.12: for full UTF8 support + vk_bg = 3, charlist = {}, -- table to store input string charpos = 1, @@ -35,12 +32,13 @@ InputBox = { -- values to control layouts: min & max min_layout = 2, max_layout = 9, - -- default layout = 2, i.e. shiftmode = symbolmode = utf8mode = false - layout = 2, + layout = 3, -- now bits to toggle the layout mode - shiftmode = true, -- toggle chars <> capitals, lowest bit in (layout-2) - symbolmode = false, -- toggle chars <> symbols, middle bit in (layout-2) - utf8mode = false, -- toggle english <> national, highest bit in (layout-2) + shiftmode = true, -- toggle chars <-> capitals, lowest bit in (layout-2) + symbolmode = false, -- toggle chars <-> symbols, middle bit in (layout-2) + utf8mode = false, -- toggle english <-> national, highest bit in (layout-2) + calcmode = false, -- toggle calculator mode + calcfunctions = nil, -- math functions for calculator helppage } function InputBox:new(o) @@ -127,8 +125,13 @@ end ---------------------------------------------------------------------- function InputBox:input(ypos, height, title, d_text, is_hint) -- To avoid confusion with old ypos & height parameters, I'd better define - -- my own position, at the bottom screen edge (NuPogodi, 26.05.12) + -- my own position, at the bottom screen edge ypos = fb.bb:getHeight() - 165 + -- some corrections for calculator mode + if self.calcmode then + self:setCalcMode() + end + -- at first, draw titled box and content local h, w = 55, fb.bb:getWidth() - 2 self:drawBox(ypos, w, h, title) @@ -142,21 +145,16 @@ function InputBox:input(ypos, height, title, d_text, is_hint) y_pos = ypos + 13, h = 30, } + if d_text then if is_hint then - -- print hint text + -- print hint text fb.bb:paintRect(self.input_start_x-5, self.input_start_y-19, self.input_slot_w, self.fheight, self.input_bg) renderUtf8Text(fb.bb, self.input_start_x+5, self.input_start_y, self.face, d_text, 0) fb.bb:dimRect(self.input_start_x-5, self.input_start_y-19, self.input_slot_w, self.fheight, self.input_bg) else - self.input_string = d_text - string.gsub( d_text, "(.)", function(char) - table.insert(self.charlist, self.charpos, char) - self.charpos = self.charpos + 1 - return "" - end) - Debug("charlist", self.charlist) - + -- add text to input_string + self:StringToCharlist(d_text) self.input_cur_x = self.input_cur_x + (self.fwidth * #self.charlist) self.cursor.x_pos = self.cursor.x_pos + (self.fwidth * #self.charlist) self:refreshText() @@ -164,8 +162,10 @@ function InputBox:input(ypos, height, title, d_text, is_hint) end self.cursor:draw() fb:refresh(1, 1, ypos, w, h) + + local ev, keydef, command, ret_code while true do - local ev = input.saveWaitForEvent() + ev = input.saveWaitForEvent() ev.code = adjustKeyEvents(ev) if ev.type == EV_KEY and ev.value ~= EVENT_VALUE_KEY_RELEASE then keydef = Keydef:new(ev.code, getKeyModifier()) @@ -183,62 +183,63 @@ function InputBox:input(ypos, height, title, d_text, is_hint) end end -- if end -- while - local return_str = self.input_string + + local output = self.input_string self.input_string = "" self.charlist = {} self.charpos = 1 - return return_str + return output end function InputBox:setLayoutsTable() - -- trying to read the layout from the user-defined file "mykeyboard.lua" - local ok, stored = pcall(dofile,"./mykeyboard.lua") + -- trying to read the layout from the user-defined file + local ok, stored = pcall(dofile, lfs.currentdir() .. "/mykeyboard.lua") if ok then self.INPUT_KEYS = stored else -- if an error happens, we use the default layout self.INPUT_KEYS = { { KEY_Q, "Q", "q", "1", "!", "Я", "я", "1", "!", }, { KEY_W, "W", "w", "2", "?", "Ж", "ж", "2", "?", }, - { KEY_E, "E", "e", "3", "#", "Е", "е", "3", "«", }, - { KEY_R, "R", "r", "4", "@", "Р", "р", "4", "»", }, - { KEY_T, "T", "t", "5", "%", "Т", "т", "5", ":", }, + { KEY_E, "E", "e", "3", "|", "Е", "е", "3", "«", }, + { KEY_R, "R", "r", "4", "#", "Р", "р", "4", "»", }, + { KEY_T, "T", "t", "5", "@", "Т", "т", "5", ":", }, { KEY_Y, "Y", "y", "6", "‰", "Ы", "ы", "6", ";", }, - { KEY_U, "U", "u", "7", "\'", "У", "у", "7", "~", }, + { KEY_U, "U", "u", "7", "'", "У", "у", "7", "~", }, { KEY_I, "I", "i", "8", "`", "И", "и", "8", "(",}, { KEY_O, "O", "o", "9", ":", "О", "о", "9", ")",}, { KEY_P, "P", "p", "0", ";", "П", "п", "0", "=", }, -- middle raw { KEY_A, "A", "a", "+", "…", "А", "а", "Ш", "ш", }, { KEY_S, "S", "s", "-", "_", "С", "с", "Ѕ", "ѕ", }, - { KEY_D, "D", "d", "*", "¦", "Д", "д", "Э", "э", }, - { KEY_F, "F", "f", "/", "|", "Ф", "ф", "Ю", "ю", }, - { KEY_G, "G", "g", "\\", "„", "Г", "г", "Ґ", "ґ", }, - { KEY_H, "H", "h", "=", "“", "Ч", "ч", "Ј", "ј", }, + { KEY_D, "D", "d", "*", "=", "Д", "д", "Э", "э", }, + { KEY_F, "F", "f", "/", "\\", "Ф", "ф", "Ю", "ю", }, + { KEY_G, "G", "g", "%", "„", "Г", "г", "Ґ", "ґ", }, + { KEY_H, "H", "h", "^", "“", "Ч", "ч", "Ј", "ј", }, { KEY_J, "J", "j", "<", "”", "Й", "й", "І", "і", }, - { KEY_K, "K", "k", "ˆ", "\"", "К", "к", "Ќ", "ќ", }, + { KEY_K, "K", "k", "=", "\"", "К", "к", "Ќ", "ќ", }, { KEY_L, "L", "l", ">", "~", "Л", "л", "Љ", "љ", }, -- lowest raw { KEY_Z, "Z", "z", "(", "$", "З", "з", "Щ", "щ", }, { KEY_X, "X", "x", ")", "€", "Х", "х", "№", "@", }, - { KEY_C, "C", "c", "{", "¥", "Ц", "ц", "Џ", "џ", }, - { KEY_V, "V", "v", "}", "£", "В", "в", "Ў", "ў", }, - { KEY_B, "B", "b", "[", "‚", "Б", "б", "Ћ", "ћ", }, - { KEY_N, "N", "n", "]", "‘", "Н", "н", "Њ", "њ", }, - { KEY_M, "M", "m", "&", "’", "М", "м", "Ї", "ї", }, - { KEY_DOT, ".", ",", ".", ",", ".", ",", "Є", "є", }, + { KEY_C, "C", "c", "&", "¥", "Ц", "ц", "Џ", "џ", }, + { KEY_V, "V", "v", ":", "£", "В", "в", "Ў", "ў", }, + { KEY_B, "B", "b", "π", "‚", "Б", "б", "Ћ", "ћ", }, + { KEY_N, "N", "n", "е", "‘", "Н", "н", "Њ", "њ", }, + { KEY_M, "M", "m", "~", "’", "М", "м", "Ї", "ї", }, + { KEY_DOT, ",", ".", ".", ",", ",", ".", "Є", "є", }, -- Let us make key 'Space' the same for all layouts { KEY_SPACE," ", " ", " ", " ", " ", " ", " ", " ", }, - -- Simultaneous pressing Alt + Q..P should also work properly - { KEY_1, "1", " ", " ", " ", "1", " ", " ", " ", }, - { KEY_2, "2", " ", " ", " ", "2", " ", " ", " ", }, - { KEY_3, "3", " ", " ", " ", "3", " ", " ", " ", }, - { KEY_4, "4", " ", " ", " ", "4", " ", " ", " ", }, - { KEY_5, "5", " ", " ", " ", "5", " ", " ", " ", }, - { KEY_6, "6", " ", " ", " ", "6", " ", " ", " ", }, - { KEY_7, "7", " ", " ", " ", "7", " ", " ", " ", }, - { KEY_8, "8", " ", " ", " ", "8", " ", " ", " ", }, - { KEY_9, "9", " ", " ", " ", "9", " ", " ", " ", }, - { KEY_0, "0", " ", " ", " ", "0", " ", " ", " ", }, + -- Simultaneous pressing Alt + Q..P should also work properly everywhere + { KEY_1, "1", "1", "1", "1", "1", "1", "1", "1", }, + { KEY_2, "2", "2", "2", "2", "2", "2", "2", "2", }, + { KEY_3, "3", "3", "3", "3", "3", "3", "3", "3", }, + { KEY_4, "4", "4", "4", "4", "4", "4", "4", "4", }, + { KEY_5, "5", "5", "5", "5", "5", "5", "5", "5", }, + { KEY_6, "6", "6", "6", "6", "6", "6", "6", "6", }, + { KEY_7, "7", "7", "7", "7", "7", "7", "7", "7", }, + { KEY_8, "8", "8", "8", "8", "8", "8", "8", "8", }, + { KEY_9, "9", "9", "9", "9", "9", "9", "9", "9", }, + { KEY_0, "0", "0", "0", "0", "0", "0", "0", "0", }, -- DXG keys { KEY_SLASH,"/", "\\", "/", "\\", "/", "\\", "/", "\\", }, } @@ -281,13 +282,13 @@ function InputBox:DrawVirtualKeyboard() blitbuffer.paintBorder(fb.bb, lx+9*dx-10, vy-dy-r-8, r, r, t, c, r) renderUtf8Text(fb.bb, lx-5+9*dx, vy-dy-3, smfont, "Del", true) -- Sym - blitbuffer.paintBorder(fb.bb, lx+8*dx-10, vy-r-8, r, r, t + (r-t)*number(self.symbolmode), c, r) + blitbuffer.paintBorder(fb.bb, lx+8*dx-10, vy-r-8, r, r, t + (r-t)*self:num(self.symbolmode), c, r) renderUtf8Text(fb.bb, lx-5+8*dx, vy-3, smfont, "Sym", true) -- Enter blitbuffer.paintBorder(fb.bb, lx+9*dx-10, vy-r-8, r, r, t, c, r) renderUtf8Text(fb.bb, lx+9*dx, vy-2, vkfont, "«", true) -- Menu - blitbuffer.paintBorder(fb.bb, lx+10*dx-8, vy-2*dy-r-8, r+50, r, t+(r-t)*number(self.utf8mode), c, r) + blitbuffer.paintBorder(fb.bb, lx+10*dx-8, vy-2*dy-r-8, r+50, r, t+(r-t)*self:num(self.utf8mode), c, r) renderUtf8Text(fb.bb, lx+10*dx+11, vy-2*dy-3, smfont, "Menu", true) -- fiveway local h=dy+2*r-2 @@ -296,6 +297,14 @@ function InputBox:DrawVirtualKeyboard() fb:refresh(1, 1, fb.bb:getHeight()-120, fb.bb:getWidth()-2, 120) end +function InputBox:num(bool) + return bool and 1 or 0 +end + +function InputBox:VKLayout(b1, b2, b3) + return 2 + self:num(b1) + 2 * self:num(b2) + 4 * self:num(b3) +end + function InputBox:addCharCommands(layout) -- at first, let's define self.layout and extract separate bits as layout modes if layout then @@ -306,25 +315,48 @@ function InputBox:addCharCommands(layout) -- fill the layout modes layout = (layout - 2) % 4 self.shiftmode = (layout == 1 or layout == 3) - self.symbolmode = (layout == 2 or layout == 3) + self.symbolmode = (layout == 2 or layout == 4) self.utf8mode = (self.layout > 5) else -- or, without input parameter, restore layout from current layout modes - self.layout = 2 + number(self.shiftmode) + 2 * number(self.symbolmode) + 4 * number(self.utf8mode) + self.layout = self:VKLayout(self.shiftmode, self.symbolmode, self.utf8mode) end + -- let's define layout called by Shift+Key (to type capitalized chars being in low-case layout) + local shift_layout = self:VKLayout(not self.shiftmode, self.symbolmode, self.utf8mode) -- adding the commands for k,v in ipairs(self.INPUT_KEYS) do - -- seems to work without removing old commands, - self.commands:del(v[1], nil, "") - -- just redefining existing ones - self.commands:add(v[1], nil, "", "input "..v[self.layout], + -- just redefining existing + self.commands:add(v[1], nil, "A..Z", "enter character from virtual keyboard (VK)", function(self) self:addChar(v[self.layout]) end ) + -- and commands for chars pressed with Shift + self.commands:add(v[1], MOD_SHIFT, "A..Z", "enter capitalized VK-character", + function(self) + self:addChar(v[shift_layout]) + end + ) end self:DrawVirtualKeyboard() end +function InputBox:StringToCharlist(text) + if text == nill then return end + -- clear + self.charlist = {} + self.charpos = 1 + local prevcharcode, charcode = 0 + for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do + charcode = util.utf8charcode(uchar) + if prevcharcode then -- utf8 + self.charlist[#self.charlist+1] = uchar + end + prevcharcode = charcode + end + self.input_string = self:CharlistToString() + self.charpos = #self.charlist+1 +end + function InputBox:CharlistToString() local s, i = "" for i=1, #self.charlist do @@ -333,22 +365,25 @@ function InputBox:CharlistToString() return s end -function number(bool) - return bool and 1 or 0 -end - function InputBox:addAllCommands() - -- we only initialize once + -- if already initialized, we (re)define only calcmode-dependent commands if self.commands then + self:ModeDependentCommands() self:DrawVirtualKeyboard() return end self:setLayoutsTable() self.commands = Commands:new{} - -- adding command to enter character commands - self:addCharCommands() + -- adding character commands + self:addCharCommands(self.layout) -- adding the rest commands (independent of the selected layout) - self.commands:add(KEY_FW_LEFT, nil, "", + self.commands:add(KEY_H, MOD_ALT, "H", + "show helppage", + function(self) + self:showHelpPage(self.commands) + end + ) + self.commands:add(KEY_FW_LEFT, nil, "joypad left", "move cursor left", function(self) if (self.cursor.x_pos + 3) > self.input_start_x then @@ -358,7 +393,17 @@ function InputBox:addAllCommands() end end ) - self.commands:add(KEY_FW_RIGHT, nil, "", + self.commands:add(KEY_FW_LEFT, MOD_SHIFT, "left", + "move cursor to the first position", + function(self) + if (self.cursor.x_pos + 3) > self.input_start_x then + self.cursor:moveHorizontalAndDraw(-self.fwidth*(self.charpos-1)) + self.charpos = 1 + fb:refresh(1, self.input_start_x-5, self.ypos, self.input_slot_w, self.h) + end + end + ) + self.commands:add(KEY_FW_RIGHT, nil, "joypad right", "move cursor right", function(self) if (self.cursor.x_pos + 3) < self.input_cur_x then @@ -368,75 +413,235 @@ function InputBox:addAllCommands() end end ) - self.commands:add({KEY_ENTER, KEY_FW_PRESS}, nil, "", - "submit input content", + self.commands:add(KEY_FW_RIGHT, MOD_SHIFT, "right", + "move cursor to the last position", function(self) - if self.input_string == "" then - self.input_string = nil + if (self.cursor.x_pos + 3) < self.input_cur_x then + self.cursor:moveHorizontalAndDraw(self.fwidth*(#self.charlist+1-self.charpos)) + self.charpos = #self.charlist + 1 + fb:refresh(1, self.input_start_x-5, self.ypos, self.input_slot_w, self.h) end - return "break" end ) - self.commands:add(KEY_DEL, nil, "", + self.commands:add(KEY_DEL, nil, "Del", "delete one character", function(self) self:delChar() end ) - self.commands:add(KEY_DEL, MOD_SHIFT, "", - "empty inputbox", + self.commands:add(KEY_DEL, MOD_SHIFT, "Del", + "delete all characters (empty inputbox)", function(self) self:clearText() end ) - self.commands:add({KEY_BACK, KEY_HOME}, nil, "", - "cancel inputbox", + self.commands:addGroup("up/down", { Keydef:new(KEY_FW_DOWN, nil), Keydef:new(KEY_FW_UP, nil) }, + "goto previous/next VK-layout", function(self) - self.input_string = nil - return "break" - end - ) - self.commands:add(KEY_P, MOD_SHIFT, "P", - "make screenshot", - function(self) - Screen:screenshot() - end - ) - self.commands:add(KEY_FW_DOWN, nil, "joypad down", - "goto next keyboard layout", - function(self) - if self.layout == self.max_layout then self:addCharCommands(self.min_layout) - else self:addCharCommands(self.layout+1) end - end - ) - self.commands:add(KEY_FW_UP, nil, "joypad up", - "goto previous keyboard layout", - function(self) - if self.layout == self.min_layout then self:addCharCommands(self.max_layout) - else self:addCharCommands(self.layout-1) end + if keydef.keycode == KEY_FW_DOWN then + if self.layout == self.max_layout then self:addCharCommands(self.min_layout) + else self:addCharCommands(self.layout+1) end + else -- KEY_FW_UP + if self.layout == self.min_layout then self:addCharCommands(self.max_layout) + else self:addCharCommands(self.layout-1) end + end + end ) self.commands:add(KEY_AA, nil, "Aa", - "toggle layout: chars <> CHARS", + "toggle VK-layout: chars <> CHARS", function(self) self.shiftmode = not self.shiftmode self:addCharCommands() end ) self.commands:add(KEY_SYM, nil, "Sym", - "toggle layout: chars <> symbols", + "toggle VK-layout: chars <> symbols", function(self) self.symbolmode = not self.symbolmode self:addCharCommands() end ) self.commands:add(KEY_MENU, nil, "Menu", - "toggle layout: english <> national", + "toggle VK-layout: english <> national", function(self) self.utf8mode = not self.utf8mode self:addCharCommands() end ) + -- NuPogodi, 02.06.12: calcmode-dependent commands are collected + self:ModeDependentCommands() -- here + + self.commands:add({KEY_BACK, KEY_HOME}, nil, "Back", + "back", + function(self) + self.input_string = nil + return "break" + end + ) +end +----------------------------------------------------------------- +-- NuPogodi, 02.06.12: Some Help- & Calculator-related functions +----------------------------------------------------------------- +function InputBox:defineCalcFunctions() -- for the calculator documentation + -- to initialize only once + if self.calcfunctions then return end + + self.calcfunctions = Commands:new{} + -- remove initially added commands + self.calcfunctions:del(KEY_INTO_SCREEN_SAVER, nil, "Slider") + self.calcfunctions:del(KEY_OUTOF_SCREEN_SAVER, nil, "Slider") + self.calcfunctions:del(KEY_CHARGING, nil, "plugin/out usb") + self.calcfunctions:del(KEY_NOT_CHARGING, nil, "plugin/out usb") + self.calcfunctions:del(KEY_SPACE, MOD_ALT, "Space") + + local s = " " -- space for function groups + local a = 100 -- arithmetic functions + self.calcfunctions:add(a-1, nil, s:rep(1), string.upper("Ariphmetic operators")) + self.calcfunctions:add(a, nil, "+ -", "addition: 1+2=3; substraction: 3-2=1") + self.calcfunctions:add(a+1, nil, "* /", "multiplication: 2*2=4; division: 4/2=2") + self.calcfunctions:add(a+3, nil, "%", "modulo (remainder): 5.2%2=1.2, π-π%0.01=3.14") + local r = 200 -- relations + self.calcfunctions:add(r-1, nil, s:rep(2), string.upper("Relational operators")) + self.calcfunctions:add(r, nil, "< >", "less: (2<3)=true; more: (2>3)=false") + self.calcfunctions:add(r+1, nil, "<=", "less or equal: (3≤3)=true, (2≤1)=false") + self.calcfunctions:add(r+2, nil, ">=", "more or equal: (3≥3)=true, (1≥2)=false") + self.calcfunctions:add(r+3, nil, "==", "equal: (3==3)=true, (1==2)=false") + self.calcfunctions:add(r+4, nil, "~=", "not equal: (6~=8)=true, (3~=3)=false") + local l = 300 -- logical + self.calcfunctions:add(l-1, nil, s:rep(3), string.upper("Logical operators")) + self.calcfunctions:add(l+0, nil, "and, &", "= logical 'and': (4 and 5)=5, (nil & 5)=nil") + self.calcfunctions:add(l+1, nil, "or, |", "= logical 'or': (4 or 5)=4, (false | 5)=5") + local c = 400 -- constants + self.calcfunctions:add(c-1, nil, s:rep(4), string.upper("Some constants")) + self.calcfunctions:add(c, nil, "pi, π", "= 3.14159…; sin(π/2)=1, cos(π/2)=0") + self.calcfunctions:add(c+1, nil, "е, exp(1)", "= 2.71828…; log(е)=1") + local m = 500 -- mathematical + self.calcfunctions:add(m-1, nil, s:rep(5), string.upper("Mathematic functions")) + self.calcfunctions:add(m, nil, "abs(x)", "absolute value of x: abs(1)=1, abs(-2)=2") + self.calcfunctions:add(m+1, nil, "ceil(x)", "round to integer no less than x: ceil(0.4)=1") + self.calcfunctions:add(m+2, nil, "floor(x)", "round to integer no greater than x: floor(0.4)=0") + self.calcfunctions:add(m+3, nil, "^, pow(x,y)","= power: 2^10=1024, pow(4,0.5)=2") + self.calcfunctions:add(m+4, nil, "exp(x), e^x","= exponent: exp(1)=2.71828…") + self.calcfunctions:add(m+5, nil, "log(x)", "the natural logarithm: log(e)=1") + self.calcfunctions:add(m+6, nil, "log10(x)", "the base 10 logarithm: log10(10)=1") + self.calcfunctions:add(m+7, nil, "max(x,…)", "return maximal value: max(0,-1,2,1)=2") + self.calcfunctions:add(m+8, nil, "min(x,…)", "return minimal value: min(0,-1,2,1)=-1") + self.calcfunctions:add(m+9, nil, "sqrt(x)", "return square root: sqrt(4)=2") + local t = 600 -- trigonometrical + self.calcfunctions:add(t, nil, s:rep(6), string.upper("Trigonometric functions")) + self.calcfunctions:add(t+1, nil, "deg(x)", "convert radians to degrees: deg(π/2)=90") + self.calcfunctions:add(t+2, nil, "rad(x)", "convert degrees to radians: rad(180)=3.14159…") + self.calcfunctions:add(t+3, nil, "sin(x)", "sine for x given in radians: sin(π/2)=1") + self.calcfunctions:add(t+4, nil, "cos(x)", "cosine for x given in radians: cos(π)=-1") + self.calcfunctions:add(t+5, nil, "tan(x)", "tangent for x given in radians: tan(π/4)=1") + self.calcfunctions:add(t+6, nil, "asin(x)", "inverse sine (in radians): asin(1)/π=0.5") + self.calcfunctions:add(t+7, nil, "acos(x)", "inverse cosine (in radians): acos(0)/π=0.5") + self.calcfunctions:add(t+8, nil, "atan(x)", "inverse tangent (in radians): atan(1)/π=0.25") + self.calcfunctions:add(t+9, nil, "atan2(x,y)", "inverse tangent of two args: = atan(x/y)") + local h = 700 -- hyperbolical + self.calcfunctions:add(h, nil, s:rep(7), string.upper("Hyperbolic functions")) + self.calcfunctions:add(h+1, nil, "sinh(x)", "hyperbolic sine, (exp(x)-exp(-x))/2") + self.calcfunctions:add(h+2, nil, "cosh(x)", "hyperbolic cosine, (exp(x)+exp(-x))/2") + self.calcfunctions:add(h+3, nil, "tanh(x)", "hyperbolic tangent, sinh(x)/cosh(x)") +-- not yet documented > "fmod", "frexp", "huge", "ldexp", "modf", "randomseed", "random" +end + +function InputBox:showHelpPage(list, title) + -- make inactive input slot + self.cursor:clear() -- hide cursor + fb.bb:dimRect(self.input_start_x-5, self.input_start_y-19, self.input_slot_w, self.fheight, self.input_bg) + fb:refresh(1, self.input_start_x-5, self.ypos, self.input_slot_w, self.h) + -- now start the helppage with own list of commands and own title + HelpPage:show(0, fb.bb:getHeight()-165, list, title) + -- on the helppage-exit, making inactive helpage + fb.bb:dimRect(0, 40, fb.bb:getWidth(), fb.bb:getHeight()-205, self.input_bg) + fb:refresh(1, 0, 40, fb.bb:getWidth(), fb.bb:getHeight()-205) + -- and active input slot + self:refreshText() + self.cursor:draw() -- show cursor = ready to input + fb:refresh(1, self.input_start_x-5, self.ypos, self.input_slot_w, self.h) +end + +function InputBox:setCalcMode() + --clear previous input + self.input_string = "" + self.charlist = {} + self.charpos = 1 + -- set proper layouts + self.layout = 4 -- digits + self.min_layout = 3 + self.max_layout = 4 +end + +function InputBox:PrepareStringToCalc() + local s = string.lower(self.input_string) + -- continue interpreting the input + local mathe = { "abs", "acos", "asin", "atan2", "atan", "ceil", "cosh", "cos", + "deg", "exp", "floor", "fmod", "frexp", "huge", "ldexp", "log10", "log", + "max", "min", "modf", "pi", "pow", "rad", "randomseed", "random", + "sinh", "sin", "sqrt", "tanh", "tan", } + -- to avoid any ambiguities (like sin & sinh), one has to replace by capitals + for i=1, #mathe do + s = string.gsub(s, mathe[i], string.upper("math."..mathe[i])) + end + -- some acronyms for constants & functions + s = string.gsub(s, "π", " math.pi ") + s = string.gsub(s, "е", " math.exp(1) ") + s = string.gsub(s, "&", " and ") + s = string.gsub(s, "|", " or ") + -- return the whole string in lowercase and eventually replace double "math." + return string.gsub(string.lower(s), "math.math.", "math.") +end + +-- define whether we need to calculate the result or to return 'self.input_string' +function InputBox:ModeDependentCommands() + if self.calcmode then + -- define what to do with the input_string + self.commands:add({KEY_FW_PRESS, KEY_ENTER}, nil, "joypad center", + "calculate the result", + function(self) + local s = self:PrepareStringToCalc() + if pcall(function () f = assert(loadstring("r = tostring("..s..")")) end) then + f() + self:clearText() + self.cursor:clear() + for i=1, string.len(r) do + table.insert(self.charlist, string.sub(r,i,i)) + end + self.charpos = #self.charlist + 1 + self.input_string = r + self:refreshText() + self.cursor:moveHorizontal(#self.charlist*self.fwidth) + self.cursor:draw() + fb:refresh(1, self.input_start_x-5, self.input_start_y-25, self.input_slot_w, self.h-25) + else + showInfoMsgWithDelay("Wrong Input! ", 2000, 1) + end -- if pcall + end -- function + ) + -- add the calculator help (short list of available functions) + -- or, might be better, to make some help document and open it in reader ?? + self.commands:add(KEY_M, MOD_ALT, "M", + "math functions available in calculator", + function(self) + self:defineCalcFunctions() + self:showHelpPage(self.calcfunctions, "Math Functions for Calculator") + end + ) + else -- return input_string & close input box + self.commands:add({KEY_FW_PRESS, KEY_ENTER}, nil, "joypad center", + "submit input content", + function(self) + if self.input_string == "" then + self.input_string = nil + end + return "break" + end + ) + -- delete calculator-specific help + self.commands:del(KEY_M, MOD_ALT, "M") + end -- if self.calcmode end ---------------------------------------------------- @@ -445,7 +650,6 @@ end ---------------------------------------------------- NumInputBox = InputBox:new{ - symbolmode = true, layout = 4, - charlist = {} + charlist = {}, }