1
0
mirror of https://github.com/20kdc/OC-KittenOS.git synced 2024-11-23 10:58:06 +11:00

some boring stuff, like better multimonitor & keyboard support

This commit is contained in:
20kdc 2018-03-22 02:33:52 +00:00
parent 53db9fd2cb
commit 87932ab26c
10 changed files with 418 additions and 83 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@
# leaving in preSH.tar.gz for anyone who's interested
# in how NOT to do compression
code.tar
work.tar
work
work/

View File

@ -2,24 +2,30 @@
-- No warranty is provided, implied or otherwise.
-- 'neolithic': Text Editor
-- This was textedit (femto) from KittenOS brought kicking and screaming into the NEO world
-- 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.
-- needs translation??? figure out how to do translation in the new system NICELY
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",
"^A, ^S, ^Q: Load, Save, New",
"^C, ^V, ^D: Copy, Paste, Delete Line",
"Keymap " .. unicode.getKeymap() .. ", to correct, type",
"\"A Cruel Jump's Kinesis: DVSQuest\"",
"Then, restart the text editor.",
"^" .. mappingFinal[1] .. ", ^" .. mappingFinal[2] .. ", ^" .. mappingFinal[3] .. ": Load, Save, New",
"^" .. mappingFinal[4] .. ", ^" .. mappingFinal[5] .. ", ^" .. mappingFinal[6] .. ": 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
"^J: Reset 'append' flag for Cut Lines",
"^K: Cut Line(s)",
"^" .. mappingFinal[7] .. ": Reset 'append' flag for Cut Lines",
"^" .. mappingFinal[8] .. ": Cut Line(s)",
"^<arrows>: Resize Win",
"'^' is Control.",
"Wide text can be pasted in,",
" using your 'actual' clipboard.",
"Wide text & clipboard supported.",
" ",
}

View File

@ -172,12 +172,13 @@ local function updateRegion(monitorId, x, y, w, h, surfaceSpanCache)
end
local function updateStatus()
statusLine = "Λ-¶: menu, ◣-Λ-C: Session hardkill"
statusLine = "Λ-¶: menu (launch 'pass' to logout)"
if surfaces[1] then
if #monitors > 1 then
statusLine = "Λ-: move, Λ-Z: switch, Λ-X: swMonitor"
-- 123456789X123456789X123456789X123456789X123456789X
statusLine = "Λ-+: move, Λ-Z: switch, Λ-X: swMonitor, Λ-C: close"
else
statusLine = "Λ-: move, Λ-Z: switch"
statusLine = "Λ-+: move, Λ-Z: switch, Λ-C: close"
end
end
statusLine = unicode.safeTextFormat(statusLine)
@ -370,12 +371,13 @@ everestProvider(function (pkg, pid, sendSig)
end
local m = 0
if renderingAllowed() then m = 1 end
if surfaces[1] then m = surfaces[1][1] end
local surf = {m, 1, 1, w, h}
local focusState = false
local llid = lid
lid = lid + 1
local specialDragHandler
surf[6] = function (ev, a, b, c)
surf[6] = function (ev, a, b, c, d, e)
-- Must forward surface events
if ev == "focus" then
focusState = a
@ -401,6 +403,13 @@ everestProvider(function (pkg, pid, sendSig)
end
b = b - 1
end
if ev == "scroll" then
b = b - 1
end
if ev == "drop" then
specialDragHandler = nil
b = b - 1
end
if ev == "line" then
if a == 1 then
local lw = surf[4]
@ -426,7 +435,7 @@ everestProvider(function (pkg, pid, sendSig)
handleSpan(surf, surf[4], a, " ", 0, 0)
a = a - 1
end
sendSig(llid, ev, a, b, c)
sendSig(llid, ev, a, b, c, d, e)
end
local osrf = surfaces[1]
table.insert(surfaces, 1, surf)
@ -580,19 +589,20 @@ while true do
for k, v in ipairs(monitors) do
if v[2] == s[2] then
local x, y = math.floor(s[3]), math.floor(s[4])
local ix, iy = s[3] - x, s[4] - y
local sid, lx, ly = surfaceAt(k, x, y)
if sid then
local os = surfaces[1]
local ns = table.remove(surfaces, sid)
table.insert(surfaces, 1, ns)
changeFocus(os)
ns[6]("touch", lx, ly)
ns[6]("touch", lx, ly, ix, iy, s[5])
end
break
end
end
end
if s[1] == "h.drag" then
if s[1] == "h.drag" or s[1] == "h.drop" or s[1] == "h.scroll" then
-- Pass to focus surface, even if out of bounds
local focus = surfaces[1]
if focus then
@ -600,7 +610,9 @@ while true do
if v[2] == s[2] then
if k == focus[1] then
local x, y = (math.floor(s[3]) - focus[2]) + 1, (math.floor(s[4]) - focus[3]) + 1
focus[6]("drag", x, y)
local ix, iy = s[3] - math.floor(s[3]), s[4] - math.floor(s[4])
-- Ok, so let's see...
focus[6](s[1]:sub(3), x, y, ix, iy, s[5])
end
break
end

View File

@ -3,9 +3,10 @@
-- s-donkonit : config, shutdown, screens
-- Doesn't matter what calls this service, because there's a mutex here.
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 computer = neo.requireAccess("k.computer", "shutting down")
local fs = neo.requireAccess("c.filesystem", "settings I/O")
@ -21,6 +22,7 @@ end
-- keys are pids
local targs = {} -- settings notify targs
local targsDC = {} -- displaycontrol settings notify targs
local targsSD = {} -- shutdown notify targs
local targsST = {} -- saving throws
@ -70,9 +72,9 @@ local function saveSettings()
st.close()
end
-- Monitor management stuff
-- [i] = screenProxy
local monitorPool = {}
-- {gpu, claimedLoseCallback}
-- [screenAddr] = {gpu, claimedLoseCallback}
local monitorClaims = {}
local function announceFreeMonitor(address, except)
@ -97,17 +99,38 @@ local function getGPU(monitor)
return bestG
end
local function sRattle(name, val)
for _, v in pairs(targs) do
v("set_setting", name, val)
end
if name:sub(1, 4) == "scr." then
for k, v in pairs(targsDC) do
if not targs[k] then
v("set_setting", name, val)
end
end
end
end
-- Settings integration w/ monitors
local function getMonitorSettings(a)
local w = tonumber(settings["scr.w." .. a]) or 80
local h = tonumber(settings["scr.h." .. a]) or 25
local d = tonumber(settings["scr.d." .. a]) or 8
w, h, d = math.floor(w), math.floor(h), math.floor(d)
return w, h, d
end
local function setupMonitor(gpu, monitor)
local maxW, maxH = gpu.maxResolution()
local maxD = gpu.maxDepth()
local w = tonumber(settings["scr.w." .. monitor.address]) or 80
local h = tonumber(settings["scr.h." .. monitor.address]) or 25
local d = tonumber(settings["scr.d." .. monitor.address]) or 8
w, h, d = math.floor(w), math.floor(h), math.floor(d)
local w, h, d = getMonitorSettings(monitor.address)
w, h, d = math.min(w, maxW), math.min(h, maxH), math.min(d, maxD)
settings["scr.w." .. monitor.address] = tostring(w)
settings["scr.h." .. monitor.address] = tostring(h)
settings["scr.d." .. monitor.address] = tostring(d)
sRattle("scr.w." .. monitor.address, tostring(w))
sRattle("scr.h." .. monitor.address, tostring(h))
sRattle("scr.d." .. monitor.address, tostring(d))
gpu.setResolution(w, h)
gpu.setDepth(d)
pcall(saveSettings)
@ -132,18 +155,17 @@ donkonitSPProvider(function (pkg, pid, sendSig)
local val = nil
if name == "password" then val = "" end
settings[name] = val
for _, v in pairs(targs) do
v("set_setting", name, val)
end
sRattle(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[name] = val
for _, v in pairs(targs) do
v("set_setting", name, val)
end
-- NOTE: Either a monitor is under application control,
-- or it's not under any control.
-- Monitor settings are applied on the transition to control.
sRattle(name, val)
pcall(saveSettings)
--saveSettings()
end,
@ -249,10 +271,11 @@ loadSettings()
local function rescanDevs()
monitorPool = {}
local hasGPU = gpus.list()()
for m in screens.list() do
if monitorClaims[m.address] then
monitorClaims[m.address][2](true)
for k, v in pairs(monitorClaims) do
v[2](true)
end
monitorClaims = {}
for m in screens.list() do
table.insert(monitorPool, m)
if hasGPU then
announceFreeMonitor(m.address)
@ -265,6 +288,45 @@ rescanDevs()
saveSettings()
-- --
glacierDCProvider(function (pkg, pid, sendSig)
targsDC[pid] = sendSig
return {
getKnownMonitors = function ()
local tbl = {}
-- yes, this should work fine so long as GMS is the *last* one #luaquirks
for k, v in ipairs(monitorPool) do
tbl[k] = {v.address, false, getMonitorSettings(v.address)}
end
for k, v in pairs(monitorClaims) do
table.insert(tbl, {k, true, getMonitorSettings(v.address)})
end
end,
changeMonitorSetup = function (ma, w, h, d)
neo.ensureType(ma, "string")
neo.ensureType(w, "number")
neo.ensureType(h, "number")
neo.ensureType(d, "number")
w = math.floor(w)
h = math.floor(h)
d = math.floor(d)
if w < 1 then error("Invalid width") end
if h < 1 then error("Invalid height") end
if d < 1 then error("Invalid depth") end
w, h, d = tostring(w), tostring(h), tostring(d)
settings["scr.w." .. ma] = w
settings["scr.h." .. ma] = h
settings["scr.d." .. ma] = d
sRattle("scr.w." .. ma, w)
sRattle("scr.h." .. ma, h)
sRattle("scr.d." .. ma, d)
pcall(saveSettings)
end,
forceRescan = rescanDevs
}
end)
-- main loop
while true do
local s = {coroutine.yield()}
if s[1] == "k.timer" then
@ -272,13 +334,19 @@ while true do
shutdownFin(shutdownMode)
end
if s[1] == "h.component_added" then
-- Before doing anything, is it worth it?
if s[3] == "gpu" or s[3] == "screen" then
rescanDevs()
end
end
if s[1] == "h.component_removed" then
if s[3] == "gpu" or s[3] == "screen" then
rescanDevs()
end
end
if s[1] == "k.procdie" then
targs[s[3]] = nil
targsDC[s[3]] = nil
targsSD[s[3]] = nil
if targsST[s[3]] then
if s[4] then

View File

@ -276,11 +276,28 @@ end
local function initializeSystem()
-- System has just booted, bristol is in charge
-- Firstly, initialize hardware to something sensible since we don't know scrcfg
gpu = neo.requestAccess("c.gpu").list()()
if gpu then
screen = neo.requestAccess("c.screen").list()()
if not screen then gpu = nil end
-- Firstly, since we don't know scrcfg, let's work out something sensible.
-- Note that we should try to keep going with this if there's no reason to do otherwise.
local gpuAc = neo.requestAccess("c.gpu")
local screenAc = neo.requestAccess("c.screen")
-- time to setup gpu/screen variables!
if gpuAc and screenAc then
local scrBestWHD = 0
for s in screenAc.list() do
for g in gpuAc.list() do
g.bind(s.address)
local w, h = g.maxResolution()
local whd = w * h * g.maxDepth()
if whd > scrBestWHD then
screen = s
gpu = g
scrBestWHD = whd
end
end
if screen then
break
end
end
end
if gpu then
screen = screen.address

View File

@ -2,11 +2,7 @@
-- This is released into the public domain.
-- No warranty is provided, implied or otherwise.
-- NOTE: If it's not "local", it's because k.root ought to access it.
-- List of things that apply:
-- primaryDisk, timers, libraries, processes, accesses, wrapMeta,
-- distEvent, baseProcEnv, loadLibraryInner, retrieveAccess,
-- start
-- NOTE: local is considered unnecessary in kernel since 21 March
-- Debugging option, turns process errors into actual errors (!)
local criticalFailure = false
@ -14,9 +10,9 @@ local criticalFailure = false
local readBufSize = 2048
-- A function used for logging, usable by programs.
local emergencyFunction = function () end
-- Comment this out if you don't want programs to have
-- access to ocemu's logger.
local emergencyFunction = function () end
local ocemu = component.list("ocemu", true)()
if ocemu then
ocemu = component.proxy(ocemu)
@ -77,7 +73,13 @@ function unicode.undoSafeTextFormat(s)
for i = 1, unicode.len(s) do
if not ignoreNext then
local ch = unicode.sub(s, i, i)
ignoreNext = unicode.charWidth(ch) ~= 1
if unicode.charWidth(ch) ~= 1 then
if unicode.sub(s, i + 1, i + 1) ~= " " then
ch = " "
else
ignoreNext = true
end
end
res = res .. ch
else
ignoreNext = false
@ -86,6 +88,168 @@ 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, "AOEUIDHTN"},
{30, "aoeuidhtn"},
{45, "QJKXBM"},
{45, "qjkxbm"},
},
["??-dvorak-full"] = {
{16, "\"<>PYFGCRL"},
{16, "',.pyfgcrl"},
{30, "AOEUIDHTN"},
{30, "aoeuidhtn"},
{44, ":QJKXBM"},
{44, ";qjkxbm"},
},
["cz-qwertz"] = {
{2, "+ěščřžýáíé="}, -- The last letter is a *compose key*. #WTF
{2, "1234567890%"},
{15, "\tQWERTZUIOP/("},
{15, "\tqwertzuiopú)"},
{30, "ASDFGHJKL\"!'"},
{30, "asdfghjklů§"},
{44, "YXCVBNM?:_"},
{44, "yxcvbnm,.-"},
},
["de-qwertz"] = {
{2, "1234567890ß"}, -- another one?
{2, "!\"§$%&/()=?"},
{15, "\tQWERTZUIOPÜ*"},
{15, "\tqwertzuiopü+"},
{30, "ASDFGHJKLÖÄ"},
{30, "asdfghjklÖÄ"},
{44, "YXCVBNM;:_"},
{44, "yxcvbnm,.-"},
},
["uk-qwerty"] = {
{41, "`"}, {41, "¬"},
{2, "1234567890-="},
{2, "!\"£$%^&*()_+"},
{15, "\tQWERTYUIOP{}"},
{15, "\tqwertyuiop[]"},
{30, "ASDFGHJKL:@"},
{30, "asdfghjkl;'"},
{44, "ZXCVBNM<>?"},
{44, "zxcvbnm,./"},
},
["us-qwerty"] = {
{41, "`"}, {41, "~"},
{2, "1234567890-="},
{2, "!@#$%^&*()_+"},
{15, "\tQWERTYUIOP{}\r"},
{15, "\tqwertyuiop[]\r"},
{30, "ASDFGHJKL\"|"},
{30, "asdfghjkl'\\"},
{44, "ZXCVBNM<>?"},
{44, "zxcvbnm,./"},
}
}
local unknownKeymapContains = {}
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)
for _, v in ipairs(keymaps[km]) do
local spanLen = unicode.len(v[2])
for i = 1, spanLen do
if unicode.sub(v[2], i, i) == ch then
return v[1] + i - 1
end
end
end
end
unicode.getChByKC = function (kc, km)
for _, v in ipairs(keymaps[km]) do
local spanLen = unicode.len(v[2])
if kc >= v[1] and kc < v[1] + spanLen then
return unicode.sub(v[2], kc + 1 - v[1], kc + 1 - v[1])
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 unknownKeymapContains[ka] ~= kc then
unknownKeymapContains[ka] = kc
table.insert(keymaps["unknown"], {kc, ka})
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(unknownKeymapContains) 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 = {}
for i = 1, unicode.len(text) do
local ch = unicode.sub(text, i, i)
local okc = unicode.getKCByCh(ch, "uk-qwerty") or 0
rtext = rtext .. (unicode.getChByKC(okc, currentKeymap) or unicode.getChByKC(okc, "unknown") or ch)
codes[i] = unicode.getKCByCh(ch, currentKeymap) or unicode.getKCByCh(ch, "unknown")
end
return rtext, codes
end
local function loadfile(s, e)
local h = primaryDisk.open(s)
if h then
@ -308,6 +472,7 @@ function baseProcEnv()
totalIdleTime = function () return idleTime end,
ensurePath = ensurePath,
ensurePathComponent = ensurePathComponent,
ensureType = ensureType
}
}
end
@ -631,6 +796,9 @@ while true do
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)))

View File

@ -216,6 +216,45 @@ return function (event, neo)
end
end
rotateSelIndex()
local function moveIndex(vertical, negative)
if not controls[selIndex] then return end
local currentMA, currentOA = controls[selIndex].y, controls[selIndex].x
local currentMAX = controls[selIndex].y + controls[selIndex].h - 1
if vertical then
currentMA, currentOA = controls[selIndex].x, controls[selIndex].y
currentMAX = controls[selIndex].x + controls[selIndex].w - 1
end
local bestOA = 9001
local bestSI = selIndex
if negative then
bestOA = -9000
end
for k, v in ipairs(controls) do
if (k ~= selIndex) and v.selectable then
local ma, oa = v.y, v.x
local max = v.y + v.h - 1
if vertical then
ma, oa = v.x, v.y
max = v.x + v.w - 1
end
if (ma >= currentMA and ma <= currentMAX) or (max >= currentMA and max <= currentMAX)
or (currentMA >= ma and currentMA <= max) or (currentMAX >= ma and currentMAX <= max) then
if negative then
if (oa < currentOA) and (oa > bestOA) then
bestOA = oa
bestSI = k
end
else
if (oa > currentOA) and (oa < bestOA) then
bestOA = oa
bestSI = k
end
end
end
end
end
selIndex = bestSI
end
local function doLine(window, a)
window.span(1, a, (" "):rep(w), bg, fg)
@ -237,7 +276,17 @@ return function (event, neo)
end
end
return function (window, ev, a, b, c)
local function moveIndexAU(window, vertical, negative)
local c1 = controls[selIndex]
moveIndex(vertical, negative)
local c2 = controls[selIndex]
local cache = {}
if c1 then doZone(window, c1, cache) end
if c2 then doZone(window, c2, cache) end
end
return function (window, ev, a, b, c, d, e)
-- X,Y,Xi,Yi,B
if ev == "touch" then
local found = nil
for k, v in ipairs(controls) do
@ -263,20 +312,35 @@ return function (event, neo)
if c2 then
doZone(window, c2, cache)
if c2.touch then
c2.touch(window, function () doZone(window, c2) end, (a - c2.x) + 1, (b - c2.y) + 1)
c2.touch(window, function () doZone(window, c2) end, (a - c2.x) + 1, (b - c2.y) + 1, c, d, e)
end
end
end
end
if ev == "drag" then
-- X,Y,Xi,Yi,B (or D for scroll)
elseif ev == "drag" or ev == "drop" or ev == "scroll" then
if controls[selIndex] then
if controls[selIndex].drag then
controls[selIndex].drag(window, function () doZone(window, controls[selIndex]) end, (a - controls[selIndex].x) + 1, (b - controls[selIndex].y) + 1)
if controls[selIndex][ev] then
controls[selIndex][ev](window, function () doZone(window, controls[selIndex]) end, (a - controls[selIndex].x) + 1, (b - controls[selIndex].y) + 1, c, d, e)
end
end
elseif ev == "key" then
if b == 203 then
if c then
moveIndexAU(window, false, true)
end
if ev == "key" then
if a == 9 then
elseif b == 205 then
if c then
moveIndexAU(window, false, false)
end
elseif b == 200 then
if c then
moveIndexAU(window, true, true)
end
elseif b == 208 then
if c then
moveIndexAU(window, true, false)
end
elseif a == 9 then
if c then
local c1 = controls[selIndex]
rotateSelIndex()
@ -285,18 +349,14 @@ return function (event, neo)
if c1 then doZone(window, c1, cache) end
if c2 then doZone(window, c2, cache) end
end
else
if controls[selIndex] then
elseif controls[selIndex] then
if controls[selIndex].key then
controls[selIndex].key(window, function () doZone(window, controls[selIndex]) end, a, b, c)
end
end
end
end
if ev == "line" then
elseif ev == "line" then
doLine(window, a)
end
if ev == "close" then
elseif ev == "close" then
closing(window)
end
end, doZone

View File

@ -2,18 +2,21 @@
-- No warranty is provided, implied or otherwise. XX
local sector = io.write -- XX
-- BUNDIVIDE reference implementation for integration XX
local Cs,Cbu,Cb,Cw,Cp,Ci,CP,CB,CD={},128,"",128,""
CP=function(d,b,i)
i=1
while i<=#d do
b=d:byte(i)
i=i+1
local Cs,Cbu,Cb,Cw,Cp,Ct,Ci,CP,CB,CD={},128,"",128,"",""
CP=function(d,b)
Ct=Ct..d
while#Ct>2 do
b=Ct:byte()
Ct=Ct:sub(2)
if b==127then
b=d:byte(i)
i=i+1
b=Ct:byte()
Ct=Ct:sub(2)
if b==127then
b=d:byte(i)+254
i=i+1
b=Ct:byte()+254
if b>255then
b=b-256
end
Ct=Ct:sub(2)
else
b=b+127
end
@ -63,4 +66,4 @@ CD(io.read("*a")) -- XX
--local Ch=D.open("init-bdivide.lua","rb")--
--dieCB=function()D.close(Ch)D.remove("init-bdivide.lua")end--
--while true do local t=D.read(Ch, 64)if not t then break end CD(t)end--
CD("\x00\x00")CP(Cs[Cw])
CD("\x00\x00")CP(Cs[Cw] .. "\x00\x00")

View File

@ -52,7 +52,7 @@ local function tA(s)
else
tFN = s:sub(1, 100):gsub("\x00", "")
local sz = convoct(s:sub(125, 135))
if tFN:sub(1, 5) ~= "work/" then
if tFN:sub(1, 5) ~= "code/" then
tW = math.ceil(sz / 512)
else
tFN = tFN:sub(6)

View File

@ -3,7 +3,7 @@
# This is released into the public domain.
# No warranty is provided, implied or otherwise.
echo "WARNING: This will rm -rf the 'work' folder."
# safety measure: unless we are likely in the right folder, DO NOT CONTINUE
git status && stat imitclaw.lua code/apps/sys-init.lua && rm -rf work work.tar
lua imitclaw.lua && tar -cf work.tar work
rm code.tar
# Hey, look behind you, there's nothing to see here.
# ... ok, are they seriously all named "Mann"?
tar --owner=gray:0 --group=mann:0 -cf code.tar code