diff --git a/code/apps/app-flash.lua b/code/apps/app-flash.lua new file mode 100644 index 0000000..dfba972 --- /dev/null +++ b/code/apps/app-flash.lua @@ -0,0 +1,9 @@ +-- This is released into the public domain. +-- No warranty is provided, implied or otherwise. + +local event = require("event")(neo) +local neoux = require("neoux")(event, neo) + +-- label +-- [ ] +-- diff --git a/code/apps/app-textedit.lua b/code/apps/app-textedit.lua index bdd8ff8..2d66232 100644 --- a/code/apps/app-textedit.lua +++ b/code/apps/app-textedit.lua @@ -5,24 +5,16 @@ -- This was textedit (femto) from KittenOS 'ported' to NEO. -- It also has fixes for bugs involving wide text, and runs faster due to the chars -> lines change. -local mapping, _ = unicode.keymap("ASQCVDJK") -local mappingFinal = {} -for i = 1, #mapping do - mappingFinal[i] = unicode.sub(mapping, i, i) -end local lines = { "Neolithic: Text Editor", - "Keymap " .. unicode.getKeymap() .. ", to correct, type", - " the alphabet in capitals.", - "Then, restart the text editor.", - "^" .. mappingFinal[1] .. ", ^" .. mappingFinal[2] .. ", ^" .. mappingFinal[3] .. ": Load, Save, New", - "^" .. mappingFinal[4] .. ", ^" .. mappingFinal[5] .. ", ^" .. mappingFinal[6] .. ": Copy, Paste, Delete Line", + "F3, F4, F1: Load, Save, New", + "F5, F6, ^←: Copy, Paste, Delete Line", -- These two are meant to replace similar functionality in GNU Nano -- (which I consider the best console text editor out there - Neolithic is an *imitation* and a poor one at that), -- except fixing a UI flaw by instead making J responsible for resetting the append flag, -- so the user can more or less arbitrarily mash together lines - "^" .. mappingFinal[7] .. ": Reset 'append' flag for Cut Lines", - "^" .. mappingFinal[8] .. ": Cut Line(s)", + "F7: Reset 'append' flag for Cut Lines", + "F8: Cut Line(s)", "^: Resize Win", "'^' is Control.", "Wide text & clipboard supported.", @@ -35,14 +27,7 @@ local lines = { -- The way I have things setup is that you perform J then K(repeat) *instead*, which means you have to explicitly say "destroy current clipboard". local event = require("event")(neo) -local clipboard = neo.requestAccess("x.neo.pub.clip.text") -if not clipboard then - local clipboardData = "" - clipboard = { - copy = function (text) clipboardData = text end, - paste = function () return clipboardData end - } -end +local clipsrc = neo.requireAccess("x.neo.pub.globals", "clipboard") local cursorX = 1 local cursorY = math.ceil(#lines / 2) @@ -207,8 +192,10 @@ local function ev_key(ka, kc, down) ctrlFlag = down return false end + -- Action keys + if not down then return false end if ctrlFlag then - if not down then return false end + -- Control Action Keys if kc == 200 then -- Up sH = sH - 1 if sH == 0 then @@ -231,40 +218,87 @@ local function ev_key(ka, kc, down) sW = sW + 1 sW, sH = window.setSize(sW, sH) end - if kc == 31 then -- S - startSave() + if kc == 14 then -- ^Backspace + delLine() + return true end - if kc == 30 then -- A - startLoad() + else + -- Non-Control Action Keys + -- Basic Action Keys + if kc == 200 or kc == 201 then -- Go up one - go up page + local moveAmount = 1 + if kc == 201 then + moveAmount = math.floor(sH / 2) + end + cursorY = cursorY - moveAmount + if cursorY < 1 then + cursorY = 1 + end + clampCursorX() + return true end - if kc == 16 then -- Q + if kc == 208 or kc == 209 then -- Go down one - go down page + local moveAmount = 1 + if kc == 209 then + moveAmount = math.floor(sH / 2) + end + cursorY = cursorY + moveAmount + if cursorY > #lines then + cursorY = #lines + end + clampCursorX() + return true + end + if kc == 203 then + if cursorX > 1 then + cursorX = cursorX - 1 + else + if cursorY > 1 then + cursorY = cursorY - 1 + cursorX = unicode.len(lines[cursorY]) + 1 + else + return false + end + end + return true + end + if kc == 205 then + cursorX = cursorX + 1 + if clampCursorX() then + if cursorY < #lines then + cursorY = cursorY + 1 + cursorX = 1 + end + end + return true + end + -- Extra Non-Control Keys + if kc == 199 then + cursorX = 1 + return true + end + if kc == 207 then + cursorX = unicode.len(lines[cursorY]) + 1 + return true + end + -- Major Actions + if kc == 59 then -- F1 lines = {""} cursorX = 1 cursorY = 1 return true end - if kc == 32 then -- D - delLine() - return true + if kc == 61 then -- F3 + startLoad() end - if kc == 46 then -- C - clipboard.copy(lines[cursorY]) + if kc == 62 then -- F4 + startSave() end - if kc == 36 then -- J - appendFlag = false + if kc == 63 then -- F5 + clipsrc.setSetting("clipboard", lines[cursorY]) end - if kc == 37 then -- K - if appendFlag then - local base = clipboard.paste() - clipboard.copy(base .. "\n" .. delLine()) - else - clipboard.copy(delLine()) - end - appendFlag = true - return true - end - if kc == 47 then -- V - local tx = clipboard.paste() + if kc == 64 then -- F6 + local tx = clipsrc.getSetting("clipboard") or "" local txi = tx:find("\n") local nt = {} while txi do @@ -278,85 +312,39 @@ local function ev_key(ka, kc, down) end return true end - return false - end - -- action keys - if not down then - return false - end - if kc == 200 or kc == 201 then -- Go up one - go up page - local moveAmount = 1 - if kc == 201 then - moveAmount = math.floor(sH / 2) + if kc == 65 then -- F7 + appendFlag = false end - cursorY = cursorY - moveAmount - if cursorY < 1 then - cursorY = 1 + if kc == 66 then -- F8 + if appendFlag then + local base = clipsrc.getSetting("clipboard") + clipsrc.setSetting("clipboard", base .. "\n" .. delLine()) + else + clipsrc.setSetting("clipboard", delLine()) + end + appendFlag = true + return true end - clampCursorX() - return true end - if kc == 208 or kc == 209 then -- Go down one - go down page - local moveAmount = 1 - if kc == 209 then - moveAmount = math.floor(sH / 2) - end - cursorY = cursorY + moveAmount - if cursorY > #lines then - cursorY = #lines - end - clampCursorX() - return true - end - if kc == 203 then - if cursorX > 1 then - cursorX = cursorX - 1 - else - if cursorY > 1 then + -- Letters + if ka ~= 0 then + if ka == 8 then + if cursorX == 1 then + if cursorY == 1 then + return false + end + local l = table.remove(lines, cursorY) cursorY = cursorY - 1 cursorX = unicode.len(lines[cursorY]) + 1 + lines[cursorY] = lines[cursorY] .. l else - return false + local a, b = splitCur() + a = unicode.sub(a, 1, unicode.len(a) - 1) + lines[cursorY] = a.. b + cursorX = cursorX - 1 end + return true end - return true - end - if kc == 205 then - cursorX = cursorX + 1 - if clampCursorX() then - if cursorY < #lines then - cursorY = cursorY + 1 - cursorX = 1 - end - end - return true - end - if kc == 199 then - cursorX = 1 - return true - end - if kc == 207 then - cursorX = unicode.len(lines[cursorY]) + 1 - return true - end - if ka == 8 then - if cursorX == 1 then - if cursorY == 1 then - return false - end - local l = table.remove(lines, cursorY) - cursorY = cursorY - 1 - cursorX = unicode.len(lines[cursorY]) + 1 - lines[cursorY] = lines[cursorY] .. l - else - local a, b = splitCur() - a = unicode.sub(a, 1, unicode.len(a) - 1) - lines[cursorY] = a.. b - cursorX = cursorX - 1 - end - return true - end - if ka ~= 0 then putLetter(unicode.char(ka)) return true end diff --git a/code/apps/sys-glacier.lua b/code/apps/sys-glacier.lua index 42f52e9..65d7d7b 100644 --- a/code/apps/sys-glacier.lua +++ b/code/apps/sys-glacier.lua @@ -6,7 +6,7 @@ local donkonitSPProvider = neo.requireAccess("r.neo.sys.manage", "creating NEO core APIs") -- Restrict to s- -- Doesn't matter what calls this service, because there's a mutex here. local donkonitRDProvider = neo.requireAccess("r.neo.sys.screens", "creating NEO core APIs") -local glacierDCProvider = neo.requireAccess("r.neo.sys.randr", "creating NEO core APIs") +local glacierDCProvider = neo.requireAccess("r.neo.pub.globals", "creating NEO core APIs") local computer = neo.requireAccess("k.computer", "shutting down") local fs = neo.requireAccess("c.filesystem", "settings I/O") @@ -14,6 +14,7 @@ local gpus = neo.requireAccess("c.gpu", "screen control") local screens = neo.requireAccess("c.screen", "screen control") neo.requireAccess("s.h.component_added", "HW management") neo.requireAccess("s.h.component_removed", "HW management") +neo.requireAccess("s.h.key_down", "Keymap guesswork") local function shutdownFin(reboot) -- any final actions donkonit needs to take here @@ -39,6 +40,7 @@ local settings = { -- The list of settings is here: -- password password = "", + ["pub.clipboard"] = "", ["sys-init.shell"] = "sys-everest", ["run.sys-icecap"] = "yes", -- scr.w/h/d. @@ -115,7 +117,7 @@ local function sRattle(name, val) for _, v in pairs(targs) do v("set_setting", name, val) end - if name:sub(1, 4) == "scr." then + if name:sub(1, 4) == "scr." or name:sub(1, 4) == "pub." then for k, v in pairs(targsDC) do if not targs[k] then v("set_setting", name, val) @@ -160,6 +162,7 @@ donkonitSPProvider(function (pkg, pid, sendSig) end return s end, + -- NOTE: REPLICATED IN GB getSetting = function (name) if type(name) ~= "string" then error("Setting name must be string") end return settings[name] @@ -167,7 +170,7 @@ donkonitSPProvider(function (pkg, pid, sendSig) delSetting = function (name) if type(name) ~= "string" then error("Setting name must be string") end local val = nil - if name == "password" then val = "" end + if name == "password" or name == "pub.clipboard" then val = "" end settings[name] = val sRattle(name, val) pcall(saveSettings) @@ -181,8 +184,8 @@ donkonitSPProvider(function (pkg, pid, sendSig) -- Monitor settings are applied on the transition to control. sRattle(name, val) pcall(saveSettings) - --saveSettings() end, + -- registerForShutdownEvent = function () targsSD[pid] = sendSig end, @@ -338,7 +341,27 @@ glacierDCProvider(function (pkg, pid, sendSig) sRattle("scr.d." .. ma, d) pcall(saveSettings) end, - forceRescan = rescanDevs + forceRescan = rescanDevs, + -- NOTE: "pub." prefixed version of functions in sys.manage + getSetting = function (name) + if type(name) ~= "string" then error("Setting name must be string") end + return settings["pub." .. name] + end, + delSetting = function (name) + if type(name) ~= "string" then error("Setting name must be string") end + local val = nil + if name == "clipboard" then val = "" end + settings["pub." .. name] = val + sRattle("pub." .. name, val) + pcall(saveSettings) + end, + setSetting = function (name, val) + if type(name) ~= "string" then error("Setting name must be string") end + if type(val) ~= "string" then error("Setting value must be string") end + settings["pub." .. name] = val + sRattle("pub." .. name, val) + pcall(saveSettings) + end } end) diff --git a/code/data/app-claw/local.lua b/code/data/app-claw/local.lua index d71ddd7..6e77b41 100644 --- a/code/data/app-claw/local.lua +++ b/code/data/app-claw/local.lua @@ -109,6 +109,20 @@ return { "apps/app-textedit.lua" }, }, + ["app-flash"] = { + desc = "KittenOS NEO EEPROM Flasher", + v = 0, + app = "app-flash", + deps = { + "neo" + }, + dirs = { + "apps" + }, + files = { + "apps/app-flash.lua" + }, + }, ["app-pass"] = { desc = "KittenOS NEO Password Setter & Logout", v = 0, diff --git a/code/init.lua b/code/init.lua index 1b304ff..d2d5aa7 100644 --- a/code/init.lua +++ b/code/init.lua @@ -88,127 +88,6 @@ function unicode.undoSafeTextFormat(s) return res end --- Yes, this is what I used the freed up SR space for. --- Think of this as my apology for refusing translation support on NEO. -keymaps = { - -- 'synth' keymap - ["unknown"] = { - }, - ["??-qwerty"] = { - {16, "QWERTYUIOP"}, - {16, "qwertyuiop"}, - {30, "ASDFGHJKL"}, - {30, "asdfghjkl"}, - {44, "ZXCVBNM"}, - {44, "zxcvbnm"}, - }, - ["??-qwertz"] = { - {16, "QWERTZUIOP"}, - {16, "qwertzuiop"}, - {30, "ASDFGHJKL"}, - {30, "asdfghjkl"}, - {44, "YXCVBNM"}, - {44, "yxcvbnm"}, - }, - ["??-dvorak"] = { - {19, "PYFGCRL"}, - {19, "pyfgcrl"}, - {30, "AOEUIDHTNS"}, - {30, "aoeuidhtns"}, - {45, "QJKXBMWVZ"}, - {45, "qjkxbmwvz"}, - }, -} -for k, v in pairs(keymaps) do - for k2, v2 in ipairs(v) do - for i = 1, unicode.len(v2[2]) do - v[unicode.sub(v2[2], i, i)] = i + v2[1] - 1 - end - v2[k2] = nil - end -end - -currentKeymap = "unknown" --- Not really part of this package, but... -unicode.getKeymap = function () - return currentKeymap -end --- raw info functions, they return nil if they don't know --- Due to a fantastic oversight, unicode.byte or such doesn't exist in OCEmu, --- so things are managed via "Ch" internally. -unicode.getKCByCh = function (ch, km) - return keymaps[km][ch] -end -unicode.getChByKC = function (kc, km) - for ach, akc in pairs(keymaps[km]) do - if akc == kc then - return ach - end - end -end -local function keymapDetect(ka, kc) - if ka == 0 then return end - if kc == 0 then return end - -- simple algorithm, does the job - -- emergencyFunction("KD: " .. unicode.char(signal[3]) .. " " .. signal[4]) - ka = unicode.char(ka) - if keymaps["unknown"][ka] ~= kc then - keymaps["unknown"][ka] = kc - else - return - end - - -- 25% of used keys must be known to pass - local bestRatio = 0.25 - local bestName = "unknown" - for k, _ in pairs(keymaps) do - if k ~= "unknown" then - local count = 0 - local total = 0 - for kCh, kc in pairs(keymaps["unknown"]) do - if unicode.getKCByCh(kCh, k) == kc then - count = count + 1 - end - total = total + 1 - end - local r = count / math.max(1, total) - if r > bestRatio then - bestRatio = r - bestName = k - end - end - end - if currentKeymap ~= bestName then emergencyFunction("Switching to Keymap " .. bestName) end - currentKeymap = bestName -end --- rtext, codes (codes can end up nil) --- rtext is text's letters switched over --- (for code that will still use the same keycodes, --- but wants to display correct text) --- codes is the keycodes mapped based on the letters -unicode.keymap = function (text) - local km = unicode.getKeymap() - local rtext = "" - local codes = {} - local notQ = false - for i = 1, unicode.len(text) do - local ch = unicode.sub(text, i, i) - local okc = unicode.getKCByCh(ch, "??-qwerty") or 0 - local ch2 = unicode.getChByKC(okc, currentKeymap) or unicode.getChByKC(okc, "unknown") - if not ch2 then - ch2 = "?" - else - notQ = true - end - rtext = rtext .. ch2 - codes[i] = unicode.getKCByCh(ch, currentKeymap) or unicode.getKCByCh(ch, "unknown") - end - if not notQ then - rtext = text - end - return rtext, codes -end - local function loadfile(s, e) local h = primaryDisk.open(s) if h then @@ -714,52 +593,48 @@ end if not start("sys-init") then error("Could not start sys-init") end while true do - local tmr = nil - for i = 1, 16 do - tmr = nil - local now = computer.uptime() - local breaking = false -- Used when a process dies - in this case it's assumed OC just did something drastic - local didAnything = false - local k = 1 - while timers[k] do - local v = timers[k] - if v[1] <= now then - if v[2](table.unpack(v, 3)) then - breaking = true - tmr = 0.05 - break - end - didAnything = true - v = nil - else - if not tmr then - tmr = v[1] + local ok, r = pcall(function() + local tmr = nil + for i = 1, 16 do + tmr = nil + local now = computer.uptime() + local breaking = false -- Used when a process dies - in this case it's assumed OC just did something drastic + local didAnything = false + local k = 1 + while timers[k] do + local v = timers[k] + if v[1] <= now then + table.remove(timers, k) + if v[2](table.unpack(v, 3)) then + breaking = true + tmr = 0.05 + break + end + didAnything = true else - tmr = math.min(tmr, v[1]) + if not tmr then + tmr = v[1] + else + tmr = math.min(tmr, v[1]) + end + k = k + 1 end end - if v then - k = k + 1 - else - table.remove(timers, k) - end + if breaking then break end + -- If the system didn't make any progress, then we're waiting for a signal (this includes timers) + if not didAnything then break end end - if breaking then break end - -- If the system didn't make any progress, then we're waiting for a signal (this includes timers) - if not didAnything then break end - end - now = computer.uptime() -- the above probably took a while - local dist = nil - if tmr then - dist = tmr - now - if dist < 0.05 then dist = 0.05 end - end - local signal = {computer.pullSignal(dist)} - if signal[1] == "key_down" then - keymapDetect(signal[3], signal[4]) - end - idleTime = idleTime + (computer.uptime() - now) - if signal[1] then - distEvent(nil, "h." .. signal[1], select(2, table.unpack(signal))) - end + now = computer.uptime() -- the above probably took a while + local dist = nil + if tmr then + dist = tmr - now + if dist < 0.05 then dist = 0.05 end + end + local signal = {computer.pullSignal(dist)} + idleTime = idleTime + (computer.uptime() - now) + if signal[1] then + distEvent(nil, "h." .. signal[1], select(2, table.unpack(signal))) + end + end) + if not ok then emergencyFunction("K-WARN " .. tostring(r)) end end