mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2024-11-16 23:48:05 +11:00
Compare commits
No commits in common. "master" and "neo-r4" have entirely different histories.
11
.gitignore
vendored
11
.gitignore
vendored
@ -1,8 +1,9 @@
|
||||
# This is released into the public domain.
|
||||
# No warranty is provided, implied or otherwise.
|
||||
|
||||
# leaving in preSH.tar.gz for anyone who's interested
|
||||
# in how NOT to do compression
|
||||
code.tar
|
||||
code/data/app-claw/*
|
||||
work.tar
|
||||
work
|
||||
work/
|
||||
@ -19,10 +20,6 @@ repobuild/*/*
|
||||
repobuild/*/*/
|
||||
repobuild/*/*/*
|
||||
|
||||
laboratory/ocemu.cfg
|
||||
laboratory/bios.lua
|
||||
laboratory/data
|
||||
laboratory/log
|
||||
laboratory/*/
|
||||
laboratory/*/*
|
||||
laboratory/*/*/
|
||||
@ -33,9 +30,7 @@ laboratory/*/*/*/*
|
||||
inst.lua
|
||||
# Available as the respective release
|
||||
inst-gold.lua
|
||||
# Compression stuff
|
||||
inst/iSymTab
|
||||
# internal
|
||||
com2/code.tar.bd
|
||||
upldr.sh
|
||||
upldr-dev.sh
|
||||
upldr-gold.sh
|
||||
|
75
NOTE-TO-MS.asc
Normal file
75
NOTE-TO-MS.asc
Normal file
@ -0,0 +1,75 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA256
|
||||
|
||||
- -- To Microsoft.
|
||||
- -- You deserve to get yourselves investigated by Trading Standards.
|
||||
- -- I don't mean that in a "and then everything comes out okay" way,
|
||||
- -- I mean that as in a "you deserve to be legitimately threatened with being shutdown" way.
|
||||
- -- See that MultiMC issue, #2223, about the Windows 10 thing?
|
||||
- -- That's the beginnings of what you've caused, and don't you dare deny the intent.
|
||||
- -- In what world is swapping around the names of two products, both in
|
||||
- -- active sales no less, to get one to be chosen over the other by an
|
||||
- -- uninformed buyer *not illegal*?
|
||||
|
||||
- -- To anyone else, I say this.
|
||||
- -- If you're affected by this, just pirate the Java edition.
|
||||
- -- You have been affected by what I can say without contradiction is a campaign of lies.
|
||||
- -- Deliberate or otherwise, but history would point in favour of a calculated attack.
|
||||
- -- Take what is frankly rightfully yours.
|
||||
- -- Oh, Microsoft, did you not like that? I don't care, and it is plainly obvious why I shouldn't care.
|
||||
|
||||
- -- To the Mojang team - the *real* Mojang team (Anyone working on Bedrock is exempt) - I pity you,
|
||||
- -- but I'm afraid I have to recommend this course of action.
|
||||
- -- There is no other way. I'm sure you already know what Microsoft is like first-hand.
|
||||
- -- I'm sure you've read the reports and you know Microsoft will lobby their way
|
||||
- -- past anything I could even suggest to any politician, if it even got that far.
|
||||
- -- I'm sure you can already see your presumed redundancies coming, and I doubt I hasten it.
|
||||
- -- And frankly, preventing Microsoft from abusing Minecraft as a lock-in tactic in whatever way I can
|
||||
- -- takes priority.
|
||||
|
||||
- -- To those who doubted what I said to them when I said it to them,
|
||||
- -- to those who doubt me now, know this. It's happening, it's real,
|
||||
- -- there is proof with basic searches.
|
||||
|
||||
- -- To those who are ignorant, and yet scared to let anyone leave them,
|
||||
- -- THOSE WITHOUT WINDOWS 10 ON THEIR DESKTOPS WON'T BE ABLE TO JOIN YOU
|
||||
- -- ON MC IF THIS GOES AS THEY LIKELY INTEND.
|
||||
- -- You may doubt my "likely", but remember this:
|
||||
- -- We thought they would do this long ago, when Microsoft bought Mojang.
|
||||
- -- It took time, yes. But it started to happen and when it did, everything started moving into place.
|
||||
- -- The "Better Together" (unless on a non-Windows 10 desktop) update was simply the end of a journey.
|
||||
- -- When I look back, the guesses - mine and others - as to what they will do next have been delayed,
|
||||
- -- but they are occurring, along with new horrors that I did not expect,
|
||||
- -- like the commercialization of that offered by mods for free here on the "Java Edition".
|
||||
- -- You can argue all you like about how they put work into that stuff,
|
||||
- -- fact is, Bedrock is a downgrade.
|
||||
- -- You could argue about performance, but - Mods fix the performance issues,
|
||||
- -- and they aren't exactly hard to install. Download Forge installer. Run Forge installer.
|
||||
- -- Copy one file. Done.
|
||||
- -- You cannot argue about playerbase - people are left behind, unable to go to Bedrock.
|
||||
- -- Even if you claim it's their fault for using Windows 10, how much have you somehow missed
|
||||
- -- about Windows 10's various nastiness? There's a laptop basically unusable for anything real-time here
|
||||
- -- on Windows 10 because of an update that screwed it over, and no, a reset did not fix it. Nothing did.
|
||||
- -- Except moving it to another OS, but of course, that wouldn't work so well if Bedrock was a concern.
|
||||
- -- Moddability has been, and probably always will be, destroyed on Bedrock.
|
||||
- -- Sure, you'll eventually get some more and more access,
|
||||
- -- but there's a reason the way Minecraft modding went
|
||||
- -- lead to the inventive and amazing mods out there,
|
||||
- -- and it certainly wasn't a bunch of "behavior packs"!
|
||||
|
||||
- -- To those who wonder what the hell this is doing here,
|
||||
- -- I don't care. Feel free to remove the file from your local machines,
|
||||
- -- but if you send a PR asking for its removal, I *will* reject it instantly.
|
||||
|
||||
- -- -20kdc
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQEzBAEBCAAdFiEE4HrK8U+8321iGlEUALn5S4V/2fkFAlrafToACgkQALn5S4V/
|
||||
2fkW/wf/afn8PjeCYyNOWNhGmELNO5dL3eWaBb86KAiDZXMYPmCifDiXOOmYeq2t
|
||||
3cqcDXujOQJN7PE8RBzrVSIm2kjLtQXoFuhww6A9p3LuyXdPT0WykMroPM5xYrrH
|
||||
7c6VtaWkXngHn/Z/aLgIDsveW/LiHqG5a8N98XdPivlRgfsBPo5+/wv84gcnAGzL
|
||||
vJURI/GMEuFj+Bg6Vw0fiiYF4DAVKSdSb830bW4flFTwXBHOL8SiUbEDBX1W5nj1
|
||||
KbnIhnXdy/rGbjsVUlpnDIyL+IdTyRwLyxYpjvHqpdb0RjALCw+b6uzQ6feOUb2/
|
||||
RsDIy5cRGY4k2sSP+yFByvNR34HphA==
|
||||
=uPTk
|
||||
-----END PGP SIGNATURE-----
|
60
README.md
60
README.md
@ -1,51 +1,3 @@
|
||||
# ATTENTION! WARNING! ETCETERA!!!
|
||||
|
||||
AS OF 11TH JULY 2022, ALL SUPPORT AND MAINTENANCE ON THIS REPOSITORY HAS BEEN DROPPED.
|
||||
|
||||
Microsoft finally turned off whatever mechanism PolyMC was using to let people play multiplayer on Mojang accounts.
|
||||
|
||||
Use UltimMC. Use something like https://modrinth.com/mod/easyauth . Host your servers this way.
|
||||
|
||||
Microsoft have proven they are willing to remove a bought product off your hands if you don't agree to their new rules about it.
|
||||
|
||||
They have proven that "buying" something off of them means nothing and anything you've "bought" from Mojang means nothing.
|
||||
|
||||
*They have stolen what they have been paid money for. Therefore they don't deserve to have anything bought off them at all.*
|
||||
|
||||
And before any of you go "just migrate", look at the warning signs as to the ban systems.
|
||||
|
||||
Maybe watch FitMC's video: https://www.youtube.com/watch?v=rdoFUhd0EkI
|
||||
|
||||
Or maybe read the migration horror stories:
|
||||
|
||||
+ https://www.reddit.com/r/xbox/comments/sscoa7/does_anyone_have_an_idea_why_was_i_locked_out_of/
|
||||
+ https://news.ycombinator.com/item?id=31551846
|
||||
+ https://answers.microsoft.com/en-us/xbox/forum/all/im-locked-out-of-minecraft-after-migrating-my/9f1f64cb-6a2d-4cd2-abb8-0010a6bc6f31
|
||||
+ https://www.reddit.com/r/Minecraft/comments/we8asn/why_microsoft_ever_since_i_was_forced_to_migrate/
|
||||
+ even rekrap1 got bitten by this: https://www.youtube.com/watch?v=rzPYH98TTMM
|
||||
|
||||
.
|
||||
|
||||
.
|
||||
|
||||
.
|
||||
|
||||
.
|
||||
|
||||
.
|
||||
|
||||
.
|
||||
|
||||
.
|
||||
|
||||
.
|
||||
|
||||
.
|
||||
|
||||
.
|
||||
|
||||
. OLD README BELOW
|
||||
|
||||
# KittenOS NEO
|
||||
|
||||
As per usual, no warranty, not my responsibility if this breaks, or if you somehow try to run it on an actual (non-OpenComputers) computer.
|
||||
@ -84,16 +36,12 @@ It would be really nice if, if I have screwed up, that you tell me how.
|
||||
Preferably with a solution that fits the technological constraints.
|
||||
|
||||
Licensing in this project is rather fluid,
|
||||
but everything that is not in `repository/` is unconditionally under the following license:
|
||||
but everything in code/ is unconditionally under the following license:
|
||||
|
||||
Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
This is released into the public domain.
|
||||
No warranty is provided, implied or otherwise.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
|
||||
This will be referred to as "BSD0".
|
||||
This will be referred to as "Public Domain".
|
||||
|
||||
It should be considered equivalent to CC0, and this is the intent,
|
||||
but it is smaller, which is somewhat important when optimizing for size.
|
||||
|
87
bonecrunch.lua
Normal file
87
bonecrunch.lua
Normal file
@ -0,0 +1,87 @@
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- This program tries to crunch down the installer a bit further.
|
||||
-- Specific target in mind, it has no support for string escapes.
|
||||
-- It also does this:
|
||||
for i = 1, 3 do
|
||||
print(io.read())
|
||||
end
|
||||
|
||||
local sequences = {
|
||||
{"\n", " "},
|
||||
{" ", " "},
|
||||
{" #", "#"},
|
||||
{"# ", "#"},
|
||||
{" ,", ","},
|
||||
{", ", ","},
|
||||
{" (", "("},
|
||||
{"( ", "("},
|
||||
{" )", ")"},
|
||||
{") ", ")"},
|
||||
{" <", "<"},
|
||||
{"< ", "<"},
|
||||
{" >", ">"},
|
||||
{"> ", ">"},
|
||||
{" *", "*"},
|
||||
{"* ", "*"},
|
||||
{" ~", "~"},
|
||||
{"~ ", "~"},
|
||||
{" /", "/"},
|
||||
{"/ ", "/"},
|
||||
{" %", "%"},
|
||||
{"% ", "%"},
|
||||
{" =", "="},
|
||||
{"= ", "="},
|
||||
{" -", "-"},
|
||||
{"- ", "-"},
|
||||
{" +", "+"},
|
||||
{"+ ", "+"},
|
||||
{".. ", ".."},
|
||||
{" ..", ".."},
|
||||
{"\"\" ", "\"\""},
|
||||
{"=0 t", "=0t"},
|
||||
{">0 t", ">0t"},
|
||||
{">1 t", ">1t"},
|
||||
{"=1 w", "=1w"},
|
||||
{"=380 l", "=380l"},
|
||||
{"=127 t", "=127t"},
|
||||
{"=128 t", "=128t"},
|
||||
{">255 t", ">255t"},
|
||||
{"=512 t", "=512t"}
|
||||
}
|
||||
|
||||
local function pass(buffer)
|
||||
local ob = ""
|
||||
local smode = false
|
||||
while #buffer > 0 do
|
||||
if not smode then
|
||||
local ds = true
|
||||
while ds do
|
||||
ds = false
|
||||
for _, v in ipairs(sequences) do
|
||||
if buffer:sub(1, #(v[1])) == v[1] then
|
||||
buffer = v[2] .. buffer:sub(#(v[1]) + 1)
|
||||
ds = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local ch = buffer:sub(1, 1)
|
||||
buffer = buffer:sub(2)
|
||||
ob = ob .. ch
|
||||
if ch == "\"" then
|
||||
smode = not smode
|
||||
end
|
||||
end
|
||||
return ob
|
||||
end
|
||||
local op = io.read("*a")
|
||||
while true do
|
||||
local np = pass(op)
|
||||
if np == op then
|
||||
io.write(np)
|
||||
return
|
||||
end
|
||||
op = np
|
||||
end
|
@ -1,75 +0,0 @@
|
||||
# Claw2 Formats
|
||||
|
||||
## .c2l format
|
||||
|
||||
The .c2l format is the server package list for Claw2.
|
||||
|
||||
In an exception to the rule, this file only exists on the server.
|
||||
|
||||
It is used solely in the main package list panel.
|
||||
|
||||
It is a file made up of lines.
|
||||
|
||||
Each line contains a package name, followed by a dot, followed by the package version.
|
||||
|
||||
## .V.c2p format
|
||||
|
||||
The .V.c2p (where V is the version) format is the entire contents of the package view panel,
|
||||
as text, with newlines, in UTF-8.
|
||||
|
||||
This is used when a package is selected in Claw2.
|
||||
|
||||
## .c2x format
|
||||
|
||||
The .c2x format is the actual installation script for the package.
|
||||
|
||||
It is executed by svc-claw-worker.
|
||||
|
||||
It's loaded in all-at-once, then it's gmatched
|
||||
with the pattern [^\n]+.
|
||||
|
||||
A line starting with "?" represents a dependency.
|
||||
|
||||
A line starting & ending with "/" represents a directory creation.
|
||||
|
||||
And a line starting with "+" represents a file.
|
||||
|
||||
Package metadata is not implied.
|
||||
|
||||
Thus, a valid .c2x is:
|
||||
|
||||
```
|
||||
?neo
|
||||
/apps/
|
||||
+apps/app-carrot.0.c2p
|
||||
+apps/app-carrot.c2x
|
||||
```
|
||||
|
||||
## Claw2 Architecture
|
||||
|
||||
app-claw is a very dumb client, but the only thing that'll bother
|
||||
to parse a .c2l (because it has package list/search),
|
||||
and the only thing that cares about version numbers.
|
||||
|
||||
The purpose of it is to provide an older-CLAW-style GUI.
|
||||
|
||||
It *may* take an argument, in which case a package panel is opened,
|
||||
otherwise the main search panel is opened.
|
||||
|
||||
When it wants to do anything, it shuts itself down, running svc-claw-worker.
|
||||
|
||||
svc-app-claw-worker does all package consistency & such work.
|
||||
|
||||
It can only be run from app-claw, and runs app-claw after it's done.
|
||||
|
||||
It takes 5 arguments:
|
||||
|
||||
1. The target filesystem proxy.
|
||||
2. The target package name. This package is viewed in app-claw after completion.
|
||||
3. The source to download files from.
|
||||
If nil, the package is being deleted.
|
||||
Otherwise, can either be a proxy or a string.
|
||||
Proxy means it's a filesystem,
|
||||
string means it's an internet base.
|
||||
4. Checked flag
|
||||
5. primary inet card proxy, if any
|
@ -1,38 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- CLAW local.lua converter. Expects to be run from outermost folder.
|
||||
|
||||
local target = ...
|
||||
|
||||
local serial = loadfile("code/libs/serial.lua")()
|
||||
|
||||
for k, v in pairs(serial.deserialize(io.read("*a"))) do
|
||||
print(k .. "." .. v.v .. ".c2p")
|
||||
print(k .. ".c2x")
|
||||
local f2 = io.open(target .. k .. "." .. v.v .. ".c2p", "wb")
|
||||
f2:write(k .. "\n")
|
||||
f2:write(v.desc .. "\n")
|
||||
f2:write("v" .. v.v .. " deps " .. table.concat(v.deps, ", "))
|
||||
f2:close()
|
||||
f2 = io.open(target .. k .. ".c2x", "wb")
|
||||
for _, vx in ipairs(v.deps) do
|
||||
f2:write("?" .. vx .. "\n")
|
||||
end
|
||||
for _, vx in ipairs(v.dirs) do
|
||||
f2:write("/" .. vx .. "\n")
|
||||
end
|
||||
for _, vx in ipairs(v.files) do
|
||||
f2:write("+" .. vx .. "\n")
|
||||
end
|
||||
f2:write("/data\n")
|
||||
f2:write("/data/app-claw\n")
|
||||
f2:write("+data/app-claw/" .. k .. ".c2x\n")
|
||||
f2:write("+data/app-claw/" .. k .. "." .. v.v .. ".c2p\n")
|
||||
f2:close()
|
||||
end
|
||||
|
@ -1,328 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- local.lua : CLAW Repository Metadata
|
||||
-- Authors: 20kdc
|
||||
|
||||
return {
|
||||
["app-eeprog"] = {
|
||||
desc = "Example program: EEPROM programmer / copier",
|
||||
v = 1,
|
||||
deps = {
|
||||
"neo",
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/app-eeprog.lua",
|
||||
"docs/repoauthors/app-eeprog"
|
||||
},
|
||||
},
|
||||
["neo-docs"] = {
|
||||
desc = "KittenOS NEO system documentation",
|
||||
v = 10,
|
||||
deps = {
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"docs/an-intro",
|
||||
"docs/kn-intro",
|
||||
"docs/kn-refer",
|
||||
"docs/kn-sched",
|
||||
"docs/kn-perms",
|
||||
"docs/us-perms",
|
||||
"docs/us-nxapp",
|
||||
"docs/us-setti",
|
||||
"docs/us-evrst",
|
||||
"docs/us-clawf",
|
||||
"docs/us-termi",
|
||||
"docs/ul-seria",
|
||||
"docs/ul-fwrap",
|
||||
"docs/ul-event",
|
||||
"docs/ul-fmttx",
|
||||
"docs/ul-neoux",
|
||||
"docs/ul-brail",
|
||||
"docs/ul-bmp__",
|
||||
"docs/ul-linee",
|
||||
"docs/gp-pedan",
|
||||
"docs/repoauthors/neo-docs"
|
||||
},
|
||||
},
|
||||
["app-nbox2018"] = {
|
||||
desc = "NBOX2018 and NPRT2018, a 3D-printing toolbox",
|
||||
v = 1,
|
||||
deps = {
|
||||
"neo",
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/app-nbox2018.lua",
|
||||
"apps/app-nprt2018.lua",
|
||||
"docs/repoauthors/app-nbox2018"
|
||||
},
|
||||
},
|
||||
["app-allmem"] = {
|
||||
desc = "Near-reproducible memory usage figures",
|
||||
v = 1,
|
||||
deps = {
|
||||
"neo",
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/app-allmem.lua",
|
||||
"docs/repoauthors/app-allmem"
|
||||
},
|
||||
},
|
||||
["app-telnet"] = {
|
||||
desc = "TELNET client",
|
||||
v = 1,
|
||||
deps = {
|
||||
"neo",
|
||||
"svc-t",
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/app-telnet.lua",
|
||||
"docs/repoauthors/app-telnet"
|
||||
},
|
||||
},
|
||||
["svc-ghostie"] = {
|
||||
desc = "Application that schedules a scare after a random time to test svc autostart",
|
||||
v = 1,
|
||||
deps = {
|
||||
"neo",
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/svc-ghostie.lua",
|
||||
"apps/app-ghostcall.lua",
|
||||
"docs/repoauthors/svc-ghostie"
|
||||
},
|
||||
},
|
||||
["app-metamachine"] = {
|
||||
desc = "Virtual machine",
|
||||
v = 5,
|
||||
deps = {
|
||||
"neo",
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"libs",
|
||||
"docs",
|
||||
"docs/repoauthors",
|
||||
"data",
|
||||
"data/app-metamachine"
|
||||
},
|
||||
files = {
|
||||
"apps/app-metamachine.lua",
|
||||
"libs/metamachine-vgpu.lua",
|
||||
"libs/metamachine-vfs.lua",
|
||||
"docs/repoauthors/app-metamachine",
|
||||
"data/app-metamachine/confboot.lua",
|
||||
"data/app-metamachine/lucaboot.lua"
|
||||
},
|
||||
},
|
||||
["app-pclogix-upload"] = {
|
||||
desc = "paste.pc-logix.com text uploader",
|
||||
v = 1,
|
||||
deps = {
|
||||
"neo",
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/app-pclogix-upload.lua",
|
||||
"docs/repoauthors/app-pclogix-upload"
|
||||
},
|
||||
},
|
||||
["app-rsctrl"] = {
|
||||
desc = "Redstone control",
|
||||
v = 1,
|
||||
deps = {
|
||||
"neo",
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/app-rsctrl.lua",
|
||||
"docs/repoauthors/app-rsctrl"
|
||||
},
|
||||
},
|
||||
["app-nbcompose"] = {
|
||||
desc = "Music player/composer using the NBS format",
|
||||
v = 2,
|
||||
deps = {
|
||||
"neo",
|
||||
"lib-knbs",
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/app-nbcompose.lua",
|
||||
"docs/repoauthors/app-nbcompose"
|
||||
},
|
||||
},
|
||||
["app-tapedeck"] = {
|
||||
desc = "Computronics Tape Drive interface",
|
||||
v = 3,
|
||||
deps = {
|
||||
"neo",
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/app-tapedeck.lua",
|
||||
"docs/repoauthors/app-tapedeck"
|
||||
},
|
||||
},
|
||||
["app-launchbar"] = {
|
||||
desc = "Application launcher bar",
|
||||
v = 0,
|
||||
deps = {
|
||||
"neo",
|
||||
"zzz-license-pd"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/app-launchbar.lua",
|
||||
"docs/repoauthors/app-launchbar"
|
||||
},
|
||||
},
|
||||
["app-slaunch"] = {
|
||||
desc = "Searching launcher",
|
||||
v = 0,
|
||||
deps = {
|
||||
"neo",
|
||||
"zzz-license-pd"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/app-slaunch.lua",
|
||||
"docs/repoauthors/app-slaunch"
|
||||
},
|
||||
},
|
||||
-- libraries
|
||||
["lib-knbs"] = {
|
||||
desc = "NBS reader/writer library",
|
||||
v = 2,
|
||||
deps = {
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"libs",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"libs/knbs.lua",
|
||||
"docs/repoauthors/lib-knbs"
|
||||
},
|
||||
},
|
||||
["svc-virtudev"] = {
|
||||
desc = "a clone of vcomponent",
|
||||
v = 2,
|
||||
deps = {
|
||||
"neo",
|
||||
"zzz-license-kosneo-bsd0"
|
||||
},
|
||||
dirs = {
|
||||
"apps",
|
||||
"docs",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"apps/svc-virtudev.lua",
|
||||
"apps/app-vdrslamp.lua",
|
||||
"docs/us-virtu",
|
||||
"docs/repoauthors/svc-virtudev"
|
||||
},
|
||||
},
|
||||
-- licenses (MUST BE IMMUTABLE)
|
||||
["zzz-license-pd"] = {
|
||||
desc = "license file 'Public Domain'",
|
||||
v = 0,
|
||||
deps = {
|
||||
},
|
||||
dirs = {
|
||||
"docs",
|
||||
"docs/licensing",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"docs/licensing/Public Domain",
|
||||
"docs/repoauthors/zzz-license-pd"
|
||||
},
|
||||
},
|
||||
["zzz-license-kosneo-bsd0"] = {
|
||||
desc = "license file 'KittenOS NEO BSD0'",
|
||||
v = 0,
|
||||
deps = {
|
||||
},
|
||||
dirs = {
|
||||
"docs",
|
||||
"docs/licensing",
|
||||
"docs/repoauthors"
|
||||
},
|
||||
files = {
|
||||
"docs/licensing/KittenOS NEO BSD0",
|
||||
"docs/repoauthors/zzz-license-kosneo-bsd0"
|
||||
},
|
||||
}
|
||||
}
|
17
clawmerge.lua
Normal file
17
clawmerge.lua
Normal file
@ -0,0 +1,17 @@
|
||||
local merges = {...}
|
||||
neo = {
|
||||
wrapMeta = function (x)
|
||||
return x
|
||||
end
|
||||
}
|
||||
local serial = loadfile("code/libs/serial.lua")()
|
||||
local repo = {}
|
||||
for _, v in ipairs(merges) do
|
||||
local f = io.open(v, "rb")
|
||||
local fd = f:read("*a")
|
||||
f:close()
|
||||
for k, v in pairs(serial.deserialize(fd)) do
|
||||
repo[k] = v
|
||||
end
|
||||
end
|
||||
io.write(serial.serialize(repo))
|
@ -1,78 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- app-batmon: Still not batman.
|
||||
-- Port of the original 'batmon.lua' from KittenOS Legacy.
|
||||
local window = neo.requireAccess("x.neo.pub.window", "window")(10, 2)
|
||||
|
||||
-- OCE/s, OCE at last check, uptime of last timer set, uptime of last check
|
||||
local lastChange, lastValue, lastTimer, lpTimer = 0
|
||||
local usage = {
|
||||
"[####]:",
|
||||
"[###:]:",
|
||||
"[### ]:",
|
||||
"[##: ]:",
|
||||
"[## ]:",
|
||||
"[#: ]:",
|
||||
"[# ]:",
|
||||
"[: ]:",
|
||||
"[ ]:",
|
||||
"WARNING"
|
||||
}
|
||||
local function getText(y)
|
||||
if y == 2 then
|
||||
if not lastChange then
|
||||
return "Wait..."
|
||||
end
|
||||
local ind = "Dc. "
|
||||
local wc = lastChange
|
||||
local wv = os.energy()
|
||||
if wc > 0 then
|
||||
wc = -wc
|
||||
wv = os.maxEnergy() - wv
|
||||
ind = "Ch. "
|
||||
end
|
||||
local m = math.floor((wv / -wc) / 60)
|
||||
return ind .. m .. "m"
|
||||
end
|
||||
local dec = os.energy() / os.maxEnergy()
|
||||
-- dec is from 0 to 1.
|
||||
local potential = math.floor(dec * #usage)
|
||||
if potential < 0 then potential = 1 end
|
||||
if potential >= #usage then potential = #usage - 1 end
|
||||
return usage[#usage - potential]
|
||||
end
|
||||
local function update()
|
||||
local nv = os.energy()
|
||||
if lastValue then
|
||||
lastChange = (nv - lastValue) / (os.uptime() - lpTimer)
|
||||
end
|
||||
lpTimer = os.uptime()
|
||||
lastValue = nv
|
||||
lastTimer = os.uptime() + 10
|
||||
if lastChange then
|
||||
if lastChange > 10 then
|
||||
lastTimer = lastTimer - 9
|
||||
end
|
||||
end
|
||||
neo.scheduleTimer(lastTimer)
|
||||
window.setSize(10, 2)
|
||||
end
|
||||
update()
|
||||
while true do
|
||||
local ev, a, b, c = coroutine.yield()
|
||||
if ev == "x.neo.pub.window" then
|
||||
if b == "close" then
|
||||
return
|
||||
elseif b == "line" then
|
||||
local tx = getText(c):sub(1, 10)
|
||||
window.span(1, c, tx .. (" "):rep(10 - #tx), 0xFFFFFF, 0)
|
||||
end
|
||||
elseif ev == "k.timer" then
|
||||
update()
|
||||
end
|
||||
end
|
@ -1,84 +1,148 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- app-claw: Package manager.
|
||||
|
||||
local ldrPkg, _, tgtPkg = ...
|
||||
|
||||
-- libs & such
|
||||
local event = require("event")(neo)
|
||||
local neoux = require("neoux")(event, neo)
|
||||
local neoux, err = require("neoux")
|
||||
if not neoux then error(err) end
|
||||
neoux = neoux(event, neo)
|
||||
local claw = require("app-claw-core")()
|
||||
local clawcsi = require("app-claw-csi")
|
||||
|
||||
local source = "http://20kdc.duckdns.org/neo/"
|
||||
local disks = neo.requireAccess("c.filesystem", "searching disks for packages")
|
||||
local primaryDisk = disks.primary
|
||||
local primaryINet = neo.requestAccess("c.internet")
|
||||
if primaryINet then primaryINet = primaryINet.list()() end
|
||||
|
||||
--
|
||||
|
||||
local function readFile(src, url, ocb)
|
||||
local buf = ""
|
||||
local function cb(data)
|
||||
if not data then
|
||||
ocb(buf)
|
||||
else
|
||||
buf = buf .. data
|
||||
buf = buf:gsub("[^\n]*\n", function (t)
|
||||
ocb(t:sub(1, -2))
|
||||
return ""
|
||||
end)
|
||||
local function yielder()
|
||||
-- slightly dangerous, but what can we do?
|
||||
pcall(event.sleepTo, os.uptime() + 0.05)
|
||||
end
|
||||
|
||||
local function download(url, cb)
|
||||
if not primaryINet then return nil, "no internet" end
|
||||
local req, err = primaryINet.request(source .. url)
|
||||
if not req then
|
||||
cb(nil)
|
||||
return nil, "dlR/" .. tostring(err)
|
||||
end
|
||||
if type(src) == "string" then
|
||||
assert(primaryINet, "no internet")
|
||||
local req, err = primaryINet.request(src .. url)
|
||||
assert(req, err)
|
||||
-- OpenComputers#535
|
||||
req.finishConnect()
|
||||
while true do
|
||||
local n, n2 = req.read(neo.readBufSize)
|
||||
cb(n)
|
||||
local o, r = cb(n)
|
||||
if not o then
|
||||
req.close()
|
||||
return nil, r
|
||||
end
|
||||
if not n then
|
||||
req.close()
|
||||
if n2 then
|
||||
error(n2)
|
||||
return nil, n2
|
||||
else
|
||||
cb(nil)
|
||||
break
|
||||
end
|
||||
else
|
||||
if n == "" then
|
||||
-- slightly dangerous, but what can we do?
|
||||
pcall(event.sleepTo, os.uptime() + 0.05)
|
||||
yielder()
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function fsSrc(disk)
|
||||
return function (url, cb)
|
||||
local h, e = disk.open(url, "rb")
|
||||
if not h then cb(nil) return nil, tostring(e) end
|
||||
local c = ""
|
||||
while c do
|
||||
c = disk.read(h, neo.readBufSize)
|
||||
local o, r = cb(c)
|
||||
if not o then return nil, r end
|
||||
end
|
||||
disk.close(h)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function fsDst(disk)
|
||||
return {function (url)
|
||||
local h, e = disk.open(url, "wb")
|
||||
if not h then return nil, tostring(e) end
|
||||
return function (d)
|
||||
local ok, r = true
|
||||
if d then
|
||||
ok, r = disk.write(h, d)
|
||||
else
|
||||
if url == "data/app-claw/local.c2l" then
|
||||
for _, v in ipairs(src.list("data/app-claw/")) do
|
||||
ocb(v)
|
||||
disk.close(h)
|
||||
end
|
||||
return
|
||||
if not ok then return nil, tostring(r) end
|
||||
return true
|
||||
end
|
||||
local h, e = src.open(url, "rb")
|
||||
assert(h, e)
|
||||
repeat
|
||||
local c = src.read(h, neo.readBufSize)
|
||||
cb(c)
|
||||
until not c
|
||||
src.close(h)
|
||||
end, disk.makeDirectory, disk.exists, disk.isDirectory, disk.remove, disk.rename}
|
||||
end
|
||||
|
||||
local function checked(...)
|
||||
local res, res2, err = pcall(...)
|
||||
if not res then
|
||||
neoux.startDialog(tostring(res2), "error!", true)
|
||||
elseif not res2 then
|
||||
neoux.startDialog(tostring(err), "failed!", true)
|
||||
else
|
||||
return res2
|
||||
end
|
||||
end
|
||||
|
||||
-- Sources
|
||||
-- Beginning Of The App (well, the actual one)
|
||||
|
||||
local genCurrent, genPrimary, genPackage, primaryWindow
|
||||
local running = true
|
||||
|
||||
-- primary
|
||||
local primarySearchTx = ""
|
||||
local primaryPage = 1
|
||||
local primaryList = {}
|
||||
local primaryNextMinus = false
|
||||
|
||||
-- package
|
||||
local packageLock = nil
|
||||
local packageId = "FIXME"
|
||||
|
||||
|
||||
local function describe(pkg)
|
||||
local weHave = claw.getInfo(pkg, "local")
|
||||
local theyHave = claw.getInfo(pkg, "local")
|
||||
local someoneHas = claw.getInfo(pkg, nil, true)
|
||||
if weHave then
|
||||
if theyHave.v > weHave.v then
|
||||
return pkg .. " [v" .. weHave.v .. "!]"
|
||||
end
|
||||
if someoneHas.v < weHave.v then
|
||||
return pkg .. " (v" .. weHave.v .. ") R<"
|
||||
end
|
||||
return pkg .. " (v" .. weHave.v .. ")"
|
||||
end
|
||||
return pkg
|
||||
end
|
||||
|
||||
local function primaryWindowRegenCore()
|
||||
local gen, gens = genCurrent()
|
||||
return 25, 12, "claw", neoux.tcwindow(25, 12, gen, function (w)
|
||||
w.close()
|
||||
running = false
|
||||
end, 0xFF8F00, 0, gens)
|
||||
end
|
||||
local function primaryWindowRegen()
|
||||
primaryWindow.reset(primaryWindowRegenCore())
|
||||
end
|
||||
|
||||
local sources = {}
|
||||
local sourceList = {}
|
||||
-- Use all non-primary filesystems
|
||||
local disks = neo.requireAccess("c.filesystem", "searching disks for packages")
|
||||
local primaryDisk = disks.primary
|
||||
for pass = 1, 3 do
|
||||
for v in disks.list() do
|
||||
local nam = nil
|
||||
@ -90,8 +154,11 @@ for pass = 1, 3 do
|
||||
nam = v.address
|
||||
end
|
||||
if nam then
|
||||
sources[nam] = v
|
||||
table.insert(sourceList, nam)
|
||||
local ok, r = clawcsi(claw, nam, fsSrc(v), (not v.isReadOnly()) and fsDst(v))
|
||||
if not ok and nam == "local" then
|
||||
claw.unlock()
|
||||
error(r)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -100,105 +167,19 @@ end
|
||||
disks = nil
|
||||
|
||||
if primaryINet then
|
||||
sources["inet"] = "http://20kdc.duckdns.org/neo/"
|
||||
table.insert(sourceList, "inet")
|
||||
checked(clawcsi, claw, "inet", download)
|
||||
end
|
||||
|
||||
-- List scanning for package window
|
||||
clawcsi = nil
|
||||
|
||||
local function scanList(content)
|
||||
local lst = {}
|
||||
local lst2 = {}
|
||||
for k, v in pairs(sources) do
|
||||
local ok, err = pcall(readFile, v, "data/app-claw/local.c2l", function (l)
|
||||
if l:sub(-4) == ".c2p" then
|
||||
local lt, ltv = l:sub(1, -5)
|
||||
ltv = lt:match("%.[0-9]+$")
|
||||
if ltv and l:find(content, 1, true) then
|
||||
lt = lt:sub(1, -(#ltv + 1))
|
||||
lst2[lt] = true
|
||||
end
|
||||
end
|
||||
end)
|
||||
if (not ok) and ((k == "inet") or (k == "local")) then
|
||||
neoux.startDialog(tostring(err), k)
|
||||
end
|
||||
end
|
||||
for k, v in pairs(lst2) do
|
||||
table.insert(lst, k)
|
||||
end
|
||||
table.sort(lst)
|
||||
return lst
|
||||
end
|
||||
|
||||
-- Beginning Of The App (well, the actual one)
|
||||
|
||||
local genCurrent, genPrimary, genPackage, primaryWindow
|
||||
local running = true
|
||||
|
||||
-- primary
|
||||
local primarySearchTx = ""
|
||||
local primaryPage = 1
|
||||
local primaryList = scanList("")
|
||||
local primaryNextMinus = false
|
||||
|
||||
-- package
|
||||
local packageLock = nil
|
||||
local packageId = "FIXME"
|
||||
|
||||
local function describe(pkgs)
|
||||
local lowestV, highestV, myV = {}, {}, {}
|
||||
for pk, pv in ipairs(pkgs) do
|
||||
lowestV[pk] = math.huge
|
||||
highestV[pk] = -math.huge
|
||||
end
|
||||
for k, v in pairs(sources) do
|
||||
pcall(readFile, v, "data/app-claw/local.c2l", function (l)
|
||||
local lp = l:match("%.[0-9]+%.c2p$")
|
||||
for pk, pkg in ipairs(pkgs) do
|
||||
if lp and l:sub(1, -(#lp + 1)) == pkg then
|
||||
local v = tonumber(lp:sub(2, -5))
|
||||
if k == "local" then
|
||||
myV[pk] = v
|
||||
end
|
||||
lowestV[pk] = math.min(lowestV[pk], v)
|
||||
highestV[pk] = math.max(highestV[pk], v)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
for pk, pkg in ipairs(pkgs) do
|
||||
if lowestV[pk] == math.huge then
|
||||
pkgs[pk] = pkg .. " (ERR)"
|
||||
elseif myV[pk] then
|
||||
if highestV[pk] > myV[pk] then
|
||||
pkgs[pk] = pkg .. " [v" .. myV[pk] .. "!]"
|
||||
elseif lowestV[pk] < myV[pk] then
|
||||
pkgs[pk] = pkg .. " (v" .. myV[pk] .. ") R<"
|
||||
else
|
||||
pkgs[pk] = pkg .. " (v" .. myV[pk] .. ")"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function primaryWindowRegenCore()
|
||||
local gen, gens = genCurrent()
|
||||
return 25, 14, "claw", neoux.tcwindow(25, 14, gen, function (w)
|
||||
w.close()
|
||||
running = false
|
||||
end, 0xFF8F00, 0, gens)
|
||||
end
|
||||
local function primaryWindowRegen()
|
||||
primaryWindow.reset(primaryWindowRegenCore())
|
||||
end
|
||||
primaryList = claw.getList()
|
||||
|
||||
-- Sections
|
||||
|
||||
function genPrimary()
|
||||
local minus = (primaryNextMinus and 3) or nil
|
||||
primaryNextMinus = false
|
||||
local pgs = 12
|
||||
local pgs = 10
|
||||
local pages = math.ceil(#primaryList / pgs)
|
||||
local elems = {
|
||||
neoux.tcbutton(23, 1, "+", function (w)
|
||||
@ -217,22 +198,14 @@ function genPrimary()
|
||||
end)
|
||||
}
|
||||
local base = (primaryPage - 1) * pgs
|
||||
local pkgs = {}
|
||||
for i = 1, pgs do
|
||||
local ent = primaryList[base + i]
|
||||
if ent then
|
||||
pkgs[i] = ent
|
||||
end
|
||||
end
|
||||
describe(pkgs)
|
||||
for i = 1, pgs do
|
||||
local ent = primaryList[base + i]
|
||||
if ent then
|
||||
local enttx = pkgs[i]
|
||||
local enttx = describe(ent)
|
||||
table.insert(elems, neoux.tcbutton(1, i + 1, unicode.safeTextFormat(enttx), function (w)
|
||||
-- FREE UP MEMORY NOW
|
||||
elems = {}
|
||||
w.reset(25, 14, "claw", function (ev)
|
||||
w.reset(25, 12, "claw", function (ev)
|
||||
if ev == "close" then
|
||||
w.close()
|
||||
running = false
|
||||
@ -244,13 +217,22 @@ function genPrimary()
|
||||
end))
|
||||
end
|
||||
end
|
||||
table.insert(elems, neoux.tcfield(1, 14, 16, function (s)
|
||||
table.insert(elems, neoux.tcfield(1, 12, 16, function (s)
|
||||
if s then primarySearchTx = s end
|
||||
return primarySearchTx
|
||||
end))
|
||||
table.insert(elems, neoux.tcbutton(17, 14, "Search!", function (w)
|
||||
table.insert(elems, neoux.tcbutton(17, 12, "Search!", function (w)
|
||||
local n = {}
|
||||
for _, v in ipairs(claw.getList()) do
|
||||
for i = 1, #v do
|
||||
if v:sub(i, i + #primarySearchTx - 1) == primarySearchTx then
|
||||
table.insert(n, v)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
primaryPage = 1
|
||||
primaryList = scanList(primarySearchTx)
|
||||
primaryList = n
|
||||
primaryWindowRegen()
|
||||
end))
|
||||
return elems, minus
|
||||
@ -263,38 +245,49 @@ local function packageGetBB(src, lclI, srcI, srcW)
|
||||
if srcI and srcW then
|
||||
table.insert(buttons, {
|
||||
"Del",
|
||||
function (w)
|
||||
w.close()
|
||||
running = false
|
||||
neo.executeAsync("svc-app-claw-worker", sources[src], packageId, nil, src == "local", primaryINet)
|
||||
function ()
|
||||
if packageLock then return end
|
||||
packageLock = ""
|
||||
checked(claw.remove, src, packageId, true)
|
||||
packageLock = nil
|
||||
primaryWindowRegen()
|
||||
end
|
||||
})
|
||||
end
|
||||
if srcI and ((not lclI) or (lclI < srcI)) then
|
||||
if srcI and ((not lclI) or (lclI.v < srcI.v)) then
|
||||
table.insert(buttons, {
|
||||
"Get",
|
||||
function (w)
|
||||
w.close()
|
||||
running = false
|
||||
neo.executeAsync("svc-app-claw-worker", sources["local"], packageId, sources[src], true, primaryINet)
|
||||
function ()
|
||||
if packageLock then return end
|
||||
packageLock = "installing from " .. src
|
||||
primaryWindowRegen()
|
||||
checked(claw.installTo, "local", packageId, src, true, yielder)
|
||||
packageLock = nil
|
||||
primaryWindowRegen()
|
||||
end
|
||||
})
|
||||
end
|
||||
if srcW and lclI and not srcI then
|
||||
table.insert(buttons, {
|
||||
"All",
|
||||
function (w)
|
||||
w.close()
|
||||
running = false
|
||||
neo.executeAsync("svc-app-claw-worker", sources[src], packageId, sources["local"], true, primaryINet)
|
||||
function ()
|
||||
if packageLock then return end
|
||||
packageLock = "storing w/ dependencies at " .. src
|
||||
primaryWindowRegen()
|
||||
checked(claw.installTo, src, packageId, "local", true, yielder)
|
||||
packageLock = nil
|
||||
primaryWindowRegen()
|
||||
end
|
||||
})
|
||||
table.insert(buttons, {
|
||||
"Put",
|
||||
function (w)
|
||||
w.close()
|
||||
running = false
|
||||
neo.executeAsync("svc-app-claw-worker", sources[src], packageId, sources["local"], false, primaryINet)
|
||||
function ()
|
||||
if packageLock then return end
|
||||
packageLock = "storing at " .. src
|
||||
primaryWindowRegen()
|
||||
checked(claw.installTo, src, packageId, "local", false, yielder)
|
||||
packageLock = nil
|
||||
primaryWindowRegen()
|
||||
end
|
||||
})
|
||||
end
|
||||
@ -313,50 +306,26 @@ function genPackage()
|
||||
-- inet v21 <pull>
|
||||
-- dir v22 <pull> <push>
|
||||
-- crockett <push>
|
||||
local sourceVers = {}
|
||||
local c2pSrc = "local"
|
||||
local c2pVer = -1
|
||||
for k, v in pairs(sources) do
|
||||
local ok, err = pcall(readFile, v, "data/app-claw/local.c2l", function (l)
|
||||
local lp = l:match("%.[0-9]+%.c2p$")
|
||||
if lp and l:sub(1, -(#lp + 1)) == packageId then
|
||||
sourceVers[k] = tonumber(lp:sub(2, -5))
|
||||
if c2pVer < sourceVers[k] then
|
||||
c2pSrc = k
|
||||
c2pVer = sourceVers[k]
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
if sourceVers["local"] then
|
||||
c2pSrc = "local"
|
||||
c2pVer = sourceVers["local"]
|
||||
end
|
||||
local text = ""
|
||||
local ok = pcall(readFile, sources[c2pSrc], "data/app-claw/" .. packageId .. "." .. c2pVer .. ".c2p", function (l)
|
||||
text = text .. l .. "\n"
|
||||
end)
|
||||
if not ok then
|
||||
text = packageId .. "\nUnable to read v" .. c2pVer .. " c2p from: " .. c2pSrc
|
||||
end
|
||||
local info = claw.getInfo(packageId)
|
||||
local infoL = claw.getInfo(packageId, "local")
|
||||
local elems = {
|
||||
neoux.tcrawview(1, 1, neoux.fmtText(unicode.safeTextFormat(text), 25)),
|
||||
neoux.tcrawview(1, 1, neoux.fmtText(unicode.safeTextFormat(packageId .. "\n" .. info.desc .. "\nv" .. info.v .. " deps " .. table.concat(info.deps, ", ")), 25)),
|
||||
neoux.tcbutton(20, 1, "Back", function ()
|
||||
if packageLock then return end
|
||||
genCurrent = genPrimary
|
||||
primaryWindowRegen()
|
||||
end)
|
||||
}
|
||||
for k, v in ipairs(sourceList) do
|
||||
local row = 14 + k - #sourceList
|
||||
for k, v in ipairs(claw.sourceList) do
|
||||
local lI = claw.getInfo(packageId, v[1])
|
||||
local row = 12 + k - #(claw.sourceList)
|
||||
local pfx = " "
|
||||
if sourceVers[v] then
|
||||
pfx = "v" .. string.format("%04i", sourceVers[v]) .. " "
|
||||
if lI then
|
||||
pfx = "v" .. string.format("%04i", lI.v) .. " "
|
||||
end
|
||||
table.insert(elems, neoux.tcrawview(1, row, {neoux.pad(pfx .. v, 14, false, true)}))
|
||||
table.insert(elems, neoux.tcrawview(1, row, {neoux.pad(pfx .. v[1], 14, false, true)}))
|
||||
local col = 26
|
||||
local srcW = type(sources[v]) ~= "string"
|
||||
for _, bv in ipairs(packageGetBB(v, sourceVers["local"], sourceVers[v], srcW)) do
|
||||
for _, bv in ipairs(packageGetBB(v[1], infoL, lI, v[2])) do
|
||||
local b = neoux.tcbutton(col, row, bv[1], bv[2])
|
||||
col = col - b.w
|
||||
b.x = col
|
||||
@ -368,14 +337,10 @@ end
|
||||
|
||||
--
|
||||
|
||||
if ldrPkg == "svc-app-claw-worker" and tgtPkg then
|
||||
packageId = tgtPkg
|
||||
genCurrent = genPackage
|
||||
else
|
||||
genCurrent = genPrimary
|
||||
end
|
||||
primaryWindow = neoux.create(primaryWindowRegenCore())
|
||||
|
||||
while running do
|
||||
event.pull()
|
||||
end
|
||||
claw.unlock()
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- app-control: Settings changer
|
||||
local settings = neo.requireAccess("x.neo.sys.manage", "management")
|
||||
@ -230,7 +226,7 @@ window = neoux.create(currentGen())
|
||||
while running do
|
||||
local src, id, k, v = event.pull()
|
||||
if src == "x.neo.sys.manage" then
|
||||
if id == "set_setting" and currentGen ~= logGen then
|
||||
if id == "set_setting" then
|
||||
window.reset(currentGen())
|
||||
end
|
||||
end
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- 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)
|
||||
@ -24,14 +20,12 @@ local busy = false
|
||||
local regenCore
|
||||
|
||||
local function regenLabeller(set, get, wd)
|
||||
local tx = get()
|
||||
return wd, 2, nil, neoux.tcwindow(wd, 1, {
|
||||
neoux.tcfield(1, 1, wd, function (nt)
|
||||
if nt then
|
||||
tx = nt
|
||||
set(nt)
|
||||
end
|
||||
return tx
|
||||
return get()
|
||||
end)
|
||||
}, function (w)
|
||||
busy = false
|
||||
@ -45,7 +39,7 @@ function regenCore()
|
||||
for v in eeprom.list() do
|
||||
local lbl = unicode.safeTextFormat(v.getLabel())
|
||||
table.insert(elems, neoux.tcrawview(1, l, {
|
||||
require("fmttext").pad(v.address:sub(1, 8) .. " " .. lbl, 25, false, true)
|
||||
v.address:sub(1, 8) .. " " .. lbl
|
||||
}))
|
||||
table.insert(elems, neoux.tcbutton(1, l + 1, "get", function (window)
|
||||
if busy then return end
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- app-fm: dummy app to start FM
|
||||
neo.requestAccess("x.neo.pub.base").showFileDialogAsync(nil)
|
||||
|
@ -1,15 +1,12 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- 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)
|
||||
local braille = require("braille")
|
||||
local bmp = require("bmp")
|
||||
local file = neoux.fileDialog(false)
|
||||
local icecap = neo.requireAccess("x.neo.pub.base", "loadimg")
|
||||
local file = icecap.open("/logo.bmp", false)
|
||||
|
||||
local header = file.read(bmp.headerMinSzBMP)
|
||||
local palette = ""
|
||||
@ -64,6 +61,9 @@ lcWidth = bitmap.dsSpan
|
||||
local running = true
|
||||
|
||||
local function decodeRGB(rgb, igp, col)
|
||||
if igp and bitmap.bpp > 24 then
|
||||
rgb = math.floor(rgb / 256)
|
||||
end
|
||||
local r, g, b = math.floor(rgb / 65536) % 256, math.floor(rgb / 256) % 256, rgb % 256
|
||||
-- the new KittenOS NEO logo is 'sensitive' to dithering, so disable it
|
||||
if not col then
|
||||
@ -82,8 +82,6 @@ local fp = neoux.tcwindow(bW, bH, {
|
||||
braille.new(1, 1, bW, bH, {
|
||||
selectable = true,
|
||||
get = function (window, x, y, bg, fg, selected, colour)
|
||||
if x > bitmap.width then return 0, 0, 0 end
|
||||
if y > bitmap.height then return 0, 0, 0 end
|
||||
if bitmap.ignoresPalette then
|
||||
return decodeRGB(bitmap.getPixel(x - 1, y - 1, 0), true, colour)
|
||||
end
|
||||
@ -97,9 +95,9 @@ end, 0xFFFFFF, 0)
|
||||
|
||||
neoux.create(bW, bH, nil, function (w, t, r, ...)
|
||||
if t == "focus" then
|
||||
if r and not bitmap.ignoresPalette then
|
||||
if r then
|
||||
local pal = {}
|
||||
for i = 0, math.min(15, bitmap.paletteCol - 1) do
|
||||
for i = 0, 15 do
|
||||
pal[i + 1] = bitmap.getPalette(i)
|
||||
end
|
||||
w.recommendPalette(pal)
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- app-launcher: The launcher
|
||||
local event = require("event")(neo)
|
||||
|
@ -1,168 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
local _, _, termId = ...
|
||||
local ok = pcall(function ()
|
||||
assert(string.sub(termId, 1, 12) == "x.neo.pub.t/")
|
||||
end)
|
||||
|
||||
local termClose
|
||||
|
||||
if not ok then
|
||||
termId = nil
|
||||
assert(neo.executeAsync("svc-t", function (res)
|
||||
termId = res.access
|
||||
termClose = res.close
|
||||
neo.scheduleTimer(0)
|
||||
end, "luashell"))
|
||||
while not termId do
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
TERM = neo.requireAccess(termId, "terminal")
|
||||
|
||||
-- Using event makes it easier for stuff
|
||||
-- within the shell to not spectacularly explode.
|
||||
event = require("event")(neo)
|
||||
|
||||
local alive = true
|
||||
event.listen("k.procdie", function (_, _, pid)
|
||||
if pid == TERM.pid then
|
||||
alive = false
|
||||
end
|
||||
end)
|
||||
|
||||
TERM.write([[
|
||||
KittenOS NEO Shell Usage Notes
|
||||
|
||||
Prefixing = is an alias for 'return '.
|
||||
io.read(): Reads a line.
|
||||
print: 'print with table dumping' impl.
|
||||
TERM: Your terminal. (see us-termi doc.)
|
||||
os.execute(): launch terminal apps!
|
||||
tries '*', 'sys-t-*', 'svc-t-*', 'app-*'
|
||||
example: os.execute("luashell")
|
||||
os.exit(): quit the shell
|
||||
=listCmdApps(): -t- (terminal) apps
|
||||
event: useful for setting up listeners
|
||||
without breaking shell functionality
|
||||
]])
|
||||
|
||||
function listCmdApps()
|
||||
local apps = {}
|
||||
for _, v in ipairs(neo.listApps()) do
|
||||
if v:sub(4, 6) == "-t-" then
|
||||
table.insert(apps, v)
|
||||
end
|
||||
end
|
||||
return apps
|
||||
end
|
||||
|
||||
local function vPrint(slike, ...)
|
||||
local s = {...}
|
||||
if #s > 1 then
|
||||
for i = 1, #s do
|
||||
if i ~= 1 then TERM.write("\t") end
|
||||
vPrint(slike, s[i])
|
||||
end
|
||||
elseif slike and type(s[1]) == "string" then
|
||||
TERM.write("\"" .. s[1] .. "\"")
|
||||
elseif type(s[1]) ~= "table" then
|
||||
TERM.write(tostring(s[1]))
|
||||
else
|
||||
TERM.write("{")
|
||||
for k, v in pairs(s[1]) do
|
||||
TERM.write("[")
|
||||
vPrint(true, k)
|
||||
TERM.write("] = ")
|
||||
vPrint(true, v)
|
||||
TERM.write(", ")
|
||||
end
|
||||
TERM.write("}")
|
||||
end
|
||||
end
|
||||
|
||||
print = function (...)
|
||||
vPrint(false, ...)
|
||||
TERM.write("\r\n")
|
||||
end
|
||||
|
||||
local ioBuffer = ""
|
||||
|
||||
io = {
|
||||
read = function ()
|
||||
while alive do
|
||||
local pos = ioBuffer:find("\n")
|
||||
if pos then
|
||||
local line = ioBuffer:sub(1, pos):gsub("\r", "")
|
||||
ioBuffer = ioBuffer:sub(pos + 1)
|
||||
return line
|
||||
end
|
||||
local e = {event.pull()}
|
||||
if e[1] == TERM.id then
|
||||
if e[2] == "data" then
|
||||
ioBuffer = ioBuffer .. e[3]
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
write = function (s) TERM.write(s) end
|
||||
}
|
||||
|
||||
local originalOS = os
|
||||
os = setmetatable({}, {
|
||||
__index = originalOS
|
||||
})
|
||||
|
||||
function os.exit()
|
||||
alive = false
|
||||
end
|
||||
|
||||
function os.execute(x, ...)
|
||||
local subPid = neo.executeAsync(x, TERM.id, ...)
|
||||
if not subPid then
|
||||
subPid = neo.executeAsync("sys-t-" .. x, TERM.id, ...)
|
||||
end
|
||||
if not subPid then
|
||||
subPid = neo.executeAsync("svc-t-" .. x, TERM.id, ...)
|
||||
end
|
||||
if not subPid then
|
||||
subPid = neo.executeAsync("app-" .. x, TERM.id, ...)
|
||||
end
|
||||
if not subPid then
|
||||
error("cannot find " .. x)
|
||||
end
|
||||
while true do
|
||||
local e = {event.pull()}
|
||||
if e[1] == "k.procdie" then
|
||||
if e[3] == subPid then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
while alive do
|
||||
TERM.write("> ")
|
||||
local code = io.read()
|
||||
if code then
|
||||
local ok, err = pcall(function ()
|
||||
if code:sub(1, 1) == "=" then
|
||||
code = "return " .. code:sub(2)
|
||||
end
|
||||
print(assert(load(code))())
|
||||
end)
|
||||
if not ok then
|
||||
TERM.write(tostring(err) .. "\r\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if termClose then
|
||||
termClose()
|
||||
end
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- app-taskmgr: Task manager
|
||||
-- a-hello : simple test program for Everest.
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- 'neolithic': Text Editor
|
||||
-- This was textedit (femto) from KittenOS 'ported' to NEO.
|
||||
@ -15,7 +11,7 @@ local lines = {
|
||||
"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 adding a visible way to reset the append flag,
|
||||
-- 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
|
||||
"F7: Reset 'append' flag for Cut Lines",
|
||||
"F8: Cut Line(s)",
|
||||
@ -34,17 +30,33 @@ local clipsrc = neo.requireAccess("x.neo.pub.globals", "clipboard")
|
||||
local windows = neo.requireAccess("x.neo.pub.window", "windows")
|
||||
local files = neo.requireAccess("x.neo.pub.base", "files").showFileDialogAsync
|
||||
|
||||
local lineEdit = require("lineedit")
|
||||
|
||||
local cursorX = 1
|
||||
local cursorY = math.ceil(#lines / 2)
|
||||
local ctrlFlag, appendFlag
|
||||
local cFlash = true
|
||||
local ctrlFlag = false
|
||||
local dialogLock = false
|
||||
local appendFlag = false
|
||||
local sW, sH = 37, #lines + 2
|
||||
local window = windows(sW, sH)
|
||||
local filedialog = nil
|
||||
local flush
|
||||
|
||||
local function splitCur()
|
||||
local s = lines[cursorY]
|
||||
local st = unicode.sub(s, 1, cursorX - 1)
|
||||
local en = unicode.sub(s, cursorX)
|
||||
return st, en
|
||||
end
|
||||
|
||||
local function clampCursorX()
|
||||
local s = lines[cursorY]
|
||||
if unicode.len(s) < (cursorX - 1) then
|
||||
cursorX = unicode.len(s) + 1
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local cbs = {}
|
||||
|
||||
local function fileDialog(writing, callback)
|
||||
@ -128,14 +140,31 @@ local function getline(y)
|
||||
-- rX is difficult!
|
||||
local rX = 1
|
||||
local Xthold = math.max(1, math.floor(sW / 2) - 1)
|
||||
local cLine, cursorXP = unicode.safeTextFormat(lines[cursorY], cursorX)
|
||||
local _, cursorXP = unicode.safeTextFormat(lines[cursorY], cursorX)
|
||||
rX = (math.max(0, math.floor(cursorXP / Xthold) - 1) * Xthold) + 1
|
||||
local line = lines[rY]
|
||||
if not line then
|
||||
return ("¬"):rep(sW)
|
||||
end
|
||||
line = unicode.safeTextFormat(line)
|
||||
return lineEdit.draw(sW, line, rY == cursorY and cursorXP, rX)
|
||||
-- <alter RX here by 1 if needed>
|
||||
local tl = unicode.sub(line, rX, rX + sW - 1)
|
||||
cursorXP = (cursorXP - rX) + 1
|
||||
if cFlash then
|
||||
if rY == cursorY then
|
||||
if cursorXP >= 1 then
|
||||
if cursorXP <= sW then
|
||||
local start = unicode.sub(tl, 1, cursorXP - 1)
|
||||
local endx = unicode.sub(tl, cursorXP + 1)
|
||||
tl = start .. "_" .. endx
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
while unicode.len(tl) < sW do
|
||||
tl = tl .. " "
|
||||
end
|
||||
return tl
|
||||
end
|
||||
local function delLine()
|
||||
local contents = lines[cursorY]
|
||||
@ -151,7 +180,22 @@ local function delLine()
|
||||
end
|
||||
return contents
|
||||
end
|
||||
local function key(ks, kc, down)
|
||||
-- add a single character
|
||||
local function putLetter(ch)
|
||||
if ch == "\r" then
|
||||
local a, b = splitCur()
|
||||
lines[cursorY] = a
|
||||
table.insert(lines, cursorY + 1, b)
|
||||
cursorY = cursorY + 1
|
||||
cursorX = 1
|
||||
return
|
||||
end
|
||||
local a, b = splitCur()
|
||||
a = a .. ch
|
||||
lines[cursorY] = a .. b
|
||||
cursorX = unicode.len(a) + 1
|
||||
end
|
||||
local function key(ka, kc, down)
|
||||
if dialogLock then
|
||||
return false
|
||||
end
|
||||
@ -169,23 +213,23 @@ local function key(ks, kc, down)
|
||||
sH = 1
|
||||
end
|
||||
sW, sH = window.setSize(sW, sH)
|
||||
return false
|
||||
elseif kc == 208 then -- Down
|
||||
end
|
||||
if kc == 208 then -- Down
|
||||
sH = sH + 1
|
||||
sW, sH = window.setSize(sW, sH)
|
||||
return false
|
||||
elseif kc == 203 then -- Left
|
||||
end
|
||||
if kc == 203 then -- Left
|
||||
sW = sW - 1
|
||||
if sW == 0 then
|
||||
sW = 1
|
||||
end
|
||||
sW, sH = window.setSize(sW, sH)
|
||||
return false
|
||||
elseif kc == 205 then -- Right
|
||||
end
|
||||
if kc == 205 then -- Right
|
||||
sW = sW + 1
|
||||
sW, sH = window.setSize(sW, sH)
|
||||
return false
|
||||
elseif kc == 14 then -- ^Backspace
|
||||
end
|
||||
if kc == 14 then -- ^Backspace
|
||||
delLine()
|
||||
return true
|
||||
end
|
||||
@ -201,9 +245,10 @@ local function key(ks, kc, down)
|
||||
if cursorY < 1 then
|
||||
cursorY = 1
|
||||
end
|
||||
cursorX = lineEdit.clamp(lines[cursorY], cursorX)
|
||||
clampCursorX()
|
||||
return true
|
||||
elseif kc == 208 or kc == 209 then -- Go down one - go down page
|
||||
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)
|
||||
@ -212,7 +257,39 @@ local function key(ks, kc, down)
|
||||
if cursorY > #lines then
|
||||
cursorY = #lines
|
||||
end
|
||||
cursorX = lineEdit.clamp(lines[cursorY], cursorX)
|
||||
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
|
||||
@ -221,16 +298,17 @@ local function key(ks, kc, down)
|
||||
cursorX = 1
|
||||
cursorY = 1
|
||||
return true
|
||||
elseif kc == 61 then -- F3
|
||||
end
|
||||
if kc == 61 then -- F3
|
||||
startLoad()
|
||||
return false
|
||||
elseif kc == 62 then -- F4
|
||||
end
|
||||
if kc == 62 then -- F4
|
||||
startSave()
|
||||
return false
|
||||
elseif kc == 63 then -- F5
|
||||
end
|
||||
if kc == 63 then -- F5
|
||||
clipsrc.setSetting("clipboard", lines[cursorY])
|
||||
return false
|
||||
elseif kc == 64 then -- F6
|
||||
end
|
||||
if kc == 64 then -- F6
|
||||
local tx = clipsrc.getSetting("clipboard") or ""
|
||||
local txi = tx:find("\n")
|
||||
local nt = {}
|
||||
@ -244,10 +322,11 @@ local function key(ks, kc, down)
|
||||
table.insert(lines, cursorY, v)
|
||||
end
|
||||
return true
|
||||
elseif kc == 65 then -- F7
|
||||
end
|
||||
if kc == 65 then -- F7
|
||||
appendFlag = false
|
||||
return false
|
||||
elseif kc == 66 then -- F8
|
||||
end
|
||||
if kc == 66 then -- F8
|
||||
if appendFlag then
|
||||
local base = clipsrc.getSetting("clipboard")
|
||||
clipsrc.setSetting("clipboard", base .. "\n" .. delLine())
|
||||
@ -258,38 +337,30 @@ local function key(ks, kc, down)
|
||||
return true
|
||||
end
|
||||
end
|
||||
-- LEL Keys
|
||||
local lT, lC, lX = lineEdit.key(ks, kc, lines[cursorY], cursorX)
|
||||
if lT then
|
||||
lines[cursorY] = lT
|
||||
-- Letters
|
||||
if ka == 8 or kc == 211 then
|
||||
if cursorX == 1 then
|
||||
if cursorY == 1 then
|
||||
return false
|
||||
end
|
||||
if lC then
|
||||
cursorX = lC
|
||||
end
|
||||
if lX == "l<" and cursorY > 1 then
|
||||
cursorY = cursorY - 1
|
||||
cursorX = unicode.len(lines[cursorY]) + 1
|
||||
elseif lX == "l>" and cursorY < #lines then
|
||||
cursorY = cursorY + 1
|
||||
cursorX = 1
|
||||
elseif lX == "w<" and cursorY ~= 1 then
|
||||
local l = table.remove(lines, cursorY)
|
||||
cursorY = cursorY - 1
|
||||
cursorX = unicode.len(lines[cursorY]) + 1
|
||||
lines[cursorY] = lines[cursorY] .. l
|
||||
elseif lX == "w>" and cursorY ~= #lines then
|
||||
local l = table.remove(lines, cursorY)
|
||||
cursorX = unicode.len(l) + 1
|
||||
lines[cursorY] = l .. lines[cursorY]
|
||||
elseif lX == "nl" then
|
||||
local line = lines[cursorY]
|
||||
lines[cursorY] = unicode.sub(line, 1, cursorX - 1)
|
||||
table.insert(lines, cursorY + 1, unicode.sub(line, cursorX))
|
||||
cursorX = 1
|
||||
cursorY = cursorY + 1
|
||||
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
|
||||
return false
|
||||
end
|
||||
|
||||
flush = function ()
|
||||
for i = 1, sH do
|
||||
@ -297,9 +368,16 @@ flush = function ()
|
||||
end
|
||||
end
|
||||
|
||||
neo.scheduleTimer(os.uptime() + 0.5)
|
||||
|
||||
while true do
|
||||
local e = {coroutine.yield()}
|
||||
if e[1] == "x.neo.pub.window" then
|
||||
if e[1] == "k.timer" then
|
||||
cFlash = not cFlash
|
||||
local csY = math.ceil(sH / 2)
|
||||
window.span(1, csY, getline(csY), 0xFFFFFF, 0)
|
||||
neo.scheduleTimer(os.uptime() + 0.5)
|
||||
elseif e[1] == "x.neo.pub.window" then
|
||||
if e[2] == window.id then
|
||||
if e[3] == "line" then
|
||||
window.span(1, e[4], getline(e[4]), 0xFFFFFF, 0)
|
||||
@ -310,10 +388,10 @@ while true do
|
||||
local csY = math.ceil(sH / 2)
|
||||
local nY = math.max(1, math.min(#lines, (math.floor(e[5]) - csY) + cursorY))
|
||||
cursorY = nY
|
||||
cursorX = lineEdit.clamp(lines[cursorY], cursorX)
|
||||
clampCursorX()
|
||||
flush()
|
||||
elseif e[3] == "key" then
|
||||
if key(e[4] ~= 0 and unicode.char(e[4]), e[5], e[6]) then
|
||||
if key(e[4], e[5], e[6]) then
|
||||
flush()
|
||||
end
|
||||
elseif e[3] == "focus" then
|
||||
@ -328,7 +406,7 @@ while true do
|
||||
if c == "\n" then
|
||||
c = "\r"
|
||||
end
|
||||
key(c, 0, true)
|
||||
putLetter(c)
|
||||
end
|
||||
end
|
||||
flush()
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- 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)
|
||||
|
@ -1,159 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- svc-app-claw-worker: Who stays stays. Who goes goes.
|
||||
|
||||
local callerPkg, _, destProx, packageId, downloadSrc, checked, primaryINet = ...
|
||||
if callerPkg ~= "app-claw" then error("Internal process for app-claw's bidding.") end
|
||||
-- This 'mutex' remains active as long as the process does.
|
||||
neo.requireAccess("r.svc.app-claw-worker", "CLAW mutex")
|
||||
|
||||
local function wrapLines(ocb)
|
||||
local buf = ""
|
||||
return function (data)
|
||||
if not data then
|
||||
ocb(buf)
|
||||
else
|
||||
buf = buf .. data
|
||||
buf = buf:gsub("[^\n]*\n", function (t)
|
||||
ocb(t:sub(1, -2))
|
||||
return ""
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function download(url, cb, src)
|
||||
if type(src) == "string" then
|
||||
assert(primaryINet, "no internet")
|
||||
local req, err = primaryINet.request(src .. url)
|
||||
assert(req, err)
|
||||
-- OpenComputers#535
|
||||
req.finishConnect()
|
||||
while true do
|
||||
local n, n2 = req.read(neo.readBufSize)
|
||||
cb(n)
|
||||
if not n then
|
||||
req.close()
|
||||
if n2 then
|
||||
error(n2)
|
||||
else
|
||||
cb(nil)
|
||||
break
|
||||
end
|
||||
else
|
||||
if n == "" then
|
||||
neo.scheduleTimer(os.uptime() + 0.05)
|
||||
while true do
|
||||
local res = coroutine.yield()
|
||||
if res == "k.timer" then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local h, e = src.open(url, "rb")
|
||||
assert(h, e)
|
||||
repeat
|
||||
local c = src.read(h, neo.readBufSize)
|
||||
cb(c)
|
||||
until not c
|
||||
src.close(h)
|
||||
end
|
||||
end
|
||||
|
||||
local opInstall, opRemove
|
||||
|
||||
function opInstall(packageId, checked)
|
||||
local gback = {} -- the ultimate strategy
|
||||
local gdir = {}
|
||||
local preinstall = {}
|
||||
download("data/app-claw/" .. packageId .. ".c2x", wrapLines(function (l)
|
||||
if l:sub(1, 1) == "?" and checked then
|
||||
preinstall[l:sub(2)] = true
|
||||
elseif l:sub(1, 1) == "+" then
|
||||
table.insert(gback, l:sub(2))
|
||||
elseif l:sub(1, 1) == "/" then
|
||||
table.insert(gdir, l:sub(2))
|
||||
end
|
||||
end), downloadSrc)
|
||||
for _, v in ipairs(gdir) do
|
||||
destProx.makeDirectory(v)
|
||||
assert(destProx.isDirectory(v), "unable to create dir " .. v)
|
||||
end
|
||||
gdir = nil
|
||||
for k, _ in pairs(preinstall) do
|
||||
if not destProx.exists("data/app-claw/" .. k .. ".c2x") then
|
||||
opInstall(k, true)
|
||||
end
|
||||
end
|
||||
preinstall = nil
|
||||
for _, v in ipairs(gback) do
|
||||
local f = destProx.open(v .. ".C2T", "wb")
|
||||
assert(f, "unable to create download file")
|
||||
local ok, e = pcall(download, v, function (b)
|
||||
assert(destProx.write(f, b or ""), "unable to save data")
|
||||
end, downloadSrc)
|
||||
destProx.close(f)
|
||||
if not ok then error(e) end
|
||||
end
|
||||
-- CRITICAL SECTION --
|
||||
if destProx.exists("data/app-claw/" .. packageId .. ".c2x") then
|
||||
opRemove(packageId, false)
|
||||
end
|
||||
for _, v in ipairs(gback) do
|
||||
if destProx.exists(v) then
|
||||
for _, v in ipairs(gback) do
|
||||
destProx.remove(v .. ".C2T")
|
||||
end
|
||||
error("file conflict: " .. v)
|
||||
end
|
||||
end
|
||||
for _, v in ipairs(gback) do
|
||||
destProx.rename(v .. ".C2T", v)
|
||||
end
|
||||
end
|
||||
|
||||
function opRemove(packageId, checked)
|
||||
if checked then
|
||||
local dependents = {}
|
||||
for _, pidf in ipairs(destProx.list("data/app-claw/")) do
|
||||
if pidf:sub(-4) == ".c2x" then
|
||||
local pid = pidf:sub(1, -5)
|
||||
download("data/app-claw/" .. pidf, wrapLines(function (l)
|
||||
if l == "?" .. packageId then
|
||||
table.insert(dependents, pid)
|
||||
end
|
||||
end), destProx)
|
||||
end
|
||||
end
|
||||
assert(not dependents[1], "Cannot remove " .. packageId .. ", required by:\n" .. table.concat(dependents, ", "))
|
||||
end
|
||||
local rmSchedule = {}
|
||||
download("data/app-claw/" .. packageId .. ".c2x", wrapLines(function (l)
|
||||
if l:sub(1, 1) == "+" then
|
||||
table.insert(rmSchedule, l:sub(2))
|
||||
end
|
||||
end), destProx)
|
||||
for _, v in ipairs(rmSchedule) do
|
||||
destProx.remove(v)
|
||||
end
|
||||
end
|
||||
|
||||
local ok, e
|
||||
if downloadSrc then
|
||||
ok, e = pcall(opInstall, packageId, checked)
|
||||
else
|
||||
ok, e = pcall(opRemove, packageId, checked)
|
||||
end
|
||||
destProx = nil
|
||||
downloadSrc = nil
|
||||
primaryINet = nil
|
||||
neo.executeAsync("app-claw", packageId)
|
||||
if not ok then
|
||||
error(e)
|
||||
end
|
@ -1,495 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- svc-t.lua : terminal
|
||||
|
||||
local _, _, retTbl, title = ...
|
||||
|
||||
assert(retTbl, "need to alert creator")
|
||||
|
||||
if title ~= nil then
|
||||
assert(type(title) == "string", "title must be string")
|
||||
end
|
||||
|
||||
local function rW()
|
||||
return string.format("%04x", math.random(0, 65535))
|
||||
end
|
||||
|
||||
local id = "neo.pub.t/" .. rW() .. rW() .. rW() .. rW()
|
||||
local closeNow = false
|
||||
|
||||
-- Terminus Registration State --
|
||||
|
||||
local tReg = neo.requireAccess("r." .. id, "registration")
|
||||
local sendSigs = {}
|
||||
|
||||
-- Display State --
|
||||
-- unicode.safeTextFormat'd lines.
|
||||
-- The size of this must not go below 1.
|
||||
local console = {}
|
||||
-- This must not go below 3.
|
||||
local conW = 40
|
||||
local conCX, conCY = 1, 1
|
||||
local conSCX, conSCY = 1, 1
|
||||
-- Performance
|
||||
local consoleShown = {}
|
||||
local conCYShown
|
||||
for i = 1, 14 do
|
||||
console[i] = (" "):rep(conW)
|
||||
end
|
||||
|
||||
-- Line Editing State --
|
||||
-- Nil if line editing is off.
|
||||
-- In this case, the console height
|
||||
-- must be adjusted accordingly.
|
||||
local leText = ""
|
||||
-- These are NOT nil'd out,
|
||||
-- particularly not the history buffer.
|
||||
local leCX = 1
|
||||
local leHistory = {
|
||||
-- Size = history buffer size
|
||||
"", "", "", ""
|
||||
}
|
||||
local function cycleHistoryUp()
|
||||
local backupFirst = leHistory[1]
|
||||
for i = 1, #leHistory - 1 do
|
||||
leHistory[i] = leHistory[i + 1]
|
||||
end
|
||||
leHistory[#leHistory] = backupFirst
|
||||
end
|
||||
local function cycleHistoryDown()
|
||||
local backup = leHistory[1]
|
||||
for i = 2, #leHistory do
|
||||
backup, leHistory[i] = leHistory[i], backup
|
||||
end
|
||||
leHistory[1] = backup
|
||||
end
|
||||
|
||||
-- Window --
|
||||
|
||||
local window = neo.requireAccess("x.neo.pub.window", "window")(conW, #console + 1, title)
|
||||
|
||||
-- Core Terminal Functions --
|
||||
|
||||
local function setSize(w, h)
|
||||
conW = w
|
||||
for i = 1, #console do
|
||||
consoleShown[i] = nil
|
||||
end
|
||||
while #console < h do
|
||||
table.insert(console, "")
|
||||
end
|
||||
while #console > h do
|
||||
table.remove(console, 1)
|
||||
end
|
||||
for i = 1, #console do
|
||||
console[i] = unicode.sub(console[i], 1, w) .. (" "):rep(w - unicode.len(console[i]))
|
||||
end
|
||||
if leText then
|
||||
window.setSize(w, h + 1)
|
||||
else
|
||||
window.setSize(w, h)
|
||||
end
|
||||
conCX, conCY = 1, h
|
||||
end
|
||||
|
||||
local function setLineEditing(state)
|
||||
if state and not leText then
|
||||
leText = ""
|
||||
leCX = 1
|
||||
setSize(conW, #console)
|
||||
elseif leText and not state then
|
||||
leText = nil
|
||||
setSize(conW, #console)
|
||||
end
|
||||
end
|
||||
|
||||
local function draw(i)
|
||||
if console[i] then
|
||||
window.span(1, i, console[i], 0, 0xFFFFFF)
|
||||
if i == conCY and not leText then
|
||||
window.span(conCX, i, unicode.sub(console[i], conCX, conCX), 0xFFFFFF, 0)
|
||||
end
|
||||
elseif leText then
|
||||
window.span(1, i, require("lineedit").draw(conW, unicode.safeTextFormat(leText, leCX)), 0xFFFFFF, 0)
|
||||
end
|
||||
end
|
||||
local function drawDisplay()
|
||||
for i = 1, #console do
|
||||
if consoleShown[i] ~= console[i] or i == conCY or i == conCYShown then
|
||||
draw(i)
|
||||
consoleShown[i] = console[i]
|
||||
end
|
||||
end
|
||||
conCYShown = conCY
|
||||
end
|
||||
|
||||
-- Terminal Visual --
|
||||
|
||||
local function consoleSD()
|
||||
for i = 1, #console - 1 do
|
||||
console[i] = console[i + 1]
|
||||
end
|
||||
console[#console] = (" "):rep(conW)
|
||||
end
|
||||
local function consoleSU()
|
||||
local backup = (" "):rep(conW)
|
||||
for i = 1, #console do
|
||||
backup, console[i] = console[i], backup
|
||||
end
|
||||
end
|
||||
|
||||
local function consoleCLS()
|
||||
for i = 1, #console do
|
||||
console[i] = (" "):rep(conW)
|
||||
end
|
||||
conCX, conCY = 1, 1
|
||||
end
|
||||
|
||||
local function writeFF()
|
||||
if conCY ~= #console then
|
||||
conCY = conCY + 1
|
||||
else
|
||||
consoleSD()
|
||||
end
|
||||
end
|
||||
|
||||
local function writeData(data)
|
||||
-- handle data until completion
|
||||
while #data > 0 do
|
||||
local char = unicode.sub(data, 1, 1)
|
||||
--neo.emergency("svc-t.data: " .. char:byte())
|
||||
data = unicode.sub(data, 2)
|
||||
-- handle character
|
||||
if char == "\t" then
|
||||
-- not ideal, but allowed
|
||||
char = " "
|
||||
end
|
||||
if char == "\r" then
|
||||
conCX = 1
|
||||
elseif char == "\x00" then
|
||||
-- caused by TELNET \r rules
|
||||
elseif char == "\n" then
|
||||
conCX = 1
|
||||
writeFF()
|
||||
elseif char == "\a" then
|
||||
-- Bell (er...)
|
||||
elseif char == "\b" then
|
||||
conCX = math.max(1, conCX - 1)
|
||||
elseif char == "\v" or char == "\f" then
|
||||
writeFF()
|
||||
else
|
||||
local charL = unicode.wlen(char)
|
||||
if (conCX + charL - 1) > conW then
|
||||
conCX = 1
|
||||
writeFF()
|
||||
end
|
||||
local spaces = (" "):rep(charL - 1)
|
||||
console[conCY] = unicode.sub(console[conCY], 1, conCX - 1) .. char .. spaces .. unicode.sub(console[conCY], conCX + charL)
|
||||
conCX = conCX + charL
|
||||
-- Cursor can be (intentionally!) off-screen here
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function writeANSI(s)
|
||||
--neo.emergency("svc-t.ansi: " .. s)
|
||||
-- This supports just about enough to get by.
|
||||
if s == "c" then
|
||||
consoleCLS()
|
||||
return
|
||||
end
|
||||
local pfx = s:sub(1, 1)
|
||||
local cmd = s:sub(#s)
|
||||
if pfx == "[" then
|
||||
local np = tonumber(s:sub(2, -2)) or 1
|
||||
if cmd == "A" then
|
||||
conCY = conCY - np
|
||||
elseif cmd == "B" then
|
||||
conCY = conCY + np
|
||||
elseif cmd == "C" then
|
||||
conCX = conCX + np
|
||||
elseif cmd == "D" then
|
||||
conCX = conCX - np
|
||||
elseif cmd == "f" or cmd == "H" then
|
||||
local p = s:find(";")
|
||||
if not p then
|
||||
conCY = np
|
||||
conCX = 1
|
||||
else
|
||||
conCY = tonumber(s:sub(2, p - 1)) or 1
|
||||
conCX = tonumber(s:sub(p + 1, -2)) or 1
|
||||
end
|
||||
elseif cmd == "J" then
|
||||
consoleCLS()
|
||||
elseif cmd == "K" then
|
||||
if s == "[K" or s == "[0K" then
|
||||
-- bash needs this
|
||||
console[conCY] = unicode.sub(console[conCY], 1, conCX - 1) .. (" "):rep(1 + conW - conCX)
|
||||
else
|
||||
console[conCY] = (" "):rep(conW)
|
||||
end
|
||||
elseif cmd == "n" then
|
||||
if s == "[6n" then
|
||||
for _, v in pairs(sendSigs) do
|
||||
v("data", "\x1b[" .. conY .. ";" .. conX .. "R")
|
||||
end
|
||||
end
|
||||
elseif cmd == "s" then
|
||||
conSCX, conSCY = conCX, conCY
|
||||
elseif cmd == "u" then
|
||||
conCX, conCY = conSCX, conSCY
|
||||
end
|
||||
end
|
||||
conCX = math.min(math.max(math.floor(conCX), 1), conW)
|
||||
conCY = math.min(math.max(math.floor(conCY), 1), #console)
|
||||
end
|
||||
|
||||
-- The Terminus --
|
||||
|
||||
local tvBuildingCmd = ""
|
||||
local tvBuildingUTF = ""
|
||||
local tvSubnegotiation = false
|
||||
local function incoming(s)
|
||||
tvBuildingCmd = tvBuildingCmd .. s
|
||||
-- Flush Cmd
|
||||
while #tvBuildingCmd > 0 do
|
||||
if tvBuildingCmd:byte() == 255 then
|
||||
-- It's a command. Uhoh.
|
||||
if #tvBuildingCmd < 2 then break end
|
||||
local cmd = tvBuildingCmd:byte(2)
|
||||
local param = tvBuildingCmd:byte(3)
|
||||
local cmdLen = 2
|
||||
-- Command Lengths
|
||||
if cmd >= 251 and cmd <= 254 then cmdLen = 3 end
|
||||
if #tvBuildingCmd < cmdLen then break end
|
||||
if cmd == 240 then
|
||||
-- SE
|
||||
tvSubnegotiation = false
|
||||
elseif cmd == 250 then
|
||||
-- SB
|
||||
tvSubnegotiation = true
|
||||
elseif cmd == 251 and param == 1 then
|
||||
-- WILL ECHO (respond with DO ECHO, disable line editing)
|
||||
-- test using io.write("\xFF\xFB\x01")
|
||||
for _, v in pairs(sendSigs) do
|
||||
v("telnet", "\xFF\xFD\x01")
|
||||
end
|
||||
setLineEditing(false)
|
||||
elseif cmd == 252 and param == 1 then
|
||||
-- WON'T ECHO (respond with DON'T ECHO, enable line editing)
|
||||
for _, v in pairs(sendSigs) do
|
||||
v("telnet", "\xFF\xFE\x01")
|
||||
end
|
||||
setLineEditing(true)
|
||||
elseif cmd == 251 or cmd == 252 then
|
||||
-- WILL/WON'T (x) (respond with DON'T (X))
|
||||
local res = "\xFF\xFE" .. string.char(param)
|
||||
for _, v in pairs(sendSigs) do
|
||||
v("telnet", res)
|
||||
end
|
||||
elseif cmd == 253 or cmd == 254 then
|
||||
-- DO/DON'T (x) (respond with WON'T (X))
|
||||
local res = "\xFF\xFC" .. string.char(param)
|
||||
for _, v in pairs(sendSigs) do
|
||||
v("telnet", res)
|
||||
end
|
||||
elseif cmd == 255 then
|
||||
if not tvSubnegotiation then
|
||||
tvBuildingUTF = tvBuildingUTF .. "\xFF"
|
||||
end
|
||||
end
|
||||
tvBuildingCmd = tvBuildingCmd:sub(cmdLen + 1)
|
||||
else
|
||||
if not tvSubnegotiation then
|
||||
tvBuildingUTF = tvBuildingUTF .. tvBuildingCmd:sub(1, 1)
|
||||
end
|
||||
tvBuildingCmd = tvBuildingCmd:sub(2)
|
||||
end
|
||||
end
|
||||
-- Flush UTF/Display
|
||||
while #tvBuildingUTF > 0 do
|
||||
local head = tvBuildingUTF:byte()
|
||||
local len = 1
|
||||
local handled = false
|
||||
if head == 27 then
|
||||
local h2 = tvBuildingUTF:byte(2)
|
||||
if h2 == 91 then
|
||||
for i = 3, #tvBuildingUTF do
|
||||
local cmd = tvBuildingUTF:byte(i)
|
||||
if cmd >= 0x40 and cmd <= 0x7E then
|
||||
writeANSI(tvBuildingUTF:sub(2, i))
|
||||
len = i
|
||||
handled = true
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif h2 then
|
||||
len = 2
|
||||
writeANSI(tvBuildingUTF:sub(2, 2))
|
||||
handled = true
|
||||
end
|
||||
if not handled then break end
|
||||
end
|
||||
if not handled then
|
||||
if head < 192 then
|
||||
len = 1
|
||||
elseif head < 224 then
|
||||
len = 2
|
||||
elseif head < 240 then
|
||||
len = 3
|
||||
elseif head < 248 then
|
||||
len = 4
|
||||
elseif head < 252 then
|
||||
len = 5
|
||||
elseif head < 254 then
|
||||
len = 6
|
||||
end
|
||||
if #tvBuildingUTF < len then
|
||||
break
|
||||
end
|
||||
-- verified one full character...
|
||||
writeData(tvBuildingUTF:sub(1, len))
|
||||
end
|
||||
tvBuildingUTF = tvBuildingUTF:sub(len + 1)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
tReg(function (_, pid, sendSig)
|
||||
sendSigs[pid] = sendSig
|
||||
return {
|
||||
id = "x." .. id,
|
||||
pid = neo.pid,
|
||||
write = function (text)
|
||||
incoming(tostring(text))
|
||||
drawDisplay()
|
||||
end
|
||||
}
|
||||
end, true)
|
||||
|
||||
if retTbl then
|
||||
coroutine.resume(coroutine.create(retTbl), {
|
||||
access = "x." .. id,
|
||||
close = function ()
|
||||
closeNow = true
|
||||
neo.scheduleTimer(0)
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local control = false
|
||||
|
||||
local function key(a, c)
|
||||
if control then
|
||||
if c == 203 and conW > 8 then
|
||||
setSize(conW - 1, #console)
|
||||
return
|
||||
elseif c == 200 and #console > 1 then
|
||||
setSize(conW, #console - 1)
|
||||
return
|
||||
elseif c == 205 then
|
||||
setSize(conW + 1, #console)
|
||||
return
|
||||
elseif c == 208 then
|
||||
setSize(conW, #console + 1)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- so with the reserved ones dealt with...
|
||||
if not leText then
|
||||
-- Line Editing not active.
|
||||
-- For now support a bare minimum.
|
||||
for _, v in pairs(sendSigs) do
|
||||
if a == "\x03" then
|
||||
v("telnet", "\xFF\xF4")
|
||||
elseif c == 199 then
|
||||
v("data", "\x1b[H")
|
||||
elseif c == 201 then
|
||||
v("data", "\x1b[5~")
|
||||
elseif c == 207 then
|
||||
v("data", "\x1b[F")
|
||||
elseif c == 209 then
|
||||
v("data", "\x1b[6~")
|
||||
elseif c == 203 then
|
||||
v("data", "\x1b[D")
|
||||
elseif c == 205 then
|
||||
v("data", "\x1b[C")
|
||||
elseif c == 200 then
|
||||
v("data", "\x1b[A")
|
||||
elseif c == 208 then
|
||||
v("data", "\x1b[B")
|
||||
elseif a == "\r" then
|
||||
v("data", "\r\n")
|
||||
elseif a then
|
||||
v("data", a)
|
||||
end
|
||||
end
|
||||
elseif not control then
|
||||
-- Line Editing active and control isn't involved
|
||||
if c == 200 or c == 208 then
|
||||
-- History cursor up (history down)
|
||||
leText = leHistory[#leHistory]
|
||||
leCX = unicode.len(leText) + 1
|
||||
if c == 208 then
|
||||
cycleHistoryUp()
|
||||
else
|
||||
cycleHistoryDown()
|
||||
end
|
||||
return
|
||||
end
|
||||
local lT, lC, lX = require("lineedit").key(a, c, leText, leCX)
|
||||
leText = lT or leText
|
||||
leCX = lC or leCX
|
||||
if lX == "nl" then
|
||||
cycleHistoryUp()
|
||||
leHistory[#leHistory] = leText
|
||||
-- the whole thing {
|
||||
local fullText = leText .. "\r\n"
|
||||
writeData(fullText)
|
||||
drawDisplay()
|
||||
for _, v in pairs(sendSigs) do
|
||||
v("data", fullText)
|
||||
end
|
||||
-- }
|
||||
leText = ""
|
||||
leCX = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
while not closeNow do
|
||||
local e = {coroutine.yield()}
|
||||
if e[1] == "k.procdie" then
|
||||
sendSigs[e[3]] = nil
|
||||
elseif e[1] == "x.neo.pub.window" then
|
||||
if e[3] == "close" then
|
||||
break
|
||||
elseif e[3] == "clipboard" then
|
||||
for i = 1, unicode.len(e[4]) do
|
||||
local c = unicode.sub(e[4], i, i)
|
||||
if c ~= "\r" then
|
||||
if c == "\n" then
|
||||
c = "\r"
|
||||
end
|
||||
key(c, 0)
|
||||
end
|
||||
end
|
||||
draw(#console + 1)
|
||||
elseif e[3] == "key" then
|
||||
if e[5] == 29 or e[5] == 157 then
|
||||
control = e[6]
|
||||
elseif e[6] then
|
||||
key(e[4] ~= 0 and unicode.char(e[4]), e[5])
|
||||
draw(#console + 1)
|
||||
end
|
||||
elseif e[3] == "line" then
|
||||
draw(e[4])
|
||||
end
|
||||
end
|
||||
end
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- s-everest
|
||||
|
||||
@ -50,7 +46,7 @@ local monitors = {}
|
||||
-- This is where we stuff processes until monitors show up
|
||||
monitors[0] = {nil, nil, 160, 50}
|
||||
|
||||
-- {monitor, x, y, w, h, callback, title}
|
||||
-- {monitor, x, y, w, h, callback}
|
||||
-- callback events are:
|
||||
-- key ka kc down
|
||||
-- line y
|
||||
@ -65,12 +61,10 @@ local shuttingDown = false
|
||||
-- Also used for settings.
|
||||
local savingThrow = neo.requestAccess("x.neo.sys.manage")
|
||||
|
||||
local draggingWindowX, draggingWindowY
|
||||
|
||||
local function suggestAppsStop()
|
||||
for k, v in ipairs(surfaces) do
|
||||
for i = 1, 4 do
|
||||
v[6](v[8], "close")
|
||||
v[6]("close")
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -87,8 +81,8 @@ local function dying()
|
||||
-- If a process evades the deathtrap then it clearly has reason to stay alive regardless of Everest status.
|
||||
-- Also note, should savingThrow fail, neo.dead is now a thing.
|
||||
for _, v in ipairs(surfaces) do
|
||||
pcall(v[6], v[8], "line", 1)
|
||||
pcall(v[6], v[8], "line", 2)
|
||||
pcall(v[6], "line", 1)
|
||||
pcall(v[6], "line", 2)
|
||||
end
|
||||
surfaces = {}
|
||||
end
|
||||
@ -146,13 +140,162 @@ local function doBackgroundLine(m, mg, bdx, bdy, bdl)
|
||||
local str = unicode.sub(statusLine, bdx, bdx + bdl - 1)
|
||||
local strl = unicode.len(str)
|
||||
pcall(mg.set, bdx, bdy, unicode.undoSafeTextFormat(str))
|
||||
pcall(mg.set, bdx + strl, bdy, (" "):rep(bdl - strl))
|
||||
pcall(mg.fill, bdx + strl, bdy, bdl - strl, 1, " ")
|
||||
else
|
||||
monitorGPUColours(m, mg, 0x000040, 0)
|
||||
pcall(mg.set, bdx, bdy, (" "):rep(bdl))
|
||||
pcall(mg.fill, bdx, bdy, bdl, 1, " ")
|
||||
end
|
||||
end
|
||||
|
||||
local function updateRegion(monitorId, x, y, w, h, surfaceSpanCache)
|
||||
if not renderingAllowed() then return end
|
||||
local m = monitors[monitorId]
|
||||
local mg, rb = m[1]()
|
||||
if not mg then return end
|
||||
if rb then
|
||||
monitorResetBF(m)
|
||||
end
|
||||
-- The input region is the one that makes SENSE.
|
||||
-- Considering WC handling, that's not an option.
|
||||
-- WCHAX: start
|
||||
if x > 1 then
|
||||
x = x - 1
|
||||
w = w + 1
|
||||
end
|
||||
-- this, in combination with 'forcefully blank out last column of window during render',
|
||||
-- cleans up littering
|
||||
w = w + 1
|
||||
-- WCHAX: end
|
||||
|
||||
for span = 1, h do
|
||||
local backgroundMarkStart = nil
|
||||
for sx = 1, w do
|
||||
local t, tx, ty = surfaceAt(monitorId, sx + x - 1, span + y - 1)
|
||||
if t then
|
||||
-- Background must occur first due to wide char weirdness
|
||||
if backgroundMarkStart then
|
||||
local bdx, bdy, bdl = backgroundMarkStart + x - 1, span + y - 1, sx - backgroundMarkStart
|
||||
doBackgroundLine(m, mg, bdx, bdy, bdl)
|
||||
backgroundMarkStart = nil
|
||||
end
|
||||
if not surfaceSpanCache[monitorId .. "_" .. t .. "_" .. ty] then
|
||||
surfaceSpanCache[monitorId .. "_" .. t .. "_" .. ty] = true
|
||||
surfaces[t][6]("line", ty)
|
||||
end
|
||||
elseif not backgroundMarkStart then
|
||||
backgroundMarkStart = sx
|
||||
end
|
||||
end
|
||||
if backgroundMarkStart then
|
||||
doBackgroundLine(monitors[monitorId], mg, backgroundMarkStart + x - 1, span + y - 1, (w - backgroundMarkStart) + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateStatus()
|
||||
statusLine = "Λ-¶: menu (launch 'control' to logout)"
|
||||
if surfaces[1] then
|
||||
if #monitors > 1 then
|
||||
-- 123456789X123456789X123456789X123456789X123456789X
|
||||
statusLine = "Λ-+: move, Λ-Z: switch, Λ-X: swMonitor, Λ-C: close"
|
||||
else
|
||||
statusLine = "Λ-+: move, Λ-Z: switch, Λ-C: close"
|
||||
end
|
||||
end
|
||||
statusLine = unicode.safeTextFormat(statusLine)
|
||||
for k, v in ipairs(monitors) do
|
||||
updateRegion(k, 1, 1, v[3], 1, {})
|
||||
end
|
||||
end
|
||||
|
||||
local function ensureOnscreen(monitor, x, y, w, h)
|
||||
if monitor <= 0 then monitor = #monitors end
|
||||
if monitor >= (#monitors + 1) then monitor = 1 end
|
||||
-- Failing anything else, revert to monitor 0
|
||||
if #monitors == 0 then monitor = 0 end
|
||||
x = math.min(math.max(1, x), monitors[monitor][3] - (w - 1))
|
||||
y = math.max(1, math.min(monitors[monitor][4] - (h - 1), y))
|
||||
return monitor, x, y
|
||||
end
|
||||
|
||||
-- This is the "a state change occurred" function, only for use when needed
|
||||
local function reconcileAll()
|
||||
for k, v in ipairs(surfaces) do
|
||||
-- About to update whole screen anyway so avoid the wait.
|
||||
v[1], v[2], v[3] = ensureOnscreen(v[1], v[2], v[3], v[4], v[5])
|
||||
end
|
||||
local k = 1
|
||||
while k <= #monitors do
|
||||
local v = monitors[k]
|
||||
local mon, rb = v[1]()
|
||||
if rb then
|
||||
monitorResetBF(v)
|
||||
end
|
||||
if mon then
|
||||
-- This *can* return null if something went wonky. Let's detect that
|
||||
v[3], v[4] = mon.getResolution()
|
||||
if not v[3] then
|
||||
neo.emergency("everest: monitor went AWOL and nobody told me u.u")
|
||||
table.remove(monitors, k)
|
||||
v = nil
|
||||
end
|
||||
end
|
||||
if v then
|
||||
updateRegion(k, 1, 1, v[3], v[4], {})
|
||||
k = k + 1
|
||||
end
|
||||
end
|
||||
updateStatus()
|
||||
end
|
||||
|
||||
-- NOTE: If the M, X, Y, W and H are the same, this function ignores you, unless you put , true on the end.
|
||||
local function moveSurface(surface, m, x, y, w, h, force)
|
||||
local om, ox, oy, ow, oh = table.unpack(surface, 1, 5)
|
||||
m = m or om
|
||||
x = x or ox
|
||||
y = y or oy
|
||||
w = w or ow
|
||||
h = h or oh
|
||||
surface[1], surface[2], surface[3], surface[4], surface[5] = m, x, y, w, h
|
||||
local cache = {}
|
||||
if om == m and ow == w and oh == h then
|
||||
if ox == x and oy == y and not force then
|
||||
return
|
||||
end
|
||||
-- note: this doesn't always work due to WC support, and due to resize-to-repaint
|
||||
if renderingAllowed() and not force then
|
||||
local cb, b = monitors[m][1]()
|
||||
if b then
|
||||
monitorResetBF(monitors[m])
|
||||
end
|
||||
if cb then
|
||||
pcall(cb.copy, ox, oy, w, h, x - ox, y - oy)
|
||||
if surface == surfaces[1] then
|
||||
local cacheControl = {}
|
||||
for i = 1, h do
|
||||
cacheControl[om .. "_1_" .. i] = true
|
||||
end
|
||||
updateRegion(om, ox, oy, ow, oh, cacheControl)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
updateRegion(om, ox, oy, ow, oh, cache)
|
||||
updateRegion(m, x, y, w, h, cache)
|
||||
end
|
||||
-- Returns offset from where we expected to be to where we are.
|
||||
local function ofsSurface(focus, dx, dy)
|
||||
local exX, exY = focus[2] + dx, focus[3] + dy
|
||||
local m, x, y = ensureOnscreen(focus[1], exX, exY, focus[4], focus[5])
|
||||
moveSurface(focus, nil, x, y)
|
||||
return focus[2] - exX, focus[3] - exY
|
||||
end
|
||||
local function ofsMSurface(focus, dm)
|
||||
local m, x, y = ensureOnscreen(focus[1] + dm, focus[2], focus[3], focus[4], focus[5])
|
||||
moveSurface(focus, m, x, y)
|
||||
end
|
||||
|
||||
local function handleSpan(target, x, y, text, bg, fg)
|
||||
if not renderingAllowed() then return end
|
||||
local m = monitors[target[1]]
|
||||
@ -210,178 +353,6 @@ local function handleSpan(target, x, y, text, bg, fg)
|
||||
submitSegment()
|
||||
end
|
||||
|
||||
local function updateRegion(monitorId, x, y, w, h, surfaceSpanCache)
|
||||
if not renderingAllowed() then return end
|
||||
local m = monitors[monitorId]
|
||||
local mg, rb = m[1]()
|
||||
if not mg then return end
|
||||
if rb then
|
||||
monitorResetBF(m)
|
||||
end
|
||||
-- The input region is the one that makes SENSE.
|
||||
-- Considering WC handling, that's not an option.
|
||||
-- WCHAX: start
|
||||
if x > 1 then
|
||||
x = x - 1
|
||||
w = w + 1
|
||||
end
|
||||
-- this, in combination with 'forcefully blank out last column of window during render',
|
||||
-- cleans up littering
|
||||
w = w + 1
|
||||
-- WCHAX: end
|
||||
|
||||
for span = 1, h do
|
||||
local backgroundMarkStart = nil
|
||||
for sx = 1, w do
|
||||
local t, tx, ty = surfaceAt(monitorId, sx + x - 1, span + y - 1)
|
||||
if t then
|
||||
-- Background must occur first due to wide char weirdness
|
||||
if backgroundMarkStart then
|
||||
local bdx, bdy, bdl = backgroundMarkStart + x - 1, span + y - 1, sx - backgroundMarkStart
|
||||
doBackgroundLine(m, mg, bdx, bdy, bdl)
|
||||
backgroundMarkStart = nil
|
||||
end
|
||||
if not surfaceSpanCache[monitorId .. "_" .. t .. "_" .. ty] then
|
||||
surfaceSpanCache[monitorId .. "_" .. t .. "_" .. ty] = true
|
||||
if ty == 1 then
|
||||
local lw = surfaces[t][4]
|
||||
local bg = 0x0080FF
|
||||
local fg = 0x000000
|
||||
local tx = "-"
|
||||
if t == 1 then
|
||||
bg = 0x000000
|
||||
fg = 0x0080FF
|
||||
tx = "+"
|
||||
end
|
||||
local vtitle = surfaces[t][7]
|
||||
local vto = unicode.len(vtitle)
|
||||
if vto < lw then
|
||||
vtitle = vtitle .. (tx):rep(lw - vto)
|
||||
else
|
||||
vtitle = unicode.sub(vtitle, 1, lw)
|
||||
end
|
||||
handleSpan(surfaces[t], 1, 1, vtitle, bg, fg)
|
||||
else
|
||||
surfaces[t][6](surfaces[t][8], "line", ty - 1)
|
||||
end
|
||||
end
|
||||
elseif not backgroundMarkStart then
|
||||
backgroundMarkStart = sx
|
||||
end
|
||||
end
|
||||
if backgroundMarkStart then
|
||||
doBackgroundLine(monitors[monitorId], mg, backgroundMarkStart + x - 1, span + y - 1, (w - backgroundMarkStart) + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateStatus()
|
||||
statusLine = "Λ-¶: menu (launch 'control' to logout)"
|
||||
if surfaces[1] then
|
||||
if #monitors > 1 then
|
||||
-- 123456789X123456789X123456789X123456789X123456789X
|
||||
statusLine = "Λ-+: move, Λ-Z: switch, Λ-X: swMonitor, Λ-C: close"
|
||||
else
|
||||
statusLine = "Λ-+: move, Λ-Z: switch, Λ-C: close"
|
||||
end
|
||||
end
|
||||
statusLine = unicode.safeTextFormat(statusLine)
|
||||
for k, v in ipairs(monitors) do
|
||||
updateRegion(k, 1, 1, v[3], 1, {})
|
||||
end
|
||||
end
|
||||
|
||||
local function ensureOnscreen(monitor, x, y, w, h)
|
||||
if monitor <= 0 then monitor = #monitors end
|
||||
if monitor >= (#monitors + 1) then monitor = 1 end
|
||||
-- Failing anything else, revert to monitor 0
|
||||
if #monitors == 0 then monitor = 0 end
|
||||
x = math.min(math.max(x, 1), monitors[monitor][3] - (w - 1))
|
||||
y = math.max(2 - h, math.min(monitors[monitor][4], y))
|
||||
return monitor, x, y
|
||||
end
|
||||
|
||||
-- This is the "a state change occurred" function, only for use when needed
|
||||
local function reconcileAll()
|
||||
for k, v in ipairs(surfaces) do
|
||||
-- About to update whole screen anyway so avoid the wait.
|
||||
v[1], v[2], v[3] = ensureOnscreen(v[1], v[2], v[3], v[4], v[5])
|
||||
end
|
||||
local k = 1
|
||||
while k <= #monitors do
|
||||
local v = monitors[k]
|
||||
local mon, rb = v[1]()
|
||||
if rb then
|
||||
monitorResetBF(v)
|
||||
end
|
||||
if mon then
|
||||
-- This *can* return null if something went wonky. Let's detect that
|
||||
v[3], v[4] = mon.getResolution()
|
||||
if not v[3] then
|
||||
neo.emergency("everest: monitor went AWOL and nobody told me u.u")
|
||||
table.remove(monitors, k)
|
||||
v = nil
|
||||
end
|
||||
end
|
||||
if v then
|
||||
updateRegion(k, 1, 1, v[3], v[4], {})
|
||||
k = k + 1
|
||||
end
|
||||
end
|
||||
updateStatus()
|
||||
end
|
||||
|
||||
-- NOTE: If the M, X, Y, W and H are the same, this function ignores you, unless you put , true on the end.
|
||||
local function moveSurface(surface, m, x, y, w, h, force)
|
||||
local om, ox, oy, ow, oh = table.unpack(surface, 1, 5)
|
||||
m = m or om
|
||||
x = x or ox
|
||||
y = y or oy
|
||||
w = w or ow
|
||||
h = h or oh
|
||||
surface[1], surface[2], surface[3], surface[4], surface[5] = m, x, y, w, h
|
||||
local cache = {}
|
||||
if om == m and ow == w and oh == h then
|
||||
if ox == x and oy == y and not force then
|
||||
return
|
||||
end
|
||||
-- note: this doesn't always work due to WC support, and due to resize-to-repaint
|
||||
if renderingAllowed() and not force then
|
||||
local cb, b = monitors[m][1]()
|
||||
if b then
|
||||
monitorResetBF(monitors[m])
|
||||
end
|
||||
if cb then
|
||||
local monH = monitors[m][4]
|
||||
local cutTop = math.max(0, 1 - math.min(oy, y))
|
||||
local cutBottom = math.max(0, (math.max(oy + oh, y + h) - 1) - monH)
|
||||
pcall(cb.copy, ox, oy + cutTop, w, h - (cutTop + cutBottom), x - ox, y - oy)
|
||||
if surface == surfaces[1] then
|
||||
local cacheControl = {}
|
||||
for i = 1 + cutTop, h - cutBottom do
|
||||
cacheControl[om .. "_1_" .. i] = true
|
||||
end
|
||||
updateRegion(om, ox, oy, ow, oh, cacheControl)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
updateRegion(om, ox, oy, ow, oh, cache)
|
||||
updateRegion(m, x, y, w, h, cache)
|
||||
end
|
||||
-- Returns offset from where we expected to be to where we are.
|
||||
local function ofsSurface(focus, dx, dy)
|
||||
local exX, exY = focus[2] + dx, focus[3] + dy
|
||||
local m, x, y = ensureOnscreen(focus[1], exX, exY, focus[4], focus[5])
|
||||
moveSurface(focus, nil, x, y)
|
||||
return focus[2] - exX, focus[3] - exY
|
||||
end
|
||||
local function ofsMSurface(focus, dm)
|
||||
local m, x, y = ensureOnscreen(focus[1] + dm, focus[2], focus[3], focus[4], focus[5])
|
||||
moveSurface(focus, m, x, y)
|
||||
end
|
||||
|
||||
local basePalT2 = {
|
||||
-- on T2 we provide 'system colours' by default
|
||||
0x000000, 0x0080FF, 0x000040, 0xFFFFFF,
|
||||
@ -445,11 +416,11 @@ local function changeFocus(oldSurface, optcache)
|
||||
if ns1 ~= oldSurface then
|
||||
if oldSurface then
|
||||
setSurfacePalette(oldSurface, nil)
|
||||
oldSurface[6](oldSurface[8], "focus", false)
|
||||
oldSurface[6]("focus", false)
|
||||
end
|
||||
if ns1 then
|
||||
setSurfacePalette(ns1, nil)
|
||||
ns1[6](ns1[8], "focus", true)
|
||||
ns1[6]("focus", true)
|
||||
end
|
||||
updateStatus()
|
||||
if oldSurface then
|
||||
@ -488,12 +459,71 @@ everestProvider(function (pkg, pid, sendSig)
|
||||
else
|
||||
title = base .. ":" .. title
|
||||
end
|
||||
local llid = lid
|
||||
lid = lid + 1
|
||||
local surf = {math.min(#monitors, math.max(1, lIM)), 1, 2, w, h, sendSig, title, llid}
|
||||
local surf = {math.min(#monitors, math.max(1, lIM)), 1, 2, w, h}
|
||||
if h >= monitors[surf[1]][4] then
|
||||
surf[3] = 1
|
||||
end
|
||||
local focusState = false
|
||||
local llid = lid
|
||||
lid = lid + 1
|
||||
local specialDragHandler
|
||||
surf[6] = function (ev, a, b, c, d, e)
|
||||
-- Must forward surface events
|
||||
if ev == "focus" then
|
||||
focusState = a
|
||||
end
|
||||
if ev == "touch" then
|
||||
specialDragHandler = nil
|
||||
if math.floor(b) == 1 then
|
||||
if e == 1 then
|
||||
sendSig(llid, "close")
|
||||
return
|
||||
end
|
||||
specialDragHandler = function (x, y)
|
||||
local ofsX, ofsY = math.floor(x) - math.floor(a), math.floor(y) - math.floor(b)
|
||||
if (ofsX == 0) and (ofsY == 0) then return end
|
||||
ofsSurface(surf, ofsX, ofsY)
|
||||
end
|
||||
return
|
||||
end
|
||||
b = b - 1
|
||||
end
|
||||
if ev == "drag" then
|
||||
if specialDragHandler then
|
||||
specialDragHandler(a, b)
|
||||
return
|
||||
end
|
||||
b = b - 1
|
||||
end
|
||||
if ev == "scroll" or ev == "drop" then
|
||||
specialDragHandler = nil
|
||||
b = b - 1
|
||||
end
|
||||
if ev == "line" then
|
||||
if a == 1 then
|
||||
local lw = surf[4]
|
||||
local bg = 0x0080FF
|
||||
local fg = 0x000000
|
||||
local tx = "-"
|
||||
if focusState then
|
||||
bg = 0x000000
|
||||
fg = 0x0080FF
|
||||
tx = "+"
|
||||
end
|
||||
local vtitle = title
|
||||
local vto = unicode.len(vtitle)
|
||||
if vto < lw then
|
||||
vtitle = vtitle .. (tx):rep(lw - vto)
|
||||
else
|
||||
vtitle = unicode.sub(vtitle, 1, lw)
|
||||
end
|
||||
handleSpan(surf, 1, 1, vtitle, bg, fg)
|
||||
return
|
||||
end
|
||||
a = a - 1
|
||||
end
|
||||
sendSig(llid, ev, a, b, c, d, e)
|
||||
end
|
||||
local osrf = surfaces[1]
|
||||
table.insert(surfaces, 1, surf)
|
||||
surfaceOwners[surf] = pid
|
||||
@ -521,13 +551,17 @@ everestProvider(function (pkg, pid, sendSig)
|
||||
end,
|
||||
span = function (x, y, text, bg, fg)
|
||||
if neo.dead then error("everest died") end
|
||||
checkArg(3, text, "string")
|
||||
if type(x) ~= "number" then error("X must be number.") end
|
||||
if type(y) ~= "number" then error("Y must be number.") end
|
||||
if type(bg) ~= "number" then error("Background must be number.") end
|
||||
if type(fg) ~= "number" then error("Foreground must be number.") end
|
||||
if type(text) ~= "string" then error("Text must be string.") end
|
||||
x, y, bg, fg = math.floor(x), math.floor(y), math.floor(bg), math.floor(fg)
|
||||
if y == 0 then return end
|
||||
handleSpan(surf, x, y + 1, text, bg, fg)
|
||||
end,
|
||||
recommendPalette = function (pal)
|
||||
if surfaces[1] ~= surf then return 0 end
|
||||
if not focusState then return 0 end
|
||||
return setSurfacePalette(surf, pal)
|
||||
end,
|
||||
close = function ()
|
||||
@ -552,7 +586,7 @@ end)
|
||||
-- THE EVEREST USER API ENDS (now for the session API, which just does boring stuff)
|
||||
-- used later on for lost monitor, too
|
||||
local function disclaimMonitor(mon)
|
||||
checkArg(1, mon, "string")
|
||||
neo.ensureType(mon, "string")
|
||||
screens.disclaim(mon)
|
||||
for k, v in ipairs(monitors) do
|
||||
if v[2] == mon then
|
||||
@ -566,7 +600,7 @@ end
|
||||
everestSessionProvider(function (pkg, pid, sendSig)
|
||||
return {
|
||||
endSession = function (gotoBristol)
|
||||
checkArg(1, gotoBristol, "boolean")
|
||||
neo.ensureType(gotoBristol, "boolean")
|
||||
shuttingDown = true
|
||||
if gotoBristol then
|
||||
suggestAppsStop()
|
||||
@ -604,59 +638,69 @@ end
|
||||
local isAltDown = false
|
||||
local isCtrDown = false
|
||||
local function key(ku, ka, kc, down)
|
||||
local ku, lin = screens.getMonitorByKeyboard(ku)
|
||||
local ku = screens.getMonitorByKeyboard(ku)
|
||||
if not ku then return end
|
||||
for k, v in ipairs(monitors) do
|
||||
if ku and v[2] == ku then
|
||||
lin = k
|
||||
break
|
||||
if v[2] == mu then
|
||||
lIM = k
|
||||
end
|
||||
end
|
||||
if not lin then return end
|
||||
lIM = lin
|
||||
|
||||
local focus = surfaces[1]
|
||||
if kc == 29 then
|
||||
isCtrDown = down
|
||||
elseif kc == 56 then
|
||||
isAltDown = down
|
||||
if kc == 29 then isCtrDown = down end
|
||||
if kc == 56 then isAltDown = down end
|
||||
if isAltDown then
|
||||
if ka == 120 then
|
||||
if focus and down then ofsMSurface(focus, 1) end return
|
||||
end
|
||||
if isAltDown and ka == 122 then
|
||||
if kc == 200 then
|
||||
if focus and down then ofsSurface(focus, 0, -1) end return
|
||||
end
|
||||
if kc == 208 then
|
||||
if focus and down then ofsSurface(focus, 0, 1) end return
|
||||
end
|
||||
if kc == 203 then
|
||||
if focus and down then ofsSurface(focus, -1, 0) end return
|
||||
end
|
||||
if kc == 205 then
|
||||
if focus and down then ofsSurface(focus, 1, 0) end return
|
||||
end
|
||||
if ka == 122 then
|
||||
if focus and down then
|
||||
local n = table.remove(surfaces, 1)
|
||||
table.insert(surfaces, n)
|
||||
changeFocus(n)
|
||||
end return
|
||||
end
|
||||
elseif isAltDown and kc == 200 then
|
||||
if focus and down then ofsSurface(focus, 0, -1) end
|
||||
elseif isAltDown and kc == 208 then
|
||||
if focus and down then ofsSurface(focus, 0, 1) end
|
||||
elseif isAltDown and kc == 203 then
|
||||
if focus and down then ofsSurface(focus, -1, 0) end
|
||||
elseif isAltDown and kc == 205 then
|
||||
if focus and down then ofsSurface(focus, 1, 0) end
|
||||
elseif isAltDown and ka == 120 then
|
||||
if focus and down then ofsMSurface(focus, 1) end
|
||||
elseif isAltDown and ka == 97 then
|
||||
if not down then
|
||||
isAltDown = false
|
||||
if ka == 3 then
|
||||
-- Ctrl-Alt-C (!?!?!!)
|
||||
if isCtrDown then
|
||||
error("User-authorized Everest crash.")
|
||||
end
|
||||
elseif isAltDown and (ka == 3 or ka == 99) then
|
||||
end
|
||||
if ka == 99 then
|
||||
if down then
|
||||
if isCtrDown then
|
||||
error("User-authorized Everest crash.")
|
||||
elseif focus then
|
||||
focus[6](focus[8], "close")
|
||||
else
|
||||
if focus then
|
||||
focus[6]("close")
|
||||
end
|
||||
end
|
||||
elseif isAltDown and ka == 13 then
|
||||
end
|
||||
return
|
||||
end
|
||||
if ka == 13 then
|
||||
if down then
|
||||
startLauncher()
|
||||
end
|
||||
elseif focus then
|
||||
return
|
||||
end
|
||||
end
|
||||
if focus then
|
||||
if kc ~= 56 then
|
||||
lIM = focus[1]
|
||||
end
|
||||
focus[6](focus[8], "key", ka, kc, down)
|
||||
focus[6]("key", ka, kc, down)
|
||||
end
|
||||
end
|
||||
|
||||
@ -689,7 +733,7 @@ while not shuttingDown do
|
||||
end
|
||||
if s[1] == "h.clipboard" then
|
||||
if surfaces[1] then
|
||||
surfaces[1][6](surfaces[1][8], "clipboard", s[3])
|
||||
surfaces[1][6]("clipboard", s[3])
|
||||
end
|
||||
end
|
||||
-- next on my list: high-res coordinates
|
||||
@ -705,16 +749,7 @@ while not shuttingDown do
|
||||
local ns = table.remove(surfaces, sid)
|
||||
table.insert(surfaces, 1, ns)
|
||||
changeFocus(os)
|
||||
draggingWindowX, draggingWindowY = nil
|
||||
if ly == 1 then
|
||||
if s[5] == 1 then
|
||||
ns[6](ns[8], "close")
|
||||
else
|
||||
draggingWindowX, draggingWindowY = lx, ly
|
||||
end
|
||||
else
|
||||
ns[6](ns[8], "touch", lx, ly - 1, ix, iy, s[5])
|
||||
end
|
||||
ns[6]("touch", lx, ly, ix, iy, s[5])
|
||||
else
|
||||
if s[5] == 1 then startLauncher() end
|
||||
end
|
||||
@ -731,16 +766,8 @@ while not shuttingDown do
|
||||
if k == focus[1] then
|
||||
local x, y = (math.ceil(s[3]) - focus[2]) + 1, (math.ceil(s[4]) - focus[3]) + 1
|
||||
local ix, iy = s[3] - math.floor(s[3]), s[4] - math.floor(s[4])
|
||||
if s[1] == "h.drag" and draggingWindowX then
|
||||
local ofsX, ofsY = x - draggingWindowX, y - draggingWindowY
|
||||
if ofsX ~= 0 or ofsY ~= 0 then
|
||||
ofsSurface(focus, ofsX, ofsY)
|
||||
end
|
||||
else
|
||||
draggingWindowX, draggingWindowY = nil
|
||||
-- Ok, so let's see...
|
||||
focus[6](focus[8], s[1]:sub(3), x, y - 1, ix, iy, s[5])
|
||||
end
|
||||
focus[6](s[1]:sub(3), x, y, ix, iy, s[5])
|
||||
end
|
||||
break
|
||||
end
|
||||
@ -772,7 +799,7 @@ while not shuttingDown do
|
||||
if os1 then
|
||||
changeFocus(os1)
|
||||
else
|
||||
changeFocus()
|
||||
changeFocus(surfaces[1])
|
||||
end
|
||||
end
|
||||
if s[1] == "x.neo.sys.screens" then
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- s-donkonit : config, shutdown, screens
|
||||
|
||||
@ -129,7 +125,7 @@ local mBase = {
|
||||
end
|
||||
return s
|
||||
end,
|
||||
delSetting = function (name)
|
||||
delSetting = function ()
|
||||
neo.ensureType(name, "string")
|
||||
local val = nil
|
||||
if name == "password" or name == "pub.clipboard" then val = "" end
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- s-icecap : Responsible for x.neo.pub API, crash dialogs, and security policy that isn't "sys- has ALL access, anything else has none"
|
||||
-- In general, this is what userspace will be interacting with in some way or another to get stuff done
|
||||
@ -85,12 +81,20 @@ local function getPfx(xd, pkg)
|
||||
end
|
||||
end
|
||||
|
||||
local function splitAC(ac)
|
||||
local sb = ac:match("/[a-z0-9/%.]*$")
|
||||
if sb then
|
||||
return ac:sub(1, #ac - #sb), sb
|
||||
local endAcPattern = "/[a-z0-9/%.]*$"
|
||||
|
||||
local function matchesSvc(xd, pkg, perm)
|
||||
local pfx = getPfx(xd, pkg)
|
||||
if pfx then
|
||||
local permAct = perm
|
||||
local paP = permAct:match(endAcPattern)
|
||||
if paP then
|
||||
permAct = permAct:sub(1, #permAct - #paP)
|
||||
end
|
||||
if permAct == pfx then
|
||||
return "allow"
|
||||
end
|
||||
end
|
||||
return ac
|
||||
end
|
||||
|
||||
donkonitDFProvider(function (pkg, pid, sendSig)
|
||||
@ -105,20 +109,17 @@ donkonitDFProvider(function (pkg, pid, sendSig)
|
||||
end
|
||||
end
|
||||
return {
|
||||
showFileDialogAsync = function (forWrite, defName)
|
||||
showFileDialogAsync = function (forWrite)
|
||||
if not rawequal(forWrite, nil) then
|
||||
require("sys-filewrap").ensureMode(forWrite)
|
||||
end
|
||||
if not rawequal(defName, nil) then
|
||||
defName = tostring(defName)
|
||||
end
|
||||
-- Not hooked into the event API, so can't safely interfere
|
||||
-- Thus, this is async and uses a return event.
|
||||
local tag = {}
|
||||
neo.scheduleTimer(0)
|
||||
table.insert(todo, function ()
|
||||
-- sys-filedialog is yet another "library to control memory usage".
|
||||
local closer = require("sys-filedialog")(event, nexus, function (res) openHandles[tag] = nil sendSig("filedialog", tag, res) end, neo.requireAccess("c.filesystem", "file managers"), pkg, forWrite, defName)
|
||||
local closer = require("sys-filedialog")(event, nexus, function (res) openHandles[tag] = nil sendSig("filedialog", tag, res) end, neo.requireAccess("c.filesystem", "file managers"), pkg, forWrite)
|
||||
openHandles[tag] = closer
|
||||
end)
|
||||
return tag
|
||||
@ -126,8 +127,7 @@ donkonitDFProvider(function (pkg, pid, sendSig)
|
||||
myApi = getPfx("", pkg),
|
||||
lockPerm = function (perm)
|
||||
-- Are we allowed to?
|
||||
local permPfx, detail = splitAC(perm)
|
||||
if getPfx("x.", pkg) ~= permPfx then
|
||||
if not matchesSvc("x.", pkg, perm) then
|
||||
return false, "You don't own this permission."
|
||||
end
|
||||
local set = "perm|*|" .. perm
|
||||
@ -220,11 +220,7 @@ local function secPolicyStage2(pid, proc, perm, req)
|
||||
-- Push to ICECAP thread to avoid deadlock b/c wrong event-pull context
|
||||
neo.scheduleTimer(0)
|
||||
table.insert(todo, function ()
|
||||
local fPerm = perm
|
||||
if fPerm:sub(1, 2) == "r." then
|
||||
fPerm = splitAC(fPerm)
|
||||
end
|
||||
local ok, err = pcall(secpol, nexus, settings, proc.pkg, pid, fPerm, req, getPfx("", proc.pkg))
|
||||
local ok, err = pcall(secpol, nexus, settings, proc.pkg, pid, perm, req, matchesSvc)
|
||||
if not ok then
|
||||
neo.emergency("Used fallback policy because of run-err: " .. err)
|
||||
req(def)
|
||||
@ -244,7 +240,11 @@ rootAccess.securityPolicy = function (pid, proc, perm, req)
|
||||
end
|
||||
-- Do we need to start it?
|
||||
if perm:sub(1, 6) == "x.svc." and not neo.usAccessExists(perm) then
|
||||
local appAct = splitAC(perm:sub(7))
|
||||
local appAct = perm:sub(7)
|
||||
local paP = appAct:match(endAcPattern)
|
||||
if paP then
|
||||
appAct = appAct:sub(1, #appAct - #paP)
|
||||
end
|
||||
-- Prepare for success
|
||||
onReg[perm] = onReg[perm] or {}
|
||||
local orp = onReg[perm]
|
||||
|
@ -1,27 +1,21 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- s-bristol splash screen, login agent
|
||||
-- Named to allude to Plymouth (splash screen used in some linux distros)
|
||||
|
||||
local callerPkg, callerPid, callerScr = ...
|
||||
|
||||
local gpuG, screen = nil, nil
|
||||
local shutdownEmergency = neo.requestAccess("k.computer").shutdown
|
||||
neo.requestAccess("s.h.key_down")
|
||||
neo.requestAccess("s.h._kosneo_syslog")
|
||||
|
||||
-- gpuG/performDisclaim are GPU management, while screen is used for prioritization
|
||||
local gpuG, performDisclaim, screen = nil
|
||||
local scrW, scrH = 1, 1
|
||||
local nssInst
|
||||
|
||||
local console = {}
|
||||
local helpActive = false
|
||||
local buttonsActive = false
|
||||
local scrW, scrH
|
||||
local warnings = {
|
||||
"",
|
||||
"",
|
||||
""
|
||||
}
|
||||
|
||||
-- Attempts to call upon nsm for a safe shutdown
|
||||
local function shutdown(reboot)
|
||||
@ -36,53 +30,32 @@ local function shutdown(reboot)
|
||||
end
|
||||
end
|
||||
|
||||
local function basicDraw(bg)
|
||||
local gpu = gpuG()
|
||||
pcall(gpu.setBackground, bg or 0xFFFFFF)
|
||||
local function rstfbDraw(gpu)
|
||||
pcall(gpu.setBackground, 0xFFFFFF)
|
||||
pcall(gpu.setForeground, 0x000000)
|
||||
end
|
||||
|
||||
local function basicDraw(gpu)
|
||||
local ok, sw, sh = pcall(gpu.getResolution)
|
||||
if not ok then return end
|
||||
scrW, scrH = sw, sh
|
||||
pcall(gpu.fill, 1, 1, scrW, scrH, " ")
|
||||
pcall(gpu.set, 2, 2, "KittenOS NEO")
|
||||
end
|
||||
|
||||
local function advDraw(gpu)
|
||||
basicDraw(gpu)
|
||||
local usage = math.floor((os.totalMemory() - os.freeMemory()) / 1024)
|
||||
pcall(gpu.set, 2, 3, "RAM Usage: " .. usage .. "K / " .. math.floor(os.totalMemory() / 1024) .. "K")
|
||||
local cut = 7
|
||||
if buttonsActive then cut = 9 end
|
||||
local areaSize = scrH - cut
|
||||
local n2 = 0
|
||||
if helpActive then
|
||||
if _VERSION == "Lua 5.2" then
|
||||
table.insert(console, "WARNING: Lua 5.2 memory usage issue!")
|
||||
table.insert(console, "Shift-right-click while holding the CPU/APU.")
|
||||
n2 = 2
|
||||
end
|
||||
table.insert(console, "TAB to change option, ENTER to select.")
|
||||
n2 = n2 + 1
|
||||
end
|
||||
for i = 1, areaSize do
|
||||
pcall(gpu.set, 2, 6 + i, console[#console + i - areaSize] or "")
|
||||
end
|
||||
for i = 1, n2 do
|
||||
table.remove(console, #console)
|
||||
end
|
||||
return gpu
|
||||
end
|
||||
|
||||
local function consoleEventHandler(ev)
|
||||
if ev[1] == "h._kosneo_syslog" then
|
||||
local text = ""
|
||||
for i = 3, #ev do
|
||||
if i ~= 3 then text = text .. " " end
|
||||
text = text .. tostring(ev[i])
|
||||
end
|
||||
table.insert(console, text)
|
||||
for i = 1, #warnings do
|
||||
pcall(gpu.set, 2, 6 + i, warnings[i])
|
||||
end
|
||||
end
|
||||
|
||||
-- Attempts to get an NSS monitor with a priority list of screens
|
||||
local function retrieveNssMonitor(...)
|
||||
local spc = {...}
|
||||
-- Callback setup by finalPrompt to disclaim the main monitor first
|
||||
local performDisclaim = nil
|
||||
|
||||
local function retrieveNssMonitor(nss)
|
||||
gpuG = nil
|
||||
local subpool = {}
|
||||
while not gpuG do
|
||||
@ -94,33 +67,29 @@ local function retrieveNssMonitor(...)
|
||||
-- If no monitors are available, shut down now.
|
||||
-- NSS monitor pool output is smaller than, but similar to, Everest monitor data:
|
||||
-- {gpu, screenAddr}
|
||||
local pool = nssInst.getClaimable()
|
||||
local pool = nss.getClaimable()
|
||||
while not pool[1] do
|
||||
-- wait for presumably a NSS notification
|
||||
consoleEventHandler({coroutine.yield()})
|
||||
pool = nssInst.getClaimable()
|
||||
coroutine.yield() -- wait for presumably a NSS notification
|
||||
pool = nss.getClaimable()
|
||||
end
|
||||
subpool = {}
|
||||
-- Specifies which element to elevate to top priority
|
||||
local optimalSwap = nil
|
||||
local optimal = #spc + 1
|
||||
if screen then
|
||||
for k, v in ipairs(pool) do
|
||||
for k2, v2 in ipairs(spc) do
|
||||
if v == v2 and optimal > k2 then
|
||||
optimalSwap, optimal = k, k2
|
||||
if v == screen then
|
||||
optimalSwap = k
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if optimalSwap then
|
||||
local swapA = pool[optimalSwap]
|
||||
pool[optimalSwap] = pool[1]
|
||||
pool[1] = swapA
|
||||
end
|
||||
for _, v in ipairs(pool) do
|
||||
local gpu = nssInst.claim(v)
|
||||
local gpu = nss.claim(v)
|
||||
if gpu then
|
||||
local gcb = gpu()
|
||||
if gcb then
|
||||
@ -133,53 +102,52 @@ local function retrieveNssMonitor(...)
|
||||
end
|
||||
end
|
||||
end
|
||||
if subpool[1] then
|
||||
gpuG, screen = table.unpack(subpool[1])
|
||||
|
||||
if not subpool[1] then
|
||||
error("None of the GPUs we got were actually usable")
|
||||
end
|
||||
gpuG = subpool[1][1]
|
||||
screen = subpool[1][2]
|
||||
end
|
||||
-- done with search
|
||||
local gpu = gpuG()
|
||||
rstfbDraw(gpu)
|
||||
performDisclaim = function (full)
|
||||
nssInst.disclaim(subpool[1][2])
|
||||
nss.disclaim(subpool[1][2])
|
||||
if full then
|
||||
for _, v in ipairs(subpool) do
|
||||
nssInst.disclaim(v[2])
|
||||
nss.disclaim(v[2])
|
||||
end
|
||||
end
|
||||
end
|
||||
return gpu
|
||||
end
|
||||
|
||||
local function sleep(t)
|
||||
neo.scheduleTimer(os.uptime() + t)
|
||||
while true do
|
||||
local ev = {coroutine.yield()}
|
||||
consoleEventHandler(ev)
|
||||
if ev[1] == "k.timer" then
|
||||
break
|
||||
end
|
||||
if ev[1] == "x.neo.sys.screens" then
|
||||
retrieveNssMonitor(screen)
|
||||
basicDraw()
|
||||
-- This implies we have and can use nss, but check anyway
|
||||
local nss = neo.requestAccess("x.neo.sys.screens")
|
||||
if nss then
|
||||
local gpu = retrieveNssMonitor(nss)
|
||||
basicDraw(gpu)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function alert(s)
|
||||
console = {s}
|
||||
helpActive, buttonsActive = false, false
|
||||
basicDraw()
|
||||
sleep(1)
|
||||
buttonsActive = true
|
||||
end
|
||||
|
||||
local function finalPrompt()
|
||||
nssInst = neo.requestAccess("x.neo.sys.screens")
|
||||
if not nssInst then
|
||||
console = {"sys-glacier not available"}
|
||||
basicDraw()
|
||||
error("no nssInst")
|
||||
local nss = neo.requestAccess("x.neo.sys.screens")
|
||||
if nss then
|
||||
retrieveNssMonitor(nss)
|
||||
else
|
||||
error("no glacier to provide GPU for the prompt")
|
||||
end
|
||||
retrieveNssMonitor()
|
||||
helpActive, buttonsActive = true, true
|
||||
-- This is nsm's final chance to make itself available and thus allow the password to be set
|
||||
local nsm = neo.requestAccess("x.neo.sys.manage")
|
||||
local waiting = true
|
||||
@ -191,11 +159,24 @@ local function finalPrompt()
|
||||
return false
|
||||
end
|
||||
end
|
||||
if _VERSION == "Lua 5.2" then
|
||||
warnings[1] = "NOTE: It's recommended you use Lua 5.3."
|
||||
warnings[2] = "Shift-right-click while holding the CPU item."
|
||||
else
|
||||
warnings[1] = "TAB to change option,"
|
||||
warnings[2] = "ENTER to select..."
|
||||
end
|
||||
-- The actual main prompt loop
|
||||
while waiting do
|
||||
local gpu = gpuG()
|
||||
rstfbDraw(gpu)
|
||||
advDraw(gpu)
|
||||
local entry = ""
|
||||
local entry2 = ""
|
||||
local active = true
|
||||
local shButton = "<Shutdown>"
|
||||
local rbButton = "<Reboot>"
|
||||
local smButton = "<Safe Mode>"
|
||||
local pw = {function ()
|
||||
return "Password: " .. entry2
|
||||
end, function (key)
|
||||
@ -207,7 +188,10 @@ local function finalPrompt()
|
||||
if entry == password then
|
||||
waiting = false
|
||||
else
|
||||
alert("Incorrect password")
|
||||
local gpu = gpuG()
|
||||
rstfbDraw(gpu)
|
||||
advDraw(gpu)
|
||||
sleep(1)
|
||||
end
|
||||
active = false
|
||||
end
|
||||
@ -224,36 +208,47 @@ local function finalPrompt()
|
||||
end
|
||||
local controls = {
|
||||
{function ()
|
||||
return "<Shutdown>"
|
||||
return shButton
|
||||
end, function (key)
|
||||
if key == 13 then
|
||||
alert("Shutting down...")
|
||||
local gpu = gpuG()
|
||||
rstfbDraw(gpu)
|
||||
basicDraw(gpu)
|
||||
pcall(gpu.set, 2, 4, "Shutting down...")
|
||||
shutdown(false)
|
||||
end
|
||||
end, 2, scrH - 1, 10},
|
||||
end, 2, scrH - 1, unicode.len(shButton)},
|
||||
{function ()
|
||||
return "<Reboot>"
|
||||
return rbButton
|
||||
end, function (key)
|
||||
if key == 13 then
|
||||
alert("Rebooting...")
|
||||
local gpu = gpuG()
|
||||
rstfbDraw(gpu)
|
||||
basicDraw(gpu)
|
||||
pcall(gpu.set, 2, 4, "Rebooting...")
|
||||
shutdown(true)
|
||||
end
|
||||
end, 13, scrH - 1, 8},
|
||||
end, 3 + unicode.len(shButton), scrH - 1, unicode.len(rbButton)},
|
||||
{function ()
|
||||
return "<Safe Mode>"
|
||||
return smButton
|
||||
end, function (key)
|
||||
if key == 13 then
|
||||
local gpu = gpuG()
|
||||
rstfbDraw(gpu)
|
||||
basicDraw(gpu)
|
||||
pcall(gpu.set, 2, 4, "Login to activate Safe Mode.")
|
||||
sleep(1)
|
||||
gpu = gpuG()
|
||||
safeModeActive = true
|
||||
alert("Login to activate Safe Mode.")
|
||||
rstfbDraw(gpu)
|
||||
advDraw(gpu)
|
||||
end
|
||||
end, 22, scrH - 1, 11},
|
||||
end, 4 + unicode.len(shButton) + unicode.len(rbButton), scrH - 1, unicode.len(smButton)},
|
||||
pw,
|
||||
}
|
||||
local control = #controls
|
||||
local lastKeyboard
|
||||
while active do
|
||||
local gpu = basicDraw()
|
||||
if gpu then
|
||||
local gpu = gpuG()
|
||||
for k, v in ipairs(controls) do
|
||||
if k == control then
|
||||
pcall(gpu.setBackground, 0x000000)
|
||||
@ -265,28 +260,16 @@ local function finalPrompt()
|
||||
pcall(gpu.fill, v[3], v[4], v[5], 1, " ")
|
||||
pcall(gpu.set, v[3], v[4], v[1]())
|
||||
end
|
||||
end
|
||||
-- event handling...
|
||||
local sig = {coroutine.yield()}
|
||||
consoleEventHandler(sig)
|
||||
if sig[1] == "x.neo.sys.screens" then
|
||||
-- We need to reinit screens no matter what.
|
||||
retrieveNssMonitor(screen)
|
||||
active = false
|
||||
retrieveNssMonitor(nss)
|
||||
end
|
||||
if sig[1] == "h.key_down" then
|
||||
if sig[2] ~= lastKeyboard then
|
||||
lastKeyboard = sig[2]
|
||||
local nScreen = nssInst.getMonitorByKeyboard(lastKeyboard)
|
||||
if nScreen and nScreen ~= screen then
|
||||
neo.emergency("new primary:", nScreen)
|
||||
retrieveNssMonitor(nScreen, screen)
|
||||
active = false
|
||||
end
|
||||
end
|
||||
if sig[4] == 15 then
|
||||
-- this makes sense in context
|
||||
control = control % #controls
|
||||
control = control % (#controls)
|
||||
control = control + 1
|
||||
else
|
||||
controls[control][2](sig[3])
|
||||
@ -294,21 +277,24 @@ local function finalPrompt()
|
||||
end
|
||||
end
|
||||
end
|
||||
helpActive, buttonsActive = false, false
|
||||
local gpu = gpuG()
|
||||
rstfbDraw(gpu)
|
||||
advDraw(gpu)
|
||||
return safeModeActive
|
||||
end
|
||||
local function postPrompt()
|
||||
local gpu = gpuG()
|
||||
local nsm = neo.requestAccess("x.neo.sys.manage")
|
||||
local sh = "sys-everest"
|
||||
console = {"Unable to get shell (no sys-glacier)"}
|
||||
warnings = {"Unable to get sys-init.shell due to no NSM, using sys-everest"}
|
||||
if nsm then
|
||||
sh = nsm.getSetting("sys-init.shell") or sh
|
||||
console = {"Starting " .. sh}
|
||||
warnings = {"Starting " .. sh}
|
||||
end
|
||||
basicDraw()
|
||||
rstfbDraw(gpu)
|
||||
advDraw(gpu)
|
||||
performDisclaim()
|
||||
neo.executeAsync(sh)
|
||||
-- There's a delay here to allow taking the monitor.
|
||||
sleep(0.5)
|
||||
for i = 1, 9 do
|
||||
local v = neo.requestAccess("x.neo.sys.session")
|
||||
@ -318,16 +304,16 @@ local function postPrompt()
|
||||
end
|
||||
end
|
||||
-- ...oh. hope this works then?
|
||||
console = {"x.neo.sys.session not found, try Safe Mode."}
|
||||
retrieveNssMonitor(screen)
|
||||
basicDraw()
|
||||
warnings = {"That wasn't a shell. Try Safe Mode."}
|
||||
rstfbDraw(gpu)
|
||||
advDraw(gpu)
|
||||
sleep(1)
|
||||
shutdown(true)
|
||||
end
|
||||
|
||||
local function initializeSystem()
|
||||
-- System has just booted, bristol is in charge
|
||||
-- No screen configuration, so just guess.
|
||||
-- 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")
|
||||
@ -354,36 +340,55 @@ local function initializeSystem()
|
||||
gW, gH = math.min(80, gW), math.min(25, gH)
|
||||
pcall(gpu.setResolution, gW, gH)
|
||||
pcall(gpu.setDepth, gpu.maxDepth()) -- can crash on OCEmu if done at the "wrong time"
|
||||
pcall(gpu.setForeground, 0x000000)
|
||||
end
|
||||
-- Setup the new GPU provider
|
||||
gpuG = function () return gpu end
|
||||
--
|
||||
local w = 1
|
||||
local steps = {"sys-glacier"}
|
||||
for i = 1, 4 do table.insert(steps, "WAIT") end
|
||||
table.insert(steps, "INJECT")
|
||||
for i = 1, 8 do table.insert(steps, "WAIT") end
|
||||
|
||||
local steps = {
|
||||
"sys-glacier", -- (Glacier : Config, Screen, Power)
|
||||
-- Let that start, and system GC
|
||||
"WAIT",
|
||||
"WAIT",
|
||||
"WAIT",
|
||||
"WAIT",
|
||||
-- Start services
|
||||
"INJECT",
|
||||
-- extra GC time
|
||||
"WAIT",
|
||||
"WAIT",
|
||||
"WAIT",
|
||||
"WAIT",
|
||||
"WAIT",
|
||||
"WAIT",
|
||||
"WAIT"
|
||||
}
|
||||
local stepCount = #steps
|
||||
|
||||
neo.scheduleTimer(os.uptime())
|
||||
while true do
|
||||
local ev = {coroutine.yield()}
|
||||
consoleEventHandler(ev)
|
||||
if ev[1] == "k.procnew" then
|
||||
table.insert(warnings, ev[2] .. "/" .. ev[3] .. " UP")
|
||||
end
|
||||
if ev[1] == "k.procdie" then
|
||||
table.insert(warnings, ev[2] .. "/" .. ev[3] .. " DOWN")
|
||||
table.insert(warnings, tostring(ev[4]))
|
||||
end
|
||||
if ev[1] == "k.timer" then
|
||||
if gpu then
|
||||
local bg = 0xFFFFFF
|
||||
pcall(gpu.setForeground, 0x000000)
|
||||
if w < stepCount then
|
||||
local n = math.floor((w / stepCount) * 255)
|
||||
bg = (n * 0x10000) + (n * 0x100) + n
|
||||
pcall(gpu.setBackground, (n * 0x10000) + (n * 0x100) + n)
|
||||
else
|
||||
pcall(gpu.setBackground, 0xFFFFFF)
|
||||
end
|
||||
basicDraw(bg)
|
||||
basicDraw(gpu)
|
||||
end
|
||||
if steps[w] then
|
||||
if steps[w] == "INJECT" then
|
||||
local nsm = neo.requestAccess("x.neo.sys.manage")
|
||||
if not nsm then
|
||||
table.insert(console, "Settings not available for INJECT.")
|
||||
table.insert(warnings, "Settings not available for INJECT.")
|
||||
else
|
||||
local nextstepsA = {}
|
||||
local nextstepsB = {}
|
||||
@ -407,8 +412,10 @@ local function initializeSystem()
|
||||
else
|
||||
local v, err = neo.executeAsync(steps[w])
|
||||
if not v then
|
||||
neo.emergency("failed start:", steps[w])
|
||||
neo.emergency(steps[w] .. " STF")
|
||||
neo.emergency(err)
|
||||
table.insert(warnings, steps[w] .. " STF")
|
||||
table.insert(warnings, err)
|
||||
end
|
||||
end
|
||||
else
|
||||
@ -430,10 +437,12 @@ end
|
||||
-- System initialized
|
||||
if finalPrompt() then
|
||||
-- Safe Mode
|
||||
local gpu = gpuG()
|
||||
rstfbDraw(gpu)
|
||||
basicDraw(gpu)
|
||||
local nsm = neo.requestAccess("x.neo.sys.manage")
|
||||
if nsm then
|
||||
console = {"Rebooting for Safe Mode..."}
|
||||
basicDraw()
|
||||
pcall(gpu.set, 2, 4, "Rebooting for Safe Mode...")
|
||||
for _, v in ipairs(nsm.listSettings()) do
|
||||
if v ~= "password" then
|
||||
nsm.delSetting(v)
|
||||
@ -441,14 +450,12 @@ if finalPrompt() then
|
||||
end
|
||||
else
|
||||
-- assume sysconf.lua did something very bad
|
||||
console = {"No NSM. Wiping configuration completely."}
|
||||
pcall(gpu.set, 2, 4, "No NSM. Wiping configuration completely.")
|
||||
local fs = neo.requestAccess("c.filesystem")
|
||||
if not fs then
|
||||
table.insert(console, "Failed to get permission, you're doomed.")
|
||||
else
|
||||
fs.primary.remove("/data/sys-glacier/sysconf.lua")
|
||||
pcall(gpu.set, 2, 4, "Failed to get permission, you're doomed.")
|
||||
end
|
||||
basicDraw()
|
||||
fs.primary.remove("/data/sys-glacier/sysconf.lua")
|
||||
end
|
||||
-- Do not give anything a chance to alter the new configuration
|
||||
shutdownEmergency(true)
|
||||
|
@ -1,14 +1,9 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
return {
|
||||
["neo"] = {
|
||||
desc = "KittenOS NEO Kernel & Base Libs",
|
||||
v = 10,
|
||||
v = 4,
|
||||
deps = {
|
||||
},
|
||||
dirs = {
|
||||
@ -23,7 +18,6 @@ return {
|
||||
"libs/serial.lua",
|
||||
"libs/fmttext.lua",
|
||||
"libs/neoux.lua",
|
||||
"libs/lineedit.lua",
|
||||
"libs/braille.lua",
|
||||
"libs/bmp.lua",
|
||||
"libs/sys-filewrap.lua",
|
||||
@ -32,7 +26,7 @@ return {
|
||||
},
|
||||
["neo-init"] = {
|
||||
desc = "KittenOS NEO / sys-init (startup)",
|
||||
v = 11,
|
||||
v = 2,
|
||||
deps = {
|
||||
"neo",
|
||||
"neo-icecap",
|
||||
@ -47,7 +41,7 @@ return {
|
||||
},
|
||||
["neo-launcher"] = {
|
||||
desc = "KittenOS NEO / Default app-launcher",
|
||||
v = 10,
|
||||
v = 2,
|
||||
deps = {
|
||||
"neo"
|
||||
},
|
||||
@ -60,7 +54,7 @@ return {
|
||||
},
|
||||
["neo-everest"] = {
|
||||
desc = "KittenOS NEO / Everest (windowing)",
|
||||
v = 10,
|
||||
v = 3,
|
||||
deps = {
|
||||
"neo"
|
||||
},
|
||||
@ -73,7 +67,7 @@ return {
|
||||
},
|
||||
["neo-icecap"] = {
|
||||
desc = "KittenOS NEO / Icecap",
|
||||
v = 10,
|
||||
v = 3,
|
||||
deps = {
|
||||
"neo"
|
||||
},
|
||||
@ -90,7 +84,7 @@ return {
|
||||
},
|
||||
["neo-secpolicy"] = {
|
||||
desc = "KittenOS NEO / Secpolicy",
|
||||
v = 10,
|
||||
v = 2,
|
||||
deps = {
|
||||
},
|
||||
dirs = {
|
||||
@ -102,7 +96,7 @@ return {
|
||||
},
|
||||
["neo-coreapps"] = {
|
||||
desc = "KittenOS NEO Core Apps",
|
||||
v = 10,
|
||||
v = 2,
|
||||
deps = {
|
||||
"neo"
|
||||
},
|
||||
@ -111,39 +105,40 @@ return {
|
||||
},
|
||||
files = {
|
||||
"apps/app-textedit.lua",
|
||||
"apps/app-batmon.lua",
|
||||
"apps/app-control.lua",
|
||||
"apps/app-taskmgr.lua"
|
||||
}
|
||||
},
|
||||
["app-bmpview"] = {
|
||||
desc = "KittenOS NEO .bmp viewer",
|
||||
v = 10,
|
||||
["app-klogo"] = {
|
||||
desc = "KittenOS NEO Logo shower",
|
||||
v = 2,
|
||||
deps = {
|
||||
"neo",
|
||||
"app-klogo-logo"
|
||||
},
|
||||
dirs = {
|
||||
"apps"
|
||||
},
|
||||
files = {
|
||||
"apps/app-bmpview.lua",
|
||||
"apps/app-klogo.lua",
|
||||
},
|
||||
},
|
||||
["neo-logo"] = {
|
||||
["app-klogo-logo"] = {
|
||||
desc = "KittenOS NEO Logo (data)",
|
||||
v = 10,
|
||||
v = 4,
|
||||
deps = {
|
||||
},
|
||||
dirs = {
|
||||
"docs"
|
||||
"data",
|
||||
"data/app-klogo"
|
||||
},
|
||||
files = {
|
||||
"docs/logo.bmp"
|
||||
"data/app-klogo/logo.bmp"
|
||||
},
|
||||
},
|
||||
["app-flash"] = {
|
||||
desc = "KittenOS NEO EEPROM Flasher",
|
||||
v = 10,
|
||||
v = 2,
|
||||
deps = {
|
||||
"neo"
|
||||
},
|
||||
@ -156,7 +151,7 @@ return {
|
||||
},
|
||||
["app-wget"] = {
|
||||
desc = "KittenOS Web Retriever",
|
||||
v = 10,
|
||||
v = 2,
|
||||
deps = {
|
||||
"neo"
|
||||
},
|
||||
@ -169,35 +164,23 @@ return {
|
||||
},
|
||||
["app-claw"] = {
|
||||
desc = "KittenOS NEO Package Manager",
|
||||
v = 10,
|
||||
v = 2,
|
||||
deps = {
|
||||
"neo"
|
||||
},
|
||||
dirs = {
|
||||
"apps"
|
||||
"apps",
|
||||
"libs"
|
||||
},
|
||||
files = {
|
||||
"apps/app-claw.lua",
|
||||
"apps/svc-app-claw-worker.lua"
|
||||
},
|
||||
},
|
||||
["svc-t"] = {
|
||||
desc = "KittenOS NEO Terminal System",
|
||||
v = 10,
|
||||
deps = {
|
||||
"neo"
|
||||
},
|
||||
dirs = {
|
||||
"apps"
|
||||
},
|
||||
files = {
|
||||
"apps/svc-t.lua",
|
||||
"apps/app-luashell.lua"
|
||||
"libs/app-claw-core.lua",
|
||||
"libs/app-claw-csi.lua"
|
||||
},
|
||||
},
|
||||
["neo-meta"] = {
|
||||
desc = "KittenOS NEO: Use 'All' to install to other disks",
|
||||
v = 10,
|
||||
v = 2,
|
||||
deps = {
|
||||
"neo",
|
||||
"neo-init",
|
||||
@ -206,11 +189,9 @@ return {
|
||||
"neo-icecap",
|
||||
"neo-secpolicy",
|
||||
"neo-coreapps",
|
||||
"neo-logo",
|
||||
"app-bmpview",
|
||||
"app-klogo",
|
||||
"app-flash",
|
||||
"app-claw",
|
||||
"svc-t",
|
||||
"app-wget"
|
||||
},
|
||||
dirs = {
|
Binary file not shown.
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
@ -1,10 +1,6 @@
|
||||
-- KittenOS N.E.O Kernel: "Tell Mettaton I said hi."
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- NOTE: local is considered unnecessary in kernel since 21 March
|
||||
|
||||
@ -463,7 +459,7 @@ function retrieveAccess(perm, pkg, pid)
|
||||
accesses[uid] = function (pkg, pid)
|
||||
return nil
|
||||
end
|
||||
return function (f, secret)
|
||||
return function (f)
|
||||
-- Registration function
|
||||
ensureType(f, "function")
|
||||
local accessObjectCache = {}
|
||||
@ -485,10 +481,8 @@ function retrieveAccess(perm, pkg, pid)
|
||||
end
|
||||
-- returns nil and fails
|
||||
end
|
||||
if not secret then
|
||||
-- Announce registration
|
||||
distEvent(nil, "k.registration", uid)
|
||||
end
|
||||
end, function ()
|
||||
-- Registration becomes null (access is held but other processes cannot retrieve object)
|
||||
if accesses[uid] then
|
||||
|
254
code/libs/app-claw-core.lua
Normal file
254
code/libs/app-claw-core.lua
Normal file
@ -0,0 +1,254 @@
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- app-claw-core: assistant to app-claw
|
||||
-- should only ever be one app-claw at a time
|
||||
-- USING THIS LIBRARY OUTSIDE OF APP-CLAW IS A BAD IDEA.
|
||||
-- SO DON'T DO IT.
|
||||
|
||||
-- Also serves to provide a mutex.
|
||||
|
||||
local lock = false
|
||||
|
||||
return function ()
|
||||
if lock then
|
||||
error("libclaw safety lock in use")
|
||||
end
|
||||
lock = true
|
||||
local sourceList = {}
|
||||
local sources = {}
|
||||
-- 1 2 3 4 5 6
|
||||
-- source ents: src dst index
|
||||
-- dst entries: writeFile(fn), mkdir(fn), exists(fn), isDirectory(fn), remove(fn), rename(fna, fnb)
|
||||
-- writeFile(fn) -> function (data/nil to close)
|
||||
local function saveInfo(dn)
|
||||
sources[dn][2][2]("data")
|
||||
sources[dn][2][2]("data/app-claw")
|
||||
local cb, _, r = sources[dn][2][1]("data/app-claw/local.lua")
|
||||
if not cb then return false, r end
|
||||
_, r = cb(require("serial").serialize(sources[dn][3]))
|
||||
if not _ then return false, r end
|
||||
_, r = cb(nil)
|
||||
if not _ then return false, r end
|
||||
return true
|
||||
end
|
||||
local remove, installTo, expandCSI, compressCSI
|
||||
local function expandS(v)
|
||||
return v:sub(2, v:byte(1) + 1), v:sub(v:byte(1) + 2)
|
||||
end
|
||||
local function expandT(v)
|
||||
local t = {}
|
||||
local n = v:byte(1)
|
||||
v = v:sub(2)
|
||||
for i = 1, n do
|
||||
t[i], v = expandS(v)
|
||||
end
|
||||
return t, v
|
||||
end
|
||||
local function compressT(x)
|
||||
local b = string.char(#x)
|
||||
for _, v in ipairs(x) do
|
||||
b = b .. string.char(#v) .. v
|
||||
end
|
||||
return b
|
||||
end
|
||||
local function expandCSI(v)
|
||||
local t = {}
|
||||
local k
|
||||
k, v = expandS(v)
|
||||
t.desc, v = expandS(v)
|
||||
t.v = (v:byte(1) * 256) + v:byte(2)
|
||||
v = v:sub(3)
|
||||
t.dirs, v = expandT(v)
|
||||
t.files, v = expandT(v)
|
||||
t.deps, v = expandT(v)
|
||||
return k, t, v
|
||||
end
|
||||
local function compressCSI(k, v)
|
||||
local nifo = string.char(#k) .. k
|
||||
nifo = nifo .. string.char(math.min(255, #v.desc)) .. v.desc:sub(1, 255)
|
||||
nifo = nifo .. string.char(math.floor(v.v / 256), v.v % 256)
|
||||
nifo = nifo .. compressT(v.dirs)
|
||||
nifo = nifo .. compressT(v.files)
|
||||
nifo = nifo .. compressT(v.deps)
|
||||
return nifo
|
||||
end
|
||||
local function findPkg(idx, pkg, del)
|
||||
del = del and ""
|
||||
idx = sources[idx][3]
|
||||
while #idx > 0 do
|
||||
local k, d
|
||||
k, d, idx = expandCSI(idx)
|
||||
if del then
|
||||
if k == pkg then
|
||||
return d, del .. idx
|
||||
end
|
||||
del = del .. compressCSI(k, d)
|
||||
else
|
||||
if k == pkg then return d end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- NOTE: Functions in this must return something due to the checked-call wrapper,
|
||||
-- but should all use error() for consistency.
|
||||
-- Operations
|
||||
installTo = function (dstName, pkg, srcName, checked, yielder)
|
||||
local errs = {}
|
||||
if srcName == dstName then
|
||||
error("Invalid API use")
|
||||
end
|
||||
-- preliminary checks
|
||||
local srcPkg = findPkg(srcName, pkg, false)
|
||||
assert(srcPkg)
|
||||
if checked then
|
||||
for _, v in ipairs(srcPkg.deps) do
|
||||
if not findPkg(dstName, v) then
|
||||
if not findPkg(srcName, v) then
|
||||
table.insert(errs, pkg .. " depends on " .. v .. "\n")
|
||||
elseif #errs == 0 then
|
||||
installTo(dstName, v, srcName, checked, yielder)
|
||||
else
|
||||
table.insert(errs, pkg .. " depends on " .. v .. " (can autoinstall)\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Files from previous versions to get rid of
|
||||
local ignFiles = {}
|
||||
local oldDst = findPkg(dstName, pkg)
|
||||
if oldDst then
|
||||
for _, v in ipairs(oldDst.files) do
|
||||
ignFiles[v] = true
|
||||
end
|
||||
end
|
||||
oldDst = nil
|
||||
for _, v in ipairs(srcPkg.files) do
|
||||
if not ignFiles[v] then
|
||||
if sources[dstName][2][3](v) then
|
||||
table.insert(errs, v .. " already exists (corrupt system?)")
|
||||
end
|
||||
end
|
||||
end
|
||||
if #errs > 0 then
|
||||
error(table.concat(errs))
|
||||
end
|
||||
for _, v in ipairs(srcPkg.dirs) do
|
||||
sources[dstName][2][2](v)
|
||||
if not sources[dstName][2][4](v) then
|
||||
error("Unable to create directory " .. v)
|
||||
end
|
||||
end
|
||||
for _, v in ipairs(srcPkg.files) do
|
||||
local tmpOut, r, ok = sources[dstName][2][1](v .. ".claw-tmp")
|
||||
ok = tmpOut
|
||||
if ok then
|
||||
ok, r = sources[srcName][1](v, tmpOut)
|
||||
end
|
||||
if ok then
|
||||
yielder()
|
||||
else
|
||||
-- Cleanup...
|
||||
for _, v in ipairs(srcPkg.files) do
|
||||
sources[dstName][2][5](v .. ".claw-tmp")
|
||||
end
|
||||
error(r)
|
||||
end
|
||||
end
|
||||
-- PAST THIS POINT, ERRORS CORRUPT!
|
||||
-- Remove package from DB
|
||||
local oldDst2, oldDst3 = findPkg(dstName, pkg, true)
|
||||
sources[dstName][3] = oldDst3 or sources[dstName][3]
|
||||
oldDst2, oldDst3 = nil
|
||||
saveInfo(dstName)
|
||||
-- Delete old files
|
||||
for k, _ in pairs(ignFiles) do
|
||||
yielder()
|
||||
sources[dstName][2][5](k)
|
||||
end
|
||||
-- Create new files
|
||||
for _, v in ipairs(srcPkg.files) do
|
||||
yielder()
|
||||
sources[dstName][2][6](v .. ".claw-tmp", v)
|
||||
end
|
||||
-- Insert into DB
|
||||
sources[dstName][3] = sources[dstName][3] .. compressCSI(pkg, srcPkg)
|
||||
saveInfo(dstName)
|
||||
return true
|
||||
end
|
||||
remove = function (dstName, pkg, checked)
|
||||
if checked then
|
||||
local errs = {}
|
||||
local buf = sources[dstName][3]
|
||||
while #buf > 0 do
|
||||
local dpsName, dpsV
|
||||
dpsName, dpsV, buf = expandCSI(buf)
|
||||
for _, v in ipairs(dpsV.deps) do
|
||||
if v == pkg then
|
||||
table.insert(errs, dpsName .. " depends on " .. pkg .. "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
if #errs > 0 then
|
||||
return nil, table.concat(errs)
|
||||
end
|
||||
end
|
||||
local dstPkg, nbuf = findPkg(dstName, pkg, true)
|
||||
assert(dstPkg, "Package wasn't installed")
|
||||
for _, v in ipairs(dstPkg.files) do
|
||||
sources[dstName][2][5](v)
|
||||
end
|
||||
sources[dstName][3] = nbuf
|
||||
saveInfo(dstName)
|
||||
return true
|
||||
end
|
||||
return {
|
||||
-- Gets the latest info, or if given a source just gives that source's info.
|
||||
-- Do not modify output.
|
||||
getInfo = function (pkg, source, oldest)
|
||||
if source then return findPkg(source, pkg) end
|
||||
local bestI = {
|
||||
v = -1,
|
||||
desc = "An unknown package.",
|
||||
deps = {}
|
||||
}
|
||||
if oldest then bestI.v = 10000 end
|
||||
for k, v in pairs(sources) do
|
||||
local pkgv = findPkg(k, pkg)
|
||||
if pkgv then
|
||||
if ((not oldest) and (pkgv.v > bestI.v)) or (oldest and (pkgv.v > bestI.v)) then
|
||||
bestI = pkgv
|
||||
end
|
||||
end
|
||||
end
|
||||
return bestI
|
||||
end,
|
||||
sources = sources,
|
||||
sourceList = sourceList,
|
||||
remove = remove,
|
||||
installTo = installTo,
|
||||
expandCSI = expandCSI,
|
||||
compressCSI = compressCSI,
|
||||
|
||||
-- Gets a total list of packages, as a table of strings. You can modify output.
|
||||
getList = function ()
|
||||
local n = {}
|
||||
local seen = {}
|
||||
for k, v in pairs(sources) do
|
||||
local p3 = v[3]
|
||||
while #p3 > 0 do
|
||||
local kb, _, nx = expandCSI(p3)
|
||||
p3 = nx
|
||||
if not seen[kb] then
|
||||
seen[kb] = true
|
||||
table.insert(n, kb)
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(n)
|
||||
return n
|
||||
end,
|
||||
unlock = function ()
|
||||
lock = false
|
||||
end
|
||||
}
|
||||
end
|
28
code/libs/app-claw-csi.lua
Normal file
28
code/libs/app-claw-csi.lua
Normal file
@ -0,0 +1,28 @@
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- app-claw-csi: addSource function
|
||||
-- USING THIS LIBRARY OUTSIDE OF APP-CLAW IS A BAD IDEA.
|
||||
-- SO DON'T DO IT.
|
||||
|
||||
-- NOTE: If a source is writable, it's added anyway despite any problems.
|
||||
return function (claw, name, src, dst)
|
||||
local ifo = ""
|
||||
local ifok, e = src("data/app-claw/local.lua", function (t)
|
||||
ifo = ifo .. (t or "")
|
||||
return true
|
||||
end)
|
||||
e = e or "local.lua parse error"
|
||||
ifo = ifok and require("serial").deserialize(ifo)
|
||||
if not (dst or ifo) then return false, e end
|
||||
table.insert(claw.sourceList, {name, not not dst})
|
||||
local nifo = ifo or ""
|
||||
if type(nifo) == "table" then
|
||||
nifo = ""
|
||||
for k, v in pairs(ifo) do
|
||||
nifo = nifo .. claw.compressCSI(k, v)
|
||||
end
|
||||
end
|
||||
claw.sources[name] = {src, dst, nifo}
|
||||
return not not ifo, e
|
||||
end
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- bmp: Portable OC BMP/DIB library
|
||||
-- Flexible: Reading can be set to
|
||||
@ -157,8 +153,20 @@ return {
|
||||
local planes = get16(0x1A)
|
||||
local bpp = get16(0x1C)
|
||||
local compression = get32(0x1E)
|
||||
local paletteCol = get32(0x2E)
|
||||
local paletteCol = 0
|
||||
local other = get32(0x2E)
|
||||
paletteCol = other
|
||||
-- postprocess
|
||||
|
||||
-- The actual values used for addressing, for cMode to mess with
|
||||
local basePtr = 14 + hdrSize + (paletteCol * 4)
|
||||
local scanWB = math.ceil((bpp * width) / 32) * 4
|
||||
local monoWB = (math.ceil((bpp * width) / 32) * 4)
|
||||
local planeWB = scanWB * height
|
||||
|
||||
if not packed then
|
||||
basePtr = get32(0x0A) -- 'BM' header
|
||||
end
|
||||
-- negative height means sane coords
|
||||
local upDown = true
|
||||
if height >= 0x80000000 then
|
||||
@ -167,18 +175,6 @@ return {
|
||||
upDown = false
|
||||
end
|
||||
|
||||
-- postprocess
|
||||
|
||||
-- The actual values used for addressing, for cMode to mess with
|
||||
local basePtr = 14 + hdrSize + (paletteCol * 4)
|
||||
local scanWB = math.ceil((bpp * width) / 32) * 4
|
||||
local monoWB = math.ceil(width / 32) * 4
|
||||
local planeWB = scanWB * height
|
||||
|
||||
if not packed then
|
||||
basePtr = get32(0x0A) -- 'BM' header
|
||||
end
|
||||
|
||||
-- Cursor/Icon
|
||||
if cMode then
|
||||
height = math.floor(height / 2)
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- Braille Converter & NeoUX component
|
||||
-- While the Neoux part isn't OS-independent,
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- event: Implements pull/listen semantics in a consistent way for a given process.
|
||||
-- This is similar in API to OpenOS's event framework, but is per-process.
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
local fmt
|
||||
fmt = {
|
||||
|
@ -1,77 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
return {
|
||||
-- note: everything must already be unicode.safeTextFormat'd
|
||||
draw = function (sW, line, cursorX, rX)
|
||||
-- if no camera, provide a default
|
||||
rX = rX or math.max(1, (cursorX or 1) - math.floor(sW * 2 / 3))
|
||||
-- transform into area-relative
|
||||
local tl = unicode.sub(line, rX, rX + sW - 1)
|
||||
-- inject cursor
|
||||
if cursorX then
|
||||
cursorX = (cursorX - rX) + 1
|
||||
if cursorX >= 1 then
|
||||
if cursorX <= sW then
|
||||
tl = unicode.sub(tl, 1, cursorX - 1) .. "_" .. unicode.sub(tl, cursorX + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
return tl .. (" "):rep(sW - unicode.len(tl))
|
||||
end,
|
||||
clamp = function (tl, cursorX)
|
||||
tl = unicode.len(tl)
|
||||
if tl < cursorX - 1 then
|
||||
return tl + 1
|
||||
end
|
||||
return cursorX
|
||||
end,
|
||||
-- returns line, cursorX, special
|
||||
-- return values may be nil if irrelevant
|
||||
key = function (ks, kc, line, cursorX)
|
||||
local cS = unicode.sub(line, 1, cursorX - 1)
|
||||
local cE = unicode.sub(line, cursorX)
|
||||
local ll = unicode.len(line)
|
||||
if kc == 203 then -- navi <
|
||||
if cursorX > 1 then
|
||||
return nil, cursorX - 1
|
||||
else
|
||||
-- cline underflow
|
||||
return nil, nil, "l<"
|
||||
end
|
||||
elseif kc == 205 then -- navi >
|
||||
if cursorX > ll then
|
||||
-- cline overflow
|
||||
return nil, nil, "l>"
|
||||
end
|
||||
return nil, cursorX + 1
|
||||
elseif kc == 199 then -- home
|
||||
return nil, 1
|
||||
elseif kc == 207 then -- end
|
||||
return nil, unicode.len(line) + 1
|
||||
elseif ks == "\8" then -- del
|
||||
if cursorX == 1 then
|
||||
-- weld prev
|
||||
return nil, nil, "w<"
|
||||
else
|
||||
return unicode.sub(cS, 1, unicode.len(cS) - 1) .. cE, cursorX - 1
|
||||
end
|
||||
elseif kc == 211 then -- del
|
||||
if cursorX > ll then
|
||||
return nil, nil, "w>"
|
||||
end
|
||||
return cS .. unicode.sub(cE, 2)
|
||||
elseif ks then -- standard letters
|
||||
if ks == "\r" then
|
||||
-- new line
|
||||
return nil, nil, "nl"
|
||||
end
|
||||
return cS .. ks .. cE, cursorX + unicode.len(ks)
|
||||
end
|
||||
-- :(
|
||||
end
|
||||
}
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- neoux: Implements utilities on top of Everest & event:
|
||||
-- Everest crash protection
|
||||
@ -29,7 +25,7 @@ newNeoux = function (event, neo)
|
||||
end
|
||||
end)
|
||||
local neoux = {}
|
||||
neoux.fileDialog = function (forWrite, callback, dfn)
|
||||
neoux.fileDialog = function (forWrite, callback)
|
||||
local sync = false
|
||||
local rtt = nil
|
||||
if not callback then
|
||||
@ -39,7 +35,7 @@ newNeoux = function (event, neo)
|
||||
rtt = rt
|
||||
end
|
||||
end
|
||||
local tag = neo.requireAccess("x.neo.pub.base", "filedialog").showFileDialogAsync(forWrite, dfn)
|
||||
local tag = neo.requireAccess("x.neo.pub.base", "filedialog").showFileDialogAsync(forWrite)
|
||||
local f
|
||||
f = function (_, fd, tg, re)
|
||||
if fd == "filedialog" then
|
||||
@ -343,8 +339,6 @@ newNeoux = function (event, neo)
|
||||
end
|
||||
-- Note: w should be at least 2 - this is similar to buttons.
|
||||
neoux.tcfield = function (x, y, w, textprop)
|
||||
-- compat. workaround for apps which nuke tcfields
|
||||
local p = unicode.len(textprop()) + 1
|
||||
return {
|
||||
x = x,
|
||||
y = y,
|
||||
@ -353,24 +347,22 @@ newNeoux = function (event, neo)
|
||||
selectable = true,
|
||||
key = function (window, update, a, c, d, f)
|
||||
if d then
|
||||
local ot = textprop()
|
||||
local le = require("lineedit")
|
||||
p = le.clamp(ot, p)
|
||||
if c == 63 then
|
||||
neo.requireAccess("x.neo.pub.globals", "clipboard").setSetting("clipboard", ot)
|
||||
neo.requireAccess("x.neo.pub.globals", "clipboard").setSetting("clipboard", textprop())
|
||||
elseif c == 64 then
|
||||
local contents = neo.requireAccess("x.neo.pub.globals", "clipboard").getSetting("clipboard")
|
||||
contents = contents:match("^[^\r\n]*")
|
||||
textprop(contents)
|
||||
update()
|
||||
elseif a ~= 9 then
|
||||
local lT, lC, lX = le.key(a ~= 0 and unicode.char(a), c, ot, p)
|
||||
if lT or lC then
|
||||
if lT then textprop(lT) end
|
||||
p = lC or p
|
||||
elseif a == 8 then
|
||||
local str = textprop()
|
||||
textprop(unicode.sub(str, 1, unicode.len(str) - 1))
|
||||
update()
|
||||
return true
|
||||
elseif a >= 32 then
|
||||
textprop(textprop() .. unicode.char(a))
|
||||
update()
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
@ -385,10 +377,9 @@ newNeoux = function (event, neo)
|
||||
fg = bg
|
||||
bg = fg1
|
||||
end
|
||||
local t, e, r = textprop(), require("lineedit")
|
||||
p = e.clamp(t, p)
|
||||
t, r = unicode.safeTextFormat(t, p)
|
||||
window.span(x, y, "[" .. e.draw(w - 2, t, selected and r) .. "]", bg, fg)
|
||||
local text = unicode.safeTextFormat(textprop())
|
||||
text = "[" .. neoux.pad(text, w - 2, false, true, true) .. "]"
|
||||
window.span(x, y, text, bg, fg)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
@ -1,10 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
local doSerialize = nil
|
||||
function doSerialize(s)
|
||||
if type(s) == "table" then
|
||||
|
@ -1,12 +1,8 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- just don't bother with proper indent here
|
||||
return function (event, nexus, retFunc, fs, pkg, mode, defName)
|
||||
return function (event, nexus, retFunc, fs, pkg, mode)
|
||||
|
||||
local fmt = require("fmttext")
|
||||
local class = "manage"
|
||||
@ -145,7 +141,7 @@ end
|
||||
nexus.create(w, h, class .. " " .. pkg, function (w, ev, a, b, c)
|
||||
if not wnd then
|
||||
wnd = w
|
||||
prepareNode(require("sys-filevfs")(fs, mode, defName))
|
||||
prepareNode(require("sys-filevfs")(fs, mode))
|
||||
end
|
||||
if ev == "key" then
|
||||
key2(a, b, c)
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- Used by filedialog to provide a sane relative environment.
|
||||
-- Essentially, the filedialog is just a 'thin' UI wrapper over this.
|
||||
@ -20,12 +16,12 @@ end
|
||||
|
||||
local getFsNode, getRoot
|
||||
local setupCopyNode
|
||||
function setupCopyNode(parent, myRoot, op, complete)
|
||||
function setupCopyNode(parent, myRoot, op, complete, impliedName)
|
||||
local function handleResult(aRes, res)
|
||||
if aRes then
|
||||
return complete(res, true)
|
||||
else
|
||||
return nil, setupCopyNode(parent, res, op, complete)
|
||||
return nil, setupCopyNode(parent, res, op, complete, impliedName)
|
||||
end
|
||||
end
|
||||
return {
|
||||
@ -36,6 +32,11 @@ function setupCopyNode(parent, myRoot, op, complete)
|
||||
complete(nil, false)
|
||||
return false, parent
|
||||
end})
|
||||
if impliedName and myRoot.unknownAvailable then
|
||||
table.insert(l, {"Implied: " .. impliedName, function ()
|
||||
return handleResult(myRoot.selectUnknown(impliedName))
|
||||
end})
|
||||
end
|
||||
for _, v in ipairs(myRoot.list()) do
|
||||
table.insert(l, {v[1], function ()
|
||||
return handleResult(v[2]())
|
||||
@ -53,7 +54,7 @@ local function setupCopyVirtualEnvironment(fs, parent, fwrap, impliedName)
|
||||
if not fwrap then
|
||||
return false, dialog("Could not open source", parent)
|
||||
end
|
||||
local myRoot = getRoot(fs, true, impliedName)
|
||||
local myRoot = getRoot(fs, true)
|
||||
-- Setup wrapping node
|
||||
return setupCopyNode(parent, myRoot, "Copy", function (fwrap2, intent)
|
||||
if not fwrap2 then
|
||||
@ -71,22 +72,14 @@ local function setupCopyVirtualEnvironment(fs, parent, fwrap, impliedName)
|
||||
fwrap.close()
|
||||
fwrap2.close()
|
||||
return false, dialog("Completed copy.", parent)
|
||||
end)
|
||||
end, impliedName)
|
||||
end
|
||||
function getFsNode(fs, parent, fsc, path, mode, impliedName)
|
||||
function getFsNode(fs, parent, fsc, path, mode)
|
||||
local va = fsc.address:sub(1, 4)
|
||||
local fscrw = not fsc.isReadOnly()
|
||||
local dir = path:sub(#path, #path) == "/"
|
||||
local confirmedDel = false
|
||||
local t
|
||||
local function selectUnknown(text)
|
||||
-- Relies on text being nil if used in leaf node
|
||||
local rt, re = require("sys-filewrap").create(fsc, path .. (text or ""), mode)
|
||||
if not rt then
|
||||
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||
end
|
||||
return true, rt
|
||||
end
|
||||
t = {
|
||||
name = ((dir and "DIR: ") or "FILE: ") .. va .. path,
|
||||
list = function ()
|
||||
@ -98,26 +91,12 @@ function getFsNode(fs, parent, fsc, path, mode, impliedName)
|
||||
for k, v in ipairs(fsc.list(path)) do
|
||||
local nm = "F: " .. v
|
||||
local fp = path .. v
|
||||
local cDir = fsc.isDirectory(fp)
|
||||
if cDir then
|
||||
if fsc.isDirectory(fp) then
|
||||
nm = "D: " .. v
|
||||
end
|
||||
if (not cDir) and (fscrw or mode == false) and (mode ~= nil) then
|
||||
local vn = v
|
||||
n[k + 1] = {nm, function () return selectUnknown(vn) end}
|
||||
else
|
||||
n[k + 1] = {nm, function () return nil, getFsNode(fs, t, fsc, fp, mode, impliedName) end}
|
||||
n[k + 1] = {nm, function () return nil, getFsNode(fs, t, fsc, fp, mode) end}
|
||||
end
|
||||
end
|
||||
else
|
||||
table.insert(n, {"Copy", function ()
|
||||
local rt, re = require("sys-filewrap").create(fsc, path, false)
|
||||
if not rt then
|
||||
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||
end
|
||||
return nil, setupCopyVirtualEnvironment(fs, parent, rt, path:match("[^/]*$") or "")
|
||||
end})
|
||||
end
|
||||
if fscrw then
|
||||
if dir then
|
||||
table.insert(n, {"Mk. Directory", function ()
|
||||
@ -135,6 +114,31 @@ function getFsNode(fs, parent, fsc, path, mode, impliedName)
|
||||
end
|
||||
}
|
||||
end})
|
||||
else
|
||||
if mode ~= nil then
|
||||
local tx = "Open"
|
||||
if mode == true then
|
||||
tx = "Save"
|
||||
elseif mode == "append" then
|
||||
tx = "Append"
|
||||
end
|
||||
if fscrw or mode == false then
|
||||
table.insert(n, {tx, function ()
|
||||
local rt, re = require("sys-filewrap").create(fsc, path, mode)
|
||||
if not rt then
|
||||
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||
end
|
||||
return true, rt
|
||||
end})
|
||||
end
|
||||
end
|
||||
table.insert(n, {"Copy", function ()
|
||||
local rt, re = require("sys-filewrap").create(fsc, path, false)
|
||||
if not rt then
|
||||
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||
end
|
||||
return nil, setupCopyVirtualEnvironment(fs, parent, rt, path:match("[^/]*$") or "")
|
||||
end})
|
||||
end
|
||||
if path ~= "/" then
|
||||
local delText = "Delete"
|
||||
@ -168,20 +172,20 @@ function getFsNode(fs, parent, fsc, path, mode, impliedName)
|
||||
end})
|
||||
end
|
||||
end
|
||||
if not dir then
|
||||
elseif impliedName then
|
||||
table.insert(n, {"Implied: " .. impliedName, function ()
|
||||
return selectUnknown(impliedName)
|
||||
end})
|
||||
end
|
||||
return n
|
||||
end,
|
||||
unknownAvailable = dir and (mode ~= nil) and ((mode == false) or fscrw),
|
||||
selectUnknown = selectUnknown
|
||||
selectUnknown = function (text)
|
||||
local rt, re = require("sys-filewrap").create(fsc, path .. text, mode)
|
||||
if not rt then
|
||||
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||
end
|
||||
return true, rt
|
||||
end
|
||||
}
|
||||
return t
|
||||
end
|
||||
function getRoot(fs, mode, defName)
|
||||
function getRoot(fs, mode)
|
||||
local t
|
||||
t = {
|
||||
name = "DRVS:",
|
||||
@ -205,7 +209,7 @@ function getRoot(fs, mode, defName)
|
||||
id = "RW " .. amount .. "% " .. mb .. "M " .. id
|
||||
end
|
||||
table.insert(l, {fsi.address:sub(1, 4) .. " " .. id, function ()
|
||||
return nil, getFsNode(fs, t, fsi, "/", mode, defName)
|
||||
return nil, getFsNode(fs, t, fsi, "/", mode)
|
||||
end})
|
||||
end
|
||||
return l
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
local function ensureMode(mode)
|
||||
local n = "rb"
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
return function (
|
||||
gpus, screens,
|
||||
@ -99,7 +95,7 @@ return function (
|
||||
return v, didBind
|
||||
end
|
||||
end
|
||||
end, monitor
|
||||
end, v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,9 +1,5 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- CRITICAL FILE!
|
||||
-- This file defines how your KittenOS NEO system responds to access requests.
|
||||
@ -15,28 +11,21 @@
|
||||
-- IRC is usually pretty safe, but no guarantees.
|
||||
|
||||
-- Returns "allow", "deny", or "ask".
|
||||
local function actualPolicy(pkg, pid, perm, pkgSvcPfx)
|
||||
local function actualPolicy(pkg, pid, perm, matchesSvc)
|
||||
-- System stuff is allowed.
|
||||
if pkg:sub(1, 4) == "sys-" then
|
||||
return "allow"
|
||||
end
|
||||
-- svc-t's job is solely to emulate terminals
|
||||
-- TO INSTALL YOUR OWN TERMINAL EMULATOR:
|
||||
-- perm|app-yourterm|r.neo.t
|
||||
if pkg == "svc-t" and perm == "r.neo.pub.t" then
|
||||
return "allow"
|
||||
end
|
||||
-- <The following is for apps & services>
|
||||
-- x.neo.pub.* is open to all
|
||||
-- x.neo.pub (aka Icecap) is open to all
|
||||
if perm:sub(1, 10) == "x.neo.pub." then
|
||||
return "allow"
|
||||
end
|
||||
-- These signals are harmless, though they identify HW (as does everything in OC...)
|
||||
if perm == "s.h.component_added" or perm == "s.h.component_removed" or perm == "s.h.tablet_use" or perm == "c.tablet" then
|
||||
if perm == "s.h.component_added" or perm == "s.h.component_removed" then
|
||||
return "allow"
|
||||
end
|
||||
-- Userlevel can register for itself
|
||||
if perm == "r." .. pkgSvcPfx then
|
||||
if matchesSvc("r.", pkg, perm) then
|
||||
return "allow"
|
||||
end
|
||||
-- Userlevel has no other registration rights
|
||||
@ -55,8 +44,8 @@ local function actualPolicy(pkg, pid, perm, pkgSvcPfx)
|
||||
return "ask"
|
||||
end
|
||||
|
||||
return function (nexus, settings, pkg, pid, perm, rsp, pkgSvcPfx)
|
||||
local res = actualPolicy(pkg, pid, perm, pkgSvcPfx)
|
||||
return function (nexus, settings, pkg, pid, perm, rsp, matchesSvc)
|
||||
local res = actualPolicy(pkg, pid, perm, matchesSvc)
|
||||
if settings then
|
||||
res = settings.getSetting("perm|" .. pkg .. "|" .. perm) or
|
||||
settings.getSetting("perm|*|" .. perm) or res
|
||||
|
61
com2/bdivide.lua
Normal file
61
com2/bdivide.lua
Normal file
@ -0,0 +1,61 @@
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- BDIVIDE
|
||||
-- format:
|
||||
-- 0-127 for constants
|
||||
-- <block + 128>, <(len - 3) * 2, + lowest bit is upper bit of position>, <position - 1>
|
||||
|
||||
io.write("\x00") -- initiation character
|
||||
|
||||
local blockCache = {}
|
||||
local window = 0
|
||||
local blockUse = 128
|
||||
for i = 128, 128 + blockUse - 1 do
|
||||
blockCache[i] = ("\x00"):rep(512)
|
||||
end
|
||||
|
||||
local function runBlock(blk)
|
||||
-- firstly, get current block index
|
||||
local blockIndex = window + 128
|
||||
window = (window + 1) % blockUse
|
||||
blockCache[blockIndex] = ""
|
||||
-- ok, now work on the problem
|
||||
local i = 1
|
||||
while i <= #blk do
|
||||
local bestData = blk:sub(i, i)
|
||||
local bestRes = bestData
|
||||
local bestScore = 1
|
||||
for bid = 128, 128 + blockUse - 1 do
|
||||
for lm = 0, 127 do
|
||||
local al = lm + 3
|
||||
local pfx = blk:sub(i, i + al - 1)
|
||||
if #pfx ~= al then
|
||||
break
|
||||
end
|
||||
local p = blockCache[bid]:find(pfx, 1, true)
|
||||
if not p then
|
||||
break
|
||||
end
|
||||
local score = al / 3
|
||||
if score > bestScore then
|
||||
bestData = string.char(bid) .. string.char((lm * 2) + math.floor((p - 1) / 256)) .. string.char((p - 1) % 256)
|
||||
bestRes = pfx
|
||||
bestScore = score
|
||||
end
|
||||
end
|
||||
end
|
||||
-- ok, encode!
|
||||
io.write(bestData)
|
||||
blockCache[blockIndex] = blockCache[blockIndex] .. bestRes
|
||||
i = i + #bestRes
|
||||
end
|
||||
end
|
||||
|
||||
while 1 do
|
||||
local blkd = io.read(512)
|
||||
runBlock(blkd)
|
||||
if #blkd < 512 then
|
||||
return
|
||||
end
|
||||
end
|
73
com2/bundiv.lua
Normal file
73
com2/bundiv.lua
Normal file
@ -0,0 +1,73 @@
|
||||
-- This is released into the public domain. XX
|
||||
-- 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,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 == 127 then
|
||||
b = Ct:byte()
|
||||
Ct = Ct:sub(2)
|
||||
if b == 127 then
|
||||
b = Ct:byte()+254
|
||||
if b > 255then
|
||||
b = b - 256
|
||||
end
|
||||
Ct = Ct:sub(2)
|
||||
else
|
||||
b = b + 127
|
||||
end
|
||||
end
|
||||
Cp = Cp..string.char(b)
|
||||
if #Cp == 512 then
|
||||
sector(Cp)
|
||||
Cp = ""
|
||||
end
|
||||
end
|
||||
end
|
||||
for i = 128, 127 + Cbu do
|
||||
Cs[i] = ("\x00"):rep(512)
|
||||
end
|
||||
Cs[Cw] = ""
|
||||
CB = function (d, i, d2, x, y)
|
||||
i=1
|
||||
while i <= #d - 2 do
|
||||
b=d:byte(i)
|
||||
d2=d:sub(i,i)
|
||||
i=i+1
|
||||
if not Ci then
|
||||
if b==0then
|
||||
Ci=1
|
||||
end
|
||||
else
|
||||
if b >= 128 then
|
||||
x = d:byte(i)
|
||||
i = i + 1
|
||||
y=d:byte(i) + ((x % 2) * 256)
|
||||
i = i + 1
|
||||
d2=Cs[b]:sub(y + 1,y + 3 + math.floor(x / 2))
|
||||
end
|
||||
Cs[Cw]=Cs[Cw]..d2
|
||||
if #Cs[Cw]>=512 then
|
||||
CP(Cs[Cw])
|
||||
Cw=((Cw-127)%Cbu)+128
|
||||
Cs[Cw]=""
|
||||
end
|
||||
end
|
||||
end
|
||||
return i
|
||||
end
|
||||
CD = function(d)
|
||||
Cb = Cb .. d
|
||||
Cb = Cb:sub(CB(Cb))
|
||||
end
|
||||
CD(io.read("*a")) -- XX
|
||||
--D.remove("init-bdivide.lua")--
|
||||
--D.rename("init.lua","init-bdivide.lua")--
|
||||
--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] .. "\x00\x00")
|
20
com2/preproc.lua
Normal file
20
com2/preproc.lua
Normal file
@ -0,0 +1,20 @@
|
||||
-- PREPROC: preprocess input to be 7-bit
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
while true do
|
||||
local c = io.read(1)
|
||||
if not c then return end
|
||||
local bc = c:byte()
|
||||
if bc < 127 then
|
||||
io.write(c)
|
||||
else
|
||||
if bc <= 253 then
|
||||
-- 127(0) through 253(126)
|
||||
io.write("\x7F" .. string.char(bc - 127))
|
||||
else
|
||||
-- 254(0) through 255 (1)
|
||||
io.write("\x7F\x7F" .. string.char(bc - 254))
|
||||
end
|
||||
end
|
||||
end
|
@ -1,11 +1,4 @@
|
||||
-- KittenOS NEO Repository Compliance Check Tool
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- I'm still not a lawyer
|
||||
local filesAccountedFor = {
|
||||
["repository/data/app-claw/local.lua"] = 0,
|
||||
|
27
heroes.lua
Normal file
27
heroes.lua
Normal file
@ -0,0 +1,27 @@
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- arg is the size of the code.tar file
|
||||
local arg = ...
|
||||
os.execute("lua com2/preproc.lua < code.tar | lua com2/bdivide.lua > com2/code.tar.bd")
|
||||
os.execute("cat insthead.lua")
|
||||
print("sC=" .. math.ceil(tonumber(arg) / 512))
|
||||
local src = io.open("com2/bundiv.lua", "r")
|
||||
while true do
|
||||
local line = src:read()
|
||||
if not line then
|
||||
io.flush()
|
||||
src:close()
|
||||
return
|
||||
end
|
||||
local endix = line:sub(#line-1,#line)
|
||||
if endix ~= "XX" then
|
||||
if endix == "--" then
|
||||
-- included
|
||||
print(line:sub(3,#line-2))
|
||||
else
|
||||
print(line)
|
||||
end
|
||||
end
|
||||
-- XX means ignored.
|
||||
end
|
34
imitclaw.lua
Normal file
34
imitclaw.lua
Normal file
@ -0,0 +1,34 @@
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- Imitation CLAW
|
||||
local done = {}
|
||||
|
||||
local f, e = loadfile("code/data/app-claw/local.lua")
|
||||
if not f then error(e) end
|
||||
f = f()
|
||||
if not os.execute("mkdir work") then
|
||||
error("Delete 'work'")
|
||||
end
|
||||
for k, v in pairs(f) do
|
||||
for _, vd in ipairs(v.dirs) do
|
||||
os.execute("mkdir work/" .. vd .. " 2> /dev/null")
|
||||
end
|
||||
for _, vf in ipairs(v.files) do
|
||||
-- not totally proofed but will do
|
||||
if not os.execute("cp code/" .. vf .. " work/" .. vf) then
|
||||
error("Could not copy " .. vf .. " in " .. k)
|
||||
end
|
||||
if done[vf] then
|
||||
error("duplicate " .. vf .. " in " .. k)
|
||||
end
|
||||
print(vf .. "\t\t" .. k)
|
||||
done[vf] = true
|
||||
end
|
||||
end
|
||||
os.execute("mkdir -p work/data/app-claw")
|
||||
os.execute("cp code/data/app-claw/local.lua work/data/app-claw/local.lua")
|
||||
os.execute("cd code ; find . > ../imitclaw.treecode")
|
||||
os.execute("cd work ; find . > ../imitclaw.treework")
|
||||
os.execute("diff -u imitclaw.treecode imitclaw.treework")
|
||||
os.execute("rm imitclaw.treecode imitclaw.treework")
|
@ -1,40 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
local bga = {}
|
||||
|
||||
local str = io.read("*a")
|
||||
|
||||
for i = 1, #str - 1 do
|
||||
local bg = str:sub(i, i + 1)
|
||||
bga[bg] = (bga[bg] or 0) + 1
|
||||
end
|
||||
|
||||
local first = {}
|
||||
local second = {}
|
||||
|
||||
local mode = ...
|
||||
|
||||
for k, v in pairs(bga) do
|
||||
if mode == "combined" then
|
||||
print(string.format("%08i: %02x%02x : %s", v, k:byte(1), k:byte(2), k))
|
||||
end
|
||||
first[k:sub(1, 1)] = (first[k:sub(1, 1)] or 0) + v
|
||||
second[k:sub(1, 1)] = (second[k:sub(1, 1)] or 0) + v
|
||||
end
|
||||
|
||||
for k, v in pairs(first) do
|
||||
if mode == "first" then
|
||||
print(string.format("%08i: %s", v, k))
|
||||
end
|
||||
end
|
||||
|
||||
for k, v in pairs(second) do
|
||||
if mode == "second" then
|
||||
print(string.format("%08i: %s", v, k))
|
||||
end
|
||||
end
|
@ -1,89 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- PREPROC (r9 edition): preprocess input to be 7-bit
|
||||
|
||||
local frw = require("libs.frw")
|
||||
|
||||
local
|
||||
-- SHARED WITH DECOMPRESSION ENGINE
|
||||
function p(x, y)
|
||||
if x == 126 then
|
||||
return string.char(y), 3
|
||||
elseif x == 127 then
|
||||
return string.char(128 + y), 3
|
||||
elseif x >= 32 then
|
||||
return string.char(x), 2
|
||||
elseif x == 31 then
|
||||
return "\n", 2
|
||||
elseif x == 30 then
|
||||
return "\x00", 2
|
||||
end
|
||||
return string.char(("enart"):byte(x % 5 + 1), ("ndtelh"):byte((x - x % 5) / 5 + 1)), 2
|
||||
end
|
||||
|
||||
local preprocParts = {}
|
||||
local preprocMaxLen = 0
|
||||
for i = 0, 127 do
|
||||
for j = 0, 127 do
|
||||
local d, l = p(i, j)
|
||||
if d then
|
||||
preprocMaxLen = math.max(preprocMaxLen, #d)
|
||||
l = l - 1
|
||||
if (not preprocParts[d]) or (#preprocParts[d] > l) then
|
||||
if l == 2 then
|
||||
preprocParts[d] = string.char(i, j)
|
||||
else
|
||||
preprocParts[d] = string.char(i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function preprocWithPadding(blk, p)
|
||||
local out = ""
|
||||
local needsPadding = false
|
||||
while blk ~= "" do
|
||||
p(blk)
|
||||
local len = math.min(preprocMaxLen, #blk)
|
||||
while len > 0 do
|
||||
local seg = blk:sub(1, len)
|
||||
if preprocParts[seg] then
|
||||
out = out .. preprocParts[seg]
|
||||
needsPadding = #preprocParts[seg] < 2
|
||||
blk = blk:sub(#seg + 1)
|
||||
break
|
||||
end
|
||||
len = len - 1
|
||||
end
|
||||
assert(len ~= 0)
|
||||
end
|
||||
-- This needsPadding bit is just sort of quickly added in
|
||||
-- to keep this part properly maintained
|
||||
-- even though it might never get used
|
||||
if needsPadding then
|
||||
return out .. "\x00"
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local bdCore = require("bdivide.core")
|
||||
|
||||
return function (data, lexCrunch)
|
||||
io.stderr:write("preproc: ")
|
||||
local pi = frw.progress()
|
||||
local function p(b)
|
||||
pi(1 - (#b / #data))
|
||||
end
|
||||
data = preprocWithPadding(data, p)
|
||||
io.stderr:write("\nbdivide: ")
|
||||
pi = frw.progress()
|
||||
data = bdCore.bdividePad(bdCore.bdivide(data, p))
|
||||
io.stderr:write("\n")
|
||||
return lexCrunch.process(frw.read("bdivide/instdeco.lua"), {}), data
|
||||
end
|
@ -1,76 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- BDIVIDE r5 edition
|
||||
-- Algorithm simplified for smaller implementation and potentially better compression
|
||||
-- format:
|
||||
-- 0-127 for constants
|
||||
-- <128 + (length - 4)>, <position high>, <position low>
|
||||
-- Position is where in the window it was found, minus 1.
|
||||
-- windowSize must be the same between the encoder and decoder,
|
||||
-- and is the amount of data preserved after cropping.
|
||||
|
||||
local bdivCore = {}
|
||||
|
||||
function bdivCore.bdivide(blk, p)
|
||||
local out = ""
|
||||
|
||||
local windowSize = 0x10000
|
||||
local windowData = ("\x00"):rep(windowSize)
|
||||
|
||||
while blk ~= "" do
|
||||
p(blk)
|
||||
local bestData = blk:sub(1, 1)
|
||||
assert(blk:byte() < 128, "BDIVIDE does not handle 8-bit data")
|
||||
local bestRes = bestData
|
||||
for lm = 0, 127 do
|
||||
local al = lm + 4
|
||||
local pfx = blk:sub(1, al)
|
||||
if #pfx ~= al then
|
||||
break
|
||||
end
|
||||
local p = windowData:find(pfx, 1, true)
|
||||
if not p then
|
||||
break
|
||||
end
|
||||
local pm = p - 1
|
||||
local thirdByte = pm % 256
|
||||
bestData = string.char(128 + lm, math.floor(pm / 256), thirdByte)
|
||||
bestRes = pfx
|
||||
end
|
||||
-- ok, encode!
|
||||
out = out .. bestData
|
||||
-- crop window
|
||||
windowData = (windowData .. bestRes):sub(-windowSize)
|
||||
blk = blk:sub(#bestRes + 1)
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
-- Adds padding if required
|
||||
function bdivCore.bdividePad(data)
|
||||
local i = 1
|
||||
-- Basically, if it ends on a literal,
|
||||
-- then the literal won't get read without two padding bytes.
|
||||
-- Otherwise (including if no data) it's fine.
|
||||
local needsPadding = false
|
||||
while i <= #data do
|
||||
if data:byte(i) > 127 then
|
||||
i = i + 3
|
||||
needsPadding = false
|
||||
else
|
||||
i = i + 1
|
||||
needsPadding = true
|
||||
end
|
||||
end
|
||||
if needsPadding then
|
||||
return data .. "\x00\x00"
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
return bdivCore
|
@ -1,68 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- BDIVIDE (r5 edition) and PREPROC (r9 edition)
|
||||
-- decompression engine for installer
|
||||
|
||||
$bdPPBuffer = ""
|
||||
$bdBDBuffer = ""
|
||||
$bdBDWindow = ("\x00"):rep(2^16)
|
||||
-- High-level breakdown:
|
||||
-- q is unescaper.
|
||||
-- It'll only begin to input if at least 3 bytes are available,
|
||||
-- so you'll want to throw in 2 extra zeroes at the end of stream as done here.
|
||||
-- It uses t (input buffer) and p (output buffer).
|
||||
-- Ignore its second argument, as that's a lie, it's just there for a local.
|
||||
-- L is the actual decompressor. It has the same quirk as q, wanting two more bytes.
|
||||
-- It stores to c (compressed), and w (window).
|
||||
-- It outputs that which goes to the window to q also.
|
||||
-- And it also uses a fake local.
|
||||
|
||||
-- SEE compress.lua FOR THIS FUNCTION
|
||||
function $bdPP(x, y)
|
||||
if x == 126 then
|
||||
return string.char(y), 3
|
||||
elseif x == 127 then
|
||||
return string.char(128 + y), 3
|
||||
elseif x >= 32 then
|
||||
return string.char(x), 2
|
||||
elseif x == 31 then
|
||||
return "\n", 2
|
||||
elseif x == 30 then
|
||||
return "\x00", 2
|
||||
end
|
||||
return string.char(("enart"):byte(x % 5 + 1), ("ndtelh"):byte((x - x % 5) / 5 + 1)), 2
|
||||
end
|
||||
|
||||
${
|
||||
function $engineInput($L|lData)
|
||||
$bdBDBuffer = $bdBDBuffer .. $lData
|
||||
while #$bdBDBuffer > 2 do
|
||||
$lData = $bdBDBuffer:byte()
|
||||
if $lData < 128 then
|
||||
$lData = $bdBDBuffer:sub(1, 1)
|
||||
$bdBDBuffer = $bdBDBuffer:sub(2)
|
||||
else
|
||||
${
|
||||
$L|bdBDPtr = $bdBDBuffer:byte(2) * 256 + $bdBDBuffer:byte(3) + 1
|
||||
$lData = $bdBDWindow:sub($bdBDPtr, $bdBDPtr + $lData - 125)
|
||||
$bdBDBuffer = $bdBDBuffer:sub(4)
|
||||
$}
|
||||
end
|
||||
$bdPPBuffer = $bdPPBuffer .. $lData
|
||||
$bdBDWindow = ($bdBDWindow .. $lData):sub(-2^16)
|
||||
while #$bdPPBuffer > 1 do
|
||||
${
|
||||
$lData, $L|bdPPAdv = $bdPP($bdPPBuffer:byte(), $bdPPBuffer:byte(2))
|
||||
$bdPPBuffer = $bdPPBuffer:sub($bdPPAdv)
|
||||
$}
|
||||
$engineOutput($lData)
|
||||
end
|
||||
end
|
||||
end
|
||||
$}
|
||||
|
@ -1,22 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
local frw = require("libs.frw")
|
||||
|
||||
local bdCore = require("bdivide.core")
|
||||
|
||||
return function (data, lexCrunch)
|
||||
io.stderr:write("\nbdivide: ")
|
||||
local pi = frw.progress()
|
||||
local function p(b)
|
||||
pi(1 - (#b / #data))
|
||||
end
|
||||
data = bdCore.bdividePad(bdCore.bdivide(data, p))
|
||||
io.stderr:write("\n")
|
||||
return lexCrunch.process(frw.read("bdvlite/instdeco.lua"), {}), data
|
||||
end
|
||||
|
@ -1,76 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- BDIVIDE r5 edition
|
||||
-- Algorithm simplified for smaller implementation and potentially better compression
|
||||
-- format:
|
||||
-- 0-127 for constants
|
||||
-- <128 + (length - 4)>, <position high>, <position low>
|
||||
-- Position is where in the window it was found, minus 1.
|
||||
-- windowSize must be the same between the encoder and decoder,
|
||||
-- and is the amount of data preserved after cropping.
|
||||
|
||||
local bdivCore = {}
|
||||
|
||||
function bdivCore.bdivide(blk, p)
|
||||
local out = ""
|
||||
|
||||
local windowSize = 0x10000
|
||||
local windowData = ("\x00"):rep(windowSize)
|
||||
|
||||
while blk ~= "" do
|
||||
p(blk)
|
||||
local bestData = blk:sub(1, 1)
|
||||
assert(blk:byte() < 128, "BDIVIDE does not handle 8-bit data")
|
||||
local bestRes = bestData
|
||||
for lm = 0, 127 do
|
||||
local al = lm + 4
|
||||
local pfx = blk:sub(1, al)
|
||||
if #pfx ~= al then
|
||||
break
|
||||
end
|
||||
local p = windowData:find(pfx, 1, true)
|
||||
if not p then
|
||||
break
|
||||
end
|
||||
local pm = p - 1
|
||||
local thirdByte = pm % 256
|
||||
bestData = string.char(128 + lm, math.floor(pm / 256), thirdByte)
|
||||
bestRes = pfx
|
||||
end
|
||||
-- ok, encode!
|
||||
out = out .. bestData
|
||||
-- crop window
|
||||
windowData = (windowData .. bestRes):sub(-windowSize)
|
||||
blk = blk:sub(#bestRes + 1)
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
-- Adds padding if required
|
||||
function bdivCore.bdividePad(data)
|
||||
local i = 1
|
||||
-- Basically, if it ends on a literal,
|
||||
-- then the literal won't get read without two padding bytes.
|
||||
-- Otherwise (including if no data) it's fine.
|
||||
local needsPadding = false
|
||||
while i <= #data do
|
||||
if data:byte(i) > 127 then
|
||||
i = i + 3
|
||||
needsPadding = false
|
||||
else
|
||||
i = i + 1
|
||||
needsPadding = true
|
||||
end
|
||||
end
|
||||
if needsPadding then
|
||||
return data .. "\x00\x00"
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
return bdivCore
|
@ -1,34 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- BDIVIDE (r5 edition)
|
||||
-- decompression engine used to decompress DEFLATE decompression engine
|
||||
|
||||
$bdBDBuffer = ""
|
||||
$bdBDWindow = ("\x00"):rep(2^16)
|
||||
|
||||
${
|
||||
function $engineInput($L|lData)
|
||||
$bdBDBuffer = $bdBDBuffer .. $lData
|
||||
while #$bdBDBuffer > 2 do
|
||||
$lData = $bdBDBuffer:byte()
|
||||
if $lData < 128 then
|
||||
$lData = $bdBDBuffer:sub(1, 1)
|
||||
$bdBDBuffer = $bdBDBuffer:sub(2)
|
||||
else
|
||||
${
|
||||
$L|bdBDPtr = $bdBDBuffer:byte(2) * 256 + $bdBDBuffer:byte(3) + 1
|
||||
$lData = $bdBDWindow:sub($bdBDPtr, $bdBDPtr + $lData - 125)
|
||||
$bdBDBuffer = $bdBDBuffer:sub(4)
|
||||
$}
|
||||
end
|
||||
$bdBDWindow = ($bdBDWindow .. $lData):sub(-2^16)
|
||||
$engineOutput($lData)
|
||||
end
|
||||
end
|
||||
$}
|
||||
|
@ -1,82 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- KittenOS NEO Installer Generator --
|
||||
local args = {...}
|
||||
|
||||
local cid = args[1]
|
||||
local tarName = args[2]
|
||||
local algorithmsInReverseOrder = {}
|
||||
for i = 3, #args do
|
||||
table.insert(algorithmsInReverseOrder, 1, args[i])
|
||||
end
|
||||
|
||||
local u = require("libs.frw")
|
||||
|
||||
local instSize = 0
|
||||
local function put(data)
|
||||
io.write(data)
|
||||
instSize = instSize + #data
|
||||
end
|
||||
|
||||
-- Installer Lexcrunch Context --
|
||||
local lexCrunch = require("libs.lexcrunch")()
|
||||
|
||||
-- Installer Core --
|
||||
|
||||
-- installerFinalized:
|
||||
-- Stuff that's already finished and put at the end of RISM. Prepend to this.
|
||||
-- installerPayload / installerProgramLength:
|
||||
-- The next-outer chunk that hasn't been written to the end of RISM
|
||||
-- as the compression scheme (if one) has not been applied yet.
|
||||
-- Really, installerProgramLength is only necessary because of the innermost chunk,
|
||||
-- as that chunk has the TAR; additional data that's part of the same effective compression block,
|
||||
-- but requires the program length to avoid it.
|
||||
local installerPayload
|
||||
local installerProgramLength
|
||||
local installerFinalized = ""
|
||||
|
||||
do
|
||||
local tarData = u.read(tarName)
|
||||
local tarSectors = math.floor(#tarData / 512)
|
||||
local installerCore = lexCrunch.process(u.read("instcore.lua"), {["$$SECTORS"] = tostring(tarSectors)})
|
||||
installerPayload = installerCore .. tarData
|
||||
installerProgramLength = #installerCore
|
||||
end
|
||||
|
||||
-- Installer Compression --
|
||||
for _, v in ipairs(algorithmsInReverseOrder) do
|
||||
io.stderr:write("compressing (" .. v .. ")\n")
|
||||
local algImpl = require(v .. ".compress")
|
||||
local algEngine, algData = algImpl(installerPayload, lexCrunch)
|
||||
io.stderr:write("result: " .. #installerPayload .. " -> " .. #algData .. "\n")
|
||||
-- prepend the program length of the last section
|
||||
algEngine = lexCrunch.process("$iBlockingLen = " .. installerProgramLength .. " " .. algEngine, {})
|
||||
-- commit
|
||||
installerPayload = algEngine
|
||||
installerProgramLength = #installerPayload
|
||||
installerFinalized = algData .. installerFinalized
|
||||
end
|
||||
|
||||
-- Installer Final --
|
||||
|
||||
-- This is a special case, so the program length/payload/etc. business has to be repeated.
|
||||
put("--" .. cid .. "\n")
|
||||
put("--This is released into the public domain. No warranty is provided, implied or otherwise.\n")
|
||||
put(lexCrunch.process(u.read("insthead.lua"), {["$$CORESIZE"] = tostring(installerProgramLength)}))
|
||||
|
||||
local RISM = installerPayload .. installerFinalized
|
||||
RISM = RISM:gsub("\xFE", "\xFE\xFE")
|
||||
RISM = RISM:gsub("]]", "]\xFE]")
|
||||
RISM = "\x00" .. RISM
|
||||
put("--[[" .. RISM .. "]]")
|
||||
|
||||
-- Dumping debug info --
|
||||
local dbg = io.open("iSymTab", "wb")
|
||||
lexCrunch.dump(dbg)
|
||||
dbg:close()
|
||||
|
@ -1,18 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- This is a wrapper around (i.e. does not contain) Zopfli.
|
||||
local frw = require("libs.frw")
|
||||
|
||||
return function (data, lexCrunch)
|
||||
frw.write("tempData.bin", data)
|
||||
os.execute("zopfli --i1 --deflate -c tempData.bin > tempZopf.bin")
|
||||
local res = frw.read("tempZopf.bin")
|
||||
os.execute("rm tempData.bin tempZopf.bin")
|
||||
return lexCrunch.process(frw.read("deflate/instdeco.lua"), {}), res
|
||||
end
|
||||
|
@ -1,291 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- THIS NEXT LINE IS CLEARLY AWFUL
|
||||
$bdBDWindow = nil
|
||||
|
||||
-- THE DEFLATE DECOMPRESSOR OF MADNESS --
|
||||
|
||||
-- Core I/O --
|
||||
|
||||
-- $dfAlignToByteRemaining is
|
||||
-- set to 8 in the outer engine
|
||||
|
||||
${
|
||||
function $dfGetIntField($L|lLen, $L|lVal)
|
||||
$lVal = 0
|
||||
for $L|lI = 0, $lLen - 1 do
|
||||
if coroutine.yield() then
|
||||
$lVal = $lVal + 2^$lI
|
||||
end
|
||||
end
|
||||
return $lVal
|
||||
end
|
||||
$}
|
||||
|
||||
-- Huffman Core --
|
||||
-- The approach here is based around 1-prefixed integers.
|
||||
-- These are stored in a flat table.
|
||||
-- So 0b1000 is the pattern 000.
|
||||
|
||||
${
|
||||
function $dfReadHuffmanSymbol($L|lTree, $L|lVal)
|
||||
$lVal = 1
|
||||
while not $lTree[$lVal] do
|
||||
$lVal = ($lVal * 2) + $dfGetIntField(1)
|
||||
end
|
||||
return $lTree[$lVal]
|
||||
end
|
||||
$}
|
||||
|
||||
${
|
||||
function $dfGenHuffmanTree($L|lCodeLens)
|
||||
-- $L|lI (used everywhere; defining inside creates a bug because it gets globalized)
|
||||
$L|lNextCode = {}
|
||||
${
|
||||
-- To explain:
|
||||
-- lNextCode is needed all the way to the end.
|
||||
-- But lBLCount isn't needed after it's used to
|
||||
-- generate lNextCode.
|
||||
-- And lCode is very, very temporary.
|
||||
-- Hence this massive block.
|
||||
$L|lBLCount = {}
|
||||
-- Note the 0
|
||||
for $lI = 0, 15 do
|
||||
$lBLCount[$lI] = 0
|
||||
end
|
||||
for $lI = 0, #$lCodeLens do
|
||||
${
|
||||
$L|lCodeLen = $lCodeLens[$lI]
|
||||
if $lCodeLen ~= 0 then
|
||||
$lBLCount[$lCodeLen] = $lBLCount[$lCodeLen] + 1
|
||||
end
|
||||
$}
|
||||
end
|
||||
|
||||
$L|lCode = 0
|
||||
for $lI = 1, 15 do
|
||||
$lCode = ($lCode + $lBLCount[$lI - 1]) * 2
|
||||
$lNextCode[$lI] = $lCode
|
||||
end
|
||||
$}
|
||||
|
||||
$L|lTree = {}
|
||||
for $lI = 0, #$lCodeLens do
|
||||
${
|
||||
$L|lCodeLen = $lCodeLens[$lI]
|
||||
if $lCodeLen ~= 0 then
|
||||
$L|lPow = math.floor(2 ^ $lCodeLen)
|
||||
assert($lNextCode[$lCodeLen] < $lPow, "Tl" .. $lCodeLen)
|
||||
$L|lK = $lNextCode[$lCodeLen] + $lPow
|
||||
assert(not $lTree[$lK], "conflict @ " .. $lK)
|
||||
$lTree[$lK] = $lI
|
||||
$lNextCode[$lCodeLen] = $lNextCode[$lCodeLen] + 1
|
||||
end
|
||||
$}
|
||||
end
|
||||
return $lTree
|
||||
end
|
||||
$}
|
||||
|
||||
-- DEFLATE fixed trees --
|
||||
${
|
||||
$L|dfFixedTL = {}
|
||||
for $L|lI = 0, 143 do $dfFixedTL[$lI] = 8 end
|
||||
for $lI = 144, 255 do $dfFixedTL[$lI] = 9 end
|
||||
for $lI = 256, 279 do $dfFixedTL[$lI] = 7 end
|
||||
for $lI = 280, 287 do $dfFixedTL[$lI] = 8 end
|
||||
$dfFixedLit = $dfGenHuffmanTree($dfFixedTL)
|
||||
-- last line possibly destroyed dfFixedTL, but that's alright
|
||||
$dfFixedTL = {}
|
||||
for $lI = 0, 31 do $dfFixedTL[$lI] = 5 end
|
||||
$dfFixedDst = $dfGenHuffmanTree($dfFixedTL)
|
||||
$}
|
||||
|
||||
-- DEFLATE LZ Core --
|
||||
|
||||
$dfWindow = ("\x00"):rep(2^15)
|
||||
$dfPushBuf = ""
|
||||
${
|
||||
function $dfOutput($L|lData)
|
||||
$dfWindow = ($dfWindow .. $lData):sub(-2^15)
|
||||
$dfPushBuf = $dfPushBuf .. $lData
|
||||
end
|
||||
$}
|
||||
|
||||
$dfBittblLength = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 0
|
||||
}
|
||||
$dfBasetblLength = {
|
||||
3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 13, 15, 17, 19, 23, 27, 31,
|
||||
35, 43, 51, 59, 67, 83, 99, 115,
|
||||
131, 163, 195, 227, 258
|
||||
}
|
||||
$dfBittblDist = {
|
||||
0, 0, 0, 0, 1, 1, 2, 2,
|
||||
3, 3, 4, 4, 5, 5, 6, 6,
|
||||
7, 7, 8, 8, 9, 9, 10, 10,
|
||||
11, 11, 12, 12, 13, 13
|
||||
}
|
||||
$dfBasetblDist = {
|
||||
1, 2, 3, 4, 5, 7, 9, 13,
|
||||
17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073,
|
||||
4097, 6145, 8193, 12289, 16385, 24577
|
||||
}
|
||||
|
||||
${
|
||||
function $dfReadBlockBody($L|lLit, $L|lDst, $L|lLitSym, $L|lLen, $L|lDCode, $L|lPtr)
|
||||
while true do
|
||||
$lLitSym = $dfReadHuffmanSymbol($lLit)
|
||||
if $lLitSym <= 255 then
|
||||
$dfOutput(string.char($lLitSym))
|
||||
elseif $lLitSym == 256 then
|
||||
return
|
||||
elseif $lLitSym <= 285 then
|
||||
$lLen = $dfBasetblLength[$lLitSym - 256] + $dfGetIntField($dfBittblLength[$lLitSym - 256])
|
||||
$lDCode = $dfReadHuffmanSymbol($lDst)
|
||||
$lPtr = 32769 - ($dfBasetblDist[$lDCode + 1] + $dfGetIntField($dfBittblDist[$lDCode + 1]))
|
||||
for $L|lI = 1, $lLen do
|
||||
$dfOutput($dfWindow:sub($lPtr, $lPtr))
|
||||
end
|
||||
else
|
||||
error("nt" .. v)
|
||||
end
|
||||
end
|
||||
end
|
||||
$}
|
||||
|
||||
-- Huffman Dynamics --
|
||||
|
||||
${
|
||||
function $dfReadHuffmanDynamicSubcodes($L|lDistLens, $L|lCount, $L|lMetatree, $L|lCode)
|
||||
-- used a lot: $L|lI
|
||||
$lCode = 0
|
||||
$lDistLens[-1] = 0
|
||||
while $lCode < $lCount do
|
||||
-- use a tmpglb since it's just for the chain
|
||||
$L|lInstr = $dfReadHuffmanSymbol($lMetatree)
|
||||
if $lInstr < 16 then
|
||||
$lDistLens[$lCode] = $lInstr
|
||||
$lCode = $lCode + 1
|
||||
elseif $lInstr == 16 then
|
||||
for $lI = 1, 3 + $dfGetIntField(2) do
|
||||
$lDistLens[$lCode] = $lDistLens[$lCode - 1]
|
||||
$lCode = $lCode + 1
|
||||
assert($lCode <= $lCount, "sc.over")
|
||||
end
|
||||
elseif $lInstr == 17 then
|
||||
for $lI = 1, 3 + $dfGetIntField(3) do
|
||||
$lDistLens[$lCode] = 0
|
||||
$lCode = $lCode + 1
|
||||
assert($lCode <= $lCount, "sc.over")
|
||||
end
|
||||
elseif $lInstr == 18 then
|
||||
for $lI = 1, 11 + $dfGetIntField(7) do
|
||||
$lDistLens[$lCode] = 0
|
||||
$lCode = $lCode + 1
|
||||
assert($lCode <= $lCount, "sc.over")
|
||||
end
|
||||
else
|
||||
-- is this even possible?
|
||||
error("sc.unki")
|
||||
end
|
||||
end
|
||||
$lDistLens[-1] = nil
|
||||
return $lDistLens
|
||||
end
|
||||
$}
|
||||
|
||||
$dfDynamicMetalensScramble = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
|
||||
|
||||
${
|
||||
function $dfReadHuffmanDynamic($L|lState, $L|lLiteralSize, $L|lDistanceSize, $L|lDistanceLens)
|
||||
-- $L|lI loop variable, used all over
|
||||
-- to save on locals, this is reused
|
||||
-- as metalens
|
||||
$lState = {}
|
||||
for $lI = 0, 18 do $lState[$lI] = 0 end
|
||||
$lLiteralSize = $dfGetIntField(5) + 257
|
||||
$lDistanceSize = $dfGetIntField(5) + 1
|
||||
for $lI = 1, $dfGetIntField(4) + 4 do
|
||||
$lState[$dfDynamicMetalensScramble[$lI]] = $dfGetIntField(3)
|
||||
end
|
||||
-- as metatree
|
||||
$lState = $dfGenHuffmanTree($lState)
|
||||
-- as concatenated subcodes
|
||||
$lState = $dfReadHuffmanDynamicSubcodes({}, $lLiteralSize + $lDistanceSize, $lState)
|
||||
-- The distance lengths are removed from lState,
|
||||
-- while being added to lDistanceLens
|
||||
-- The result is completion
|
||||
$lDistanceLens = {}
|
||||
for $lI = 0, $lDistanceSize - 1 do
|
||||
$lDistanceLens[$lI] = $lState[$lLiteralSize + $lI]
|
||||
$lState[$lLiteralSize + $lI] = nil
|
||||
end
|
||||
return $dfGenHuffmanTree($lState), $dfGenHuffmanTree($lDistanceLens)
|
||||
end
|
||||
$}
|
||||
|
||||
-- Main Thread --
|
||||
|
||||
${
|
||||
$dfThread = coroutine.create(function ($L|lFinal, $L|lLitLen)
|
||||
while true do
|
||||
$lFinal = coroutine.yield()
|
||||
$L|lBlockType = $dfGetIntField(2)
|
||||
if $lBlockType == 0 then
|
||||
-- literal
|
||||
$dfGetIntField($dfAlignToByteRemaining)
|
||||
$lLitLen = $dfGetIntField(16)
|
||||
-- this is weird, ignore it
|
||||
$dfGetIntField(16)
|
||||
for $L|lI = 1, $lLitLen do
|
||||
$dfOutput(string.char($dfGetIntField(8)))
|
||||
end
|
||||
elseif $lBlockType == 1 then
|
||||
-- fixed Huffman
|
||||
$dfReadBlockBody($dfFixedLit, $dfFixedDst)
|
||||
elseif $lBlockType == 2 then
|
||||
-- dynamic Huffman
|
||||
$dfReadBlockBody($dfReadHuffmanDynamic())
|
||||
else
|
||||
error("b3")
|
||||
end
|
||||
while $lFinal do
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
end)
|
||||
$}
|
||||
|
||||
-- The Outer Engine --
|
||||
|
||||
coroutine.resume($dfThread)
|
||||
${
|
||||
function $engineInput($L|lData, $L|lByte)
|
||||
for $L|lI = 1, #$lData do
|
||||
$lByte = $lData:byte($lI)
|
||||
$dfAlignToByteRemaining = 8
|
||||
while $dfAlignToByteRemaining > 0 do
|
||||
-- If we're providing the first bit (v = 8), then there are 7 bits remaining.
|
||||
-- So this hits 0 when the *next* 8 yields will provide an as-is byte.
|
||||
$dfAlignToByteRemaining = $dfAlignToByteRemaining - 1
|
||||
assert(coroutine.resume($dfThread, $lByte % 2 == 1))
|
||||
$lByte = math.floor($lByte / 2)
|
||||
end
|
||||
end
|
||||
-- flush prepared buffer
|
||||
$engineOutput($dfPushBuf)
|
||||
$dfPushBuf = ""
|
||||
end
|
||||
$}
|
||||
|
@ -1,80 +0,0 @@
|
||||
-- KOSNEO installer base
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
$icScreen = $component.list("screen", true)()
|
||||
$icGPU = $component.list("gpu", true)()
|
||||
|
||||
$icFilename = "Starting..."
|
||||
$icBytesRemaining = 0
|
||||
|
||||
if $icScreen and $icGPU then
|
||||
$icGPU = $component.proxy($icGPU)
|
||||
$icGPU.bind($icScreen)
|
||||
$icGPU.setResolution(50, 5)
|
||||
$icGPU.setBackground(2^24-1)
|
||||
$icGPU.setForeground(0)
|
||||
$icGPU.fill(1, 1, 50, 5, "█")
|
||||
$icGPU.fill(1, 2, 50, 1, " ")
|
||||
$icGPU.set(2, 2, "KittenOS NEO Installer")
|
||||
end
|
||||
|
||||
function $icOctalToNumber($a0)
|
||||
if $a0 == "" then return 0 end
|
||||
return $icOctalToNumber($a0:sub(1, -2)) * 8 + ($a0:byte(#$a0) - 48)
|
||||
end
|
||||
|
||||
$icSectorsRead = 0
|
||||
$iBlockingLen = 512
|
||||
function $iBlockingHook($a0)
|
||||
if $icBytesRemaining > 0 then
|
||||
${
|
||||
$L|icByteAdv = math.min(512, $icBytesRemaining)
|
||||
$icBytesRemaining = $icBytesRemaining - $icByteAdv
|
||||
if $icFile then
|
||||
$filesystem.write($icFile, $a0:sub(1, $icByteAdv))
|
||||
if $icBytesRemaining <= 0 then
|
||||
$filesystem.close($icFile)
|
||||
$icFile = nil
|
||||
end
|
||||
end
|
||||
$}
|
||||
else
|
||||
$icFilename = $a0:sub(1, 100):gsub("\x00", "")
|
||||
-- this sets up the reading/skipping of data
|
||||
$icBytesRemaining = $icOctalToNumber($a0:sub(125, 135))
|
||||
if $icFilename:sub(1, 2) == "./" and $icFilename ~= "./" then
|
||||
$icFilename = $icFilename:sub(3)
|
||||
if $icFilename:sub(#$icFilename) == "/" then
|
||||
$filesystem.makeDirectory($icFilename)
|
||||
else
|
||||
$icFile = $filesystem.open($icFilename, "wb")
|
||||
if $icBytesRemaining == 0 then
|
||||
$filesystem.close($icFile)
|
||||
$icFile = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- UPDATE DISPLAY --
|
||||
$icSectorsRead = $icSectorsRead + 1
|
||||
if $icScreen and $icGPU then
|
||||
$icGPU.fill(1, 2, 50, 1, " ")
|
||||
$icGPU.set(2, 2, "KittenOS NEO Installer : " .. $icFilename)
|
||||
$icGPU.fill(2, 4, 48, 1, "█")
|
||||
$icGPU.fill(2, 4, math.ceil(48 * $icSectorsRead / $$SECTORS), 1, " ")
|
||||
end
|
||||
if $icSectorsRead % 16 == 0 then
|
||||
$computer.pullSignal(0.01)
|
||||
end
|
||||
if $icSectorsRead == $$SECTORS then
|
||||
$filesystem.close($readInFile)
|
||||
$filesystem.remove("init.neoi.lua")
|
||||
$computer.shutdown(true)
|
||||
end
|
||||
end
|
||||
|
@ -1,71 +0,0 @@
|
||||
-- KOSNEO installer base
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
$computer = computer
|
||||
$component = component
|
||||
assert($component, "KittenOS NEO installer: Copy as init.lua to the target disk, then remove other disks & reboot.")
|
||||
|
||||
$filesystem = $component.proxy($computer.getBootAddress())
|
||||
|
||||
$filesystem.remove("init.neoi.lua")
|
||||
$filesystem.rename("init.lua", "init.neoi.lua")
|
||||
$readInFile = $filesystem.open("init.neoi.lua", "rb")
|
||||
|
||||
$iBlockingBuffer = ""
|
||||
$iBlockingLen = $$CORESIZE
|
||||
${
|
||||
function $iBlockingHook($L|lBlock)
|
||||
-- Run the next script (replacement compression engine,)
|
||||
assert(load($lBlock))()
|
||||
end
|
||||
$}
|
||||
|
||||
${
|
||||
function $engineOutput($L|lBlock)
|
||||
$iBlockingBuffer = $iBlockingBuffer .. $lBlock
|
||||
while #$iBlockingBuffer >= $iBlockingLen do
|
||||
$lBlock = $iBlockingBuffer:sub(1, $iBlockingLen)
|
||||
$iBlockingBuffer = $iBlockingBuffer:sub($iBlockingLen + 1)
|
||||
$iBlockingHook($lBlock)
|
||||
end
|
||||
end
|
||||
$}
|
||||
$engineInput = $engineOutput
|
||||
|
||||
while true do
|
||||
$readInBlock = $filesystem.read($readInFile, 1024)
|
||||
${
|
||||
for i = 1, #$readInBlock do
|
||||
-- Read-in state machine
|
||||
|
||||
-- IT IS VERY IMPORTANT that read-in be performed char-by-char.
|
||||
-- This is because of compression chain-loading; if the switch between engines isn't "clean",
|
||||
-- bad stuff happens.
|
||||
|
||||
-- This character becomes invalid once
|
||||
-- it gets passed to engineInput,
|
||||
-- but that's the last step, so it's ok!
|
||||
$L|readInChar = $readInBlock:sub(i, i)
|
||||
if not $readInState then
|
||||
if $readInChar == "\x00" then
|
||||
$readInState = 0
|
||||
end
|
||||
elseif $readInState == 0 then
|
||||
if $readInChar == "\xFE" then
|
||||
$readInState = 1
|
||||
else
|
||||
$engineInput($readInChar)
|
||||
end
|
||||
else
|
||||
$engineInput($readInChar)
|
||||
$readInState = 0
|
||||
end
|
||||
end
|
||||
$}
|
||||
end
|
||||
|
@ -1,34 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
return {
|
||||
read = function (fn)
|
||||
local f = io.open(fn, "rb")
|
||||
local d = f:read("*a")
|
||||
f:close()
|
||||
return d
|
||||
end,
|
||||
write = function (fn, data)
|
||||
local f = io.open(fn, "wb")
|
||||
f:write(data)
|
||||
f:close()
|
||||
end,
|
||||
progress = function ()
|
||||
io.stderr:write("00% \\")
|
||||
local lastPercent = 0
|
||||
local chr = 0
|
||||
return function (fraction)
|
||||
local percent = math.ceil(fraction * 100)
|
||||
if percent ~= lastPercent then
|
||||
lastPercent = percent
|
||||
chr = (chr + 1) % 4
|
||||
io.stderr:write(string.format("\8\8\8\8\8%02i%% %s", percent, ("\\|/-"):sub(chr + 1, chr + 1)))
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
|
@ -1,195 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- This library helps in crunching down the installer a bit further.
|
||||
local sequences = {
|
||||
{"\n", " "},
|
||||
{" ", " "},
|
||||
{" #", "#"},
|
||||
{"# ", "#"},
|
||||
{" ,", ","},
|
||||
{", ", ","},
|
||||
{" (", "("},
|
||||
{"( ", "("},
|
||||
{" )", ")"},
|
||||
{") ", ")"},
|
||||
{" {", "{"},
|
||||
{"{ ", "{"},
|
||||
{" }", "}"},
|
||||
{"} ", "}"},
|
||||
{" <", "<"},
|
||||
{"< ", "<"},
|
||||
{" >", ">"},
|
||||
{"> ", ">"},
|
||||
{" *", "*"},
|
||||
{"* ", "*"},
|
||||
{" ~", "~"},
|
||||
{"~ ", "~"},
|
||||
{" /", "/"},
|
||||
{"/ ", "/"},
|
||||
{" %", "%"},
|
||||
{"% ", "%"},
|
||||
{" =", "="},
|
||||
{"= ", "="},
|
||||
{" -", "-"},
|
||||
{"- ", "-"},
|
||||
{" +", "+"},
|
||||
{"+ ", "+"},
|
||||
{".. ", ".."},
|
||||
{" ..", ".."},
|
||||
{"\"\" ", "\"\""},
|
||||
{"=0 t", "=0t"},
|
||||
{">0 t", ">0t"},
|
||||
{">1 t", ">1t"},
|
||||
{"=1 w", "=1w"},
|
||||
{"=380 l", "=380l"},
|
||||
{"=127 t", "=127t"},
|
||||
{"<128 t", "<128t"},
|
||||
{"=128 t", "=128t"},
|
||||
{">255 t", ">255t"},
|
||||
{"=512 t", "=512t"}
|
||||
}
|
||||
|
||||
local function pass(buffer)
|
||||
local ob = ""
|
||||
local smode = false
|
||||
while #buffer > 0 do
|
||||
if not smode then
|
||||
local ds = true
|
||||
while ds do
|
||||
ds = false
|
||||
for _, v in ipairs(sequences) do
|
||||
if buffer:sub(1, #(v[1])) == v[1] then
|
||||
buffer = v[2] .. buffer:sub(#(v[1]) + 1)
|
||||
ds = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local ch = buffer:sub(1, 1)
|
||||
buffer = buffer:sub(2)
|
||||
ob = ob .. ch
|
||||
if ch == "\"" then
|
||||
smode = not smode
|
||||
end
|
||||
end
|
||||
return ob
|
||||
end
|
||||
|
||||
-- Context creation --
|
||||
return function ()
|
||||
local forwardSymTab = {}
|
||||
local reverseSymTab = {}
|
||||
|
||||
local temporaryPool = {}
|
||||
|
||||
local stackFrames = {}
|
||||
|
||||
local log = {}
|
||||
|
||||
local possible = {}
|
||||
for i = 1, 52 do
|
||||
possible[i] = ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"):sub(i, i)
|
||||
end
|
||||
|
||||
local function allocate(reason)
|
||||
for _, v in pairs(possible) do
|
||||
if not reverseSymTab[v] then
|
||||
reverseSymTab[v] = reason
|
||||
return v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function allocTmp(id)
|
||||
assert(not forwardSymTab[id], "var already exists: " .. id)
|
||||
local val = table.remove(temporaryPool, 1)
|
||||
if not val then val = allocate("temporary") end
|
||||
forwardSymTab[id] = val
|
||||
table.insert(log, "allocTmp " .. id .. " -> " .. val)
|
||||
return val
|
||||
end
|
||||
|
||||
local lexCrunch = {}
|
||||
function lexCrunch.dump(file)
|
||||
file:write("forward table:\n")
|
||||
for k, v in pairs(forwardSymTab) do
|
||||
file:write(k .. " -> " .. v .. "\n")
|
||||
end
|
||||
file:write("reverse table (where differing):\n")
|
||||
for k, v in pairs(reverseSymTab) do
|
||||
if forwardSymTab[v] ~= k then
|
||||
file:write(v .. " -> " .. k .. "\n")
|
||||
end
|
||||
end
|
||||
file:write("log:\n")
|
||||
for k, v in ipairs(log) do
|
||||
file:write(v .. "\n")
|
||||
end
|
||||
end
|
||||
function lexCrunch.process(op, defines)
|
||||
-- symbol replacement
|
||||
op = op:gsub("%$[%$a-z%{%}%|A-Z0-9]*", function (str)
|
||||
if str:sub(2, 2) == "$" then
|
||||
-- defines
|
||||
assert(defines[str], "no define " .. str)
|
||||
return defines[str]
|
||||
end
|
||||
local com = {}
|
||||
for v in str:sub(2):gmatch("[^%|]*") do
|
||||
table.insert(com, v)
|
||||
end
|
||||
if com[1] == "L" then
|
||||
assert(#com == 2)
|
||||
local id = "$" .. com[2]
|
||||
assert(stackFrames[1], "allocation of " .. id .. " outside of stack frame")
|
||||
table.insert(stackFrames[1], id)
|
||||
return allocTmp(id)
|
||||
elseif com[1] == "{" then
|
||||
assert(#com == 1)
|
||||
table.insert(stackFrames, 1, {})
|
||||
return ""
|
||||
elseif com[1] == "}" then
|
||||
assert(#com == 1)
|
||||
for _, id in ipairs(table.remove(stackFrames, 1)) do
|
||||
table.insert(temporaryPool, forwardSymTab[id])
|
||||
forwardSymTab[id] = nil
|
||||
end
|
||||
return ""
|
||||
else
|
||||
assert(#com == 1)
|
||||
local id = "$" .. com[1]
|
||||
-- normal handling
|
||||
if forwardSymTab[id] then
|
||||
return forwardSymTab[id]
|
||||
end
|
||||
local v = allocate(id)
|
||||
forwardSymTab[id] = v
|
||||
return v
|
||||
end
|
||||
end)
|
||||
-- comment removal
|
||||
while true do
|
||||
local np = op:gsub("%-%-[^\n]*\n", " ")
|
||||
np = np:gsub("%-%-[^\n]*$", "")
|
||||
if np == op then
|
||||
break
|
||||
end
|
||||
op = np
|
||||
end
|
||||
-- stripping
|
||||
while true do
|
||||
local np = pass(op)
|
||||
if np == op then
|
||||
return np
|
||||
end
|
||||
op = np
|
||||
end
|
||||
return op
|
||||
end
|
||||
return lexCrunch
|
||||
end
|
@ -1,40 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- Status Screen --
|
||||
local target = ...
|
||||
local u = require("libs.frw")
|
||||
local instSize = #u.read(target)
|
||||
|
||||
local status = ""
|
||||
local statusDetail = ""
|
||||
local blinkI = ""
|
||||
if instSize > 65536 then
|
||||
blinkI = "5;31;"
|
||||
status = " DO NOT SHIP "
|
||||
statusDetail = "The installer is too big to ship safely.\nIt's possible it may crash on Tier 1 systems.\nUpgrade the compression system or remove existing code."
|
||||
elseif instSize > 64000 then
|
||||
blinkI = "33;"
|
||||
status = " Shippable * "
|
||||
statusDetail = "The installer is getting dangerously large.\nReserve further room for bugfixes."
|
||||
else
|
||||
blinkI = "32;"
|
||||
status = " All Green "
|
||||
statusDetail = "The installer is well within budget with room for features.\nDevelop as normal."
|
||||
end
|
||||
io.stderr:write("\n")
|
||||
local ctS, ctM, ctE = " \x1b[1;" .. blinkI .. "7m", "\x1b[0;7m", "\x1b[0m\n"
|
||||
io.stderr:write(ctS .. " " .. ctM .. " " .. ctE)
|
||||
io.stderr:write(ctS .. status .. ctM .. string.format(" %07i ", 65536 - instSize) .. ctE)
|
||||
io.stderr:write(ctS .. " " .. ctM .. " " .. ctE)
|
||||
io.stderr:write("\n")
|
||||
io.stderr:write(statusDetail .. "\n")
|
||||
io.stderr:write("\n")
|
||||
io.stderr:write("Size: " .. instSize .. "\n")
|
||||
io.stderr:write(" max. 65536\n")
|
||||
io.stderr:write("\n")
|
||||
|
@ -1,32 +0,0 @@
|
||||
# The Symbol Guide
|
||||
|
||||
## lexCrunch commands
|
||||
|
||||
The following prefixes are really special,
|
||||
and are lexcrunch's responsibility:
|
||||
|
||||
"$$THING" : These are defines.
|
||||
"$Thing" : Writes a global into stream. If not already allocated, is allocated a global.
|
||||
|
||||
"${" : Opens a frame.
|
||||
"$}" : Closes a frame. (Attached temps are released.)
|
||||
"$L|THING" : Allocates THING from temp pool, attaches to stack frame, writes to stream.
|
||||
Use inside a comment to erase the written symbol
|
||||
|
||||
## Conventions
|
||||
|
||||
The rest are convention:
|
||||
"$iThing" symbols are Installer Wrapper.
|
||||
"$icThing" symbols are Installer Core.
|
||||
"$dfThing" symbols are DEFLATE Engine.
|
||||
"$bdThing" symbols are BDIVIDE Engine.
|
||||
|
||||
"$a0", "$a1", etc. are Local Symbols.
|
||||
DEPRECATED, THESE ARE AN OLD MECHANISM, USE FRAMED TEMPS INSTEAD.
|
||||
These are reserved only for use in locals.
|
||||
(For loops count.)
|
||||
|
||||
"$lThing" symbols are used to name Local Symbols using aliases.
|
||||
|
||||
NO THEY ARE NOW USED FOR ALL TEMPS, INCLUDING LOCAL SYMBOLS
|
||||
|
@ -1,14 +0,0 @@
|
||||
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
-- THIS SOFTWARE.
|
||||
|
||||
-- Example compression engine.
|
||||
-- Given: data, lexCrunch
|
||||
-- returns compressionEngine, compressedData
|
||||
return function (data, lexCrunch)
|
||||
return lexCrunch.process(" $engineInput = $engineOutput ", {}), data
|
||||
end
|
||||
|
97
insthead.lua
Normal file
97
insthead.lua
Normal file
@ -0,0 +1,97 @@
|
||||
-- KOSNEO inst.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
C, O, G, D = component, computer
|
||||
assert(C, "To install, please copy as init.lua to a blank disk or a system to update, then remove all other disks and reboot.")
|
||||
|
||||
sa = C.list("screen", true)()
|
||||
if sa then
|
||||
G = C.list("gpu", true)()
|
||||
if G then
|
||||
G = C.proxy(G)
|
||||
G.bind(sa)
|
||||
G.setForeground(0xFFFFFF)
|
||||
G.setBackground(0x000000)
|
||||
G.setResolution(50, 5)
|
||||
G.setDepth(1)
|
||||
G.fill(1, 1, 50, 5, " ")
|
||||
G.setBackground(0xFFFFFF)
|
||||
G.setForeground(0x000000)
|
||||
G.fill(1, 2, 50, 1, " ")
|
||||
G.set(2, 2, "KittenOS NEO Installer")
|
||||
end
|
||||
end
|
||||
|
||||
D = C.proxy(O.getBootAddress())
|
||||
|
||||
tFN,tFSR,tW,tF="Starting...",0,0
|
||||
|
||||
function tO(oct)
|
||||
local v = oct:byte(#oct) - 0x30
|
||||
if #oct > 1 then
|
||||
return (tO(oct:sub(1, #oct - 1)) * 8) + v
|
||||
end
|
||||
return v
|
||||
end
|
||||
function tA(s)
|
||||
if tW > 0 then
|
||||
tW = tW - 1
|
||||
return
|
||||
end
|
||||
if tF then
|
||||
local ta = math.min(512, tFSR)
|
||||
D.write(tF, s:sub(1, ta))
|
||||
tFSR = tFSR - ta
|
||||
if tFSR == 0 then
|
||||
D.close(tF)
|
||||
tF = nil
|
||||
end
|
||||
else
|
||||
tFN = s:sub(1, 100):gsub("\x00", "")
|
||||
local sz = tO(s:sub(125, 135))
|
||||
if tFN:sub(1, 5) ~= "code/" then
|
||||
tW = math.ceil(sz / 512)
|
||||
else
|
||||
tFN = tFN:sub(6)
|
||||
if tFN == "" then
|
||||
return
|
||||
end
|
||||
if tFN:sub(#tFN) == "/" then
|
||||
tW = math.ceil(sz / 512)
|
||||
D.makeDirectory(tFN)
|
||||
else
|
||||
tF = D.open(tFN, "wb")
|
||||
tFSR = sz
|
||||
if tFSR == 0 then
|
||||
D.close(tF)
|
||||
tF = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sN, sC = 0, 0
|
||||
|
||||
function sector(n)
|
||||
tA(n)
|
||||
sN = sN + 1
|
||||
if G then
|
||||
local a = sN / sC
|
||||
G.fill(1, 2, 50, 1, " ")
|
||||
G.set(2, 2, "KittenOS NEO Installer : " .. tFN)
|
||||
G.setForeground(0xFFFFFF)
|
||||
G.setBackground(0x000000)
|
||||
G.fill(2, 4, 48, 1, " ")
|
||||
G.setBackground(0xFFFFFF)
|
||||
G.setForeground(0x000000)
|
||||
G.fill(2, 4, math.ceil(48 * a), 1, " ")
|
||||
end
|
||||
if sN % 8 == 0 then
|
||||
O.pullSignal(0.05)
|
||||
end
|
||||
if sN == sC then
|
||||
dieCB()
|
||||
O.shutdown(true)
|
||||
end
|
||||
end
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
["components"]={
|
||||
{"screen","67c66973-51ff-4aec-29cd-baabf2fbe346",},
|
||||
{"gpu","9b7fe47d-77d0-1623-0dc5-126752e3f2c7",44800,},
|
||||
{"eeprom","94a9cc26-347e-cc46-7faf-0c131bb7d8b7",4096,256,"EEPROM",},
|
||||
{"computer","36bc34ad-8c4a-d19a-10e3-0162c6f3295a",1.04858e+06,},
|
||||
{"filesystem","tmpfs",true,"tmpfs",},
|
||||
{"filesystem","c1-sda",},
|
||||
{"filesystem","c1-sdb",},
|
||||
{"keyboard","dd142450-613c-435d-6049-743b27434cc1","67c66973-51ff-4aec-29cd-baabf2fbe346",},
|
||||
{"modem","460ae893-9aa9-f10d-6bb0-462199da7376",56000,8192,8,},
|
||||
{"internet","ef97c750-d30a-ad33-5321-6e7a64ba3baa",true,true,},
|
||||
{"data","c5243e5f-cd2f-6c39-dfb2-5a788dcdef7c",["tier"]=1,},
|
||||
{"sandbox","ece7b9ba-1625-f3f6-d74d-6e641a5de07f",},
|
||||
},
|
||||
["system"]={["allowBytecode"]=false,["allowGC"]=false,["maxTcpConnections"]=4,["timeout"]=math.huge,},
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
# THIS SOFTWARE.
|
||||
|
||||
ocvm .
|
140
laboratory/ocemu.cfg
Normal file
140
laboratory/ocemu.cfg
Normal file
@ -0,0 +1,140 @@
|
||||
--OCEmu configuration. Designed to mimic HOCON syntax, but is not exactly HOCON
|
||||
--syntax.
|
||||
ocemu {
|
||||
|
||||
--Client side settings, presentation and performance related stuff.
|
||||
client {
|
||||
|
||||
--The sample rate used for generating beeps of computers' internal speakers.
|
||||
--Use custom values at your own responsibility here; if it breaks OC you'll
|
||||
--get no support. Some potentially reasonable lower values are 16000 or even
|
||||
--8000 (which was the old default, but leads to artifacting on certain
|
||||
--frequencies).
|
||||
beepSampleRate=44100
|
||||
|
||||
--The base volume of beeps generated by computers. This may be in a range of
|
||||
--[0, 127], where 0 means mute (the sound will not even be generated), and
|
||||
--127 means maximum amplitude / volume.
|
||||
beepVolume=32
|
||||
|
||||
--The color of monochrome text (i.e. displayed when in 1-bit color depth,
|
||||
--e.g. tier one screens / GPUs, or higher tier set to 1-bit color depth).
|
||||
--Defaults to white, feel free to make it some other color, tho!
|
||||
monochromeColor="0xFFFFFF"
|
||||
}
|
||||
|
||||
--Computer related settings, concerns server performance and security.
|
||||
computer {
|
||||
|
||||
--The maximum size of the byte array that can be stored on EEPROMs as
|
||||
--configuration data.
|
||||
eepromDataSize=256
|
||||
|
||||
--The maximum size of the byte array that can be stored on EEPROMs as
|
||||
--executable data..
|
||||
eepromSize=4096
|
||||
|
||||
--Settings specific to the Lua architecture.
|
||||
lua {
|
||||
|
||||
--Whether to allow loading precompiled bytecode via Lua's `load` function,
|
||||
--or related functions (`loadfile`, `dofile`). Enable this only if you
|
||||
--absolutely trust all users on your server and all Lua code you run. This
|
||||
--can be a MASSIVE SECURITY RISK, since precompiled code can easily be
|
||||
--used for exploits, running arbitrary code on the real server! I cannot
|
||||
--stress this enough: only enable this is you know what you're doing.
|
||||
allowBytecode=false
|
||||
|
||||
--Whether to allow user defined __gc callbacks, i.e. __gc callbacks
|
||||
--defined *inside* the sandbox. Since garbage collection callbacks are not
|
||||
--sandboxed (hooks are disabled while they run), this is not recommended.
|
||||
allowGC=false
|
||||
}
|
||||
|
||||
--The time in seconds a program may run without yielding before it is
|
||||
--forcibly aborted. This is used to avoid stupidly written or malicious
|
||||
--programs blocking other computers by locking down the executor threads.
|
||||
--Note that changing this won't have any effect on computers that are
|
||||
--already running - they'll have to be rebooted for this to take effect.
|
||||
timeout=5
|
||||
}
|
||||
|
||||
--Emulator related settings. Components, accuracy, and debugging.
|
||||
emulator {
|
||||
|
||||
--Default components available to the computer.
|
||||
components {
|
||||
|
||||
{"gpu", "c1-gpu-tier3", 0, 160, 50, 3},
|
||||
{"gpu", "c1-gpu-tier1", 0, 50, 16, 1},
|
||||
{"screen_sdl2", "c1-screen-tier3", -1, 160, 50, 3},
|
||||
{"screen_sdl2", "c1-screen-tier1", -1, 50, 16, 1},
|
||||
{"modem", "c1-modem", 1, false},
|
||||
{"eeprom", "c1-eeprom", 9, "lua/bios.lua"},
|
||||
{"filesystem", "c1-tmpfs", -1, "tmpfs", "tmpfs", false, 5},
|
||||
{"filesystem", "c1-sda", 5, nil, "Workbench", false, 4},
|
||||
{"filesystem", "c1-sdb", 5, nil, "Repository", false, 4},
|
||||
{"filesystem", "openos", 0, "loot/openos", "openos", true, 1},
|
||||
{"internet", "c1-internet", 2},
|
||||
{"computer", "c1-computer", -1},
|
||||
{"ocemu", "c1-ocemu", -1},
|
||||
{"keyboard_sdl2", "c1-keyboard", -1}
|
||||
}
|
||||
|
||||
--Whether to enable the emulator's extremely verbose logging.
|
||||
debug=false
|
||||
|
||||
--Whether to choose performance over timing-accuracy.
|
||||
fast=false
|
||||
|
||||
--Whether to return vague error messages like OpenComputers.
|
||||
vague=false
|
||||
}
|
||||
|
||||
filesystem {
|
||||
|
||||
--The maximum block size that can be read in one 'read' call on a file
|
||||
--system. This is used to limit the amount of memory a call from a user
|
||||
--program can cause to be allocated on the host side: when 'read' is, called
|
||||
--a byte array with the specified size has to be allocated. So if this
|
||||
--weren't limited, a Lua program could trigger massive memory allocations
|
||||
--regardless of the amount of RAM installed in the computer it runs on. As a
|
||||
--side effect this pretty much determines the read performance of file
|
||||
--systems.
|
||||
maxReadBuffer=2048
|
||||
}
|
||||
|
||||
internet {
|
||||
|
||||
--Whether to allow HTTP requests via internet cards. When enabled, the
|
||||
--`request` method on internet card components becomes available.
|
||||
enableHttp=true
|
||||
|
||||
--Whether to allow TCP connections via internet cards. When enabled, the
|
||||
--`connect` method on internet card components becomes available.
|
||||
enableTcp=true
|
||||
}
|
||||
|
||||
--Other settings that you might find useful to tweak.
|
||||
misc {
|
||||
|
||||
--The maximum size of network packets to allow sending via network cards.
|
||||
--This has *nothing to do* with real network traffic, it's just a limit for
|
||||
--the network cards, mostly to reduce the chance of computer with a lot of
|
||||
--RAM killing those with less by sending huge packets. This does not apply
|
||||
--to HTTP traffic.
|
||||
maxNetworkPacketSize=8192
|
||||
|
||||
--The maximum distance a wireless message can be sent. In other words, this
|
||||
--is the maximum signal strength a wireless network card supports. This is
|
||||
--used to limit the search range in which to check for modems, which may or
|
||||
--may not lead to performance issues for ridiculous ranges - like, you know,
|
||||
--more than the loaded area. See also: `wirelessCostPerRange`.
|
||||
maxWirelessRange=400
|
||||
}
|
||||
|
||||
--The configuration version this config was generated at. This is used to
|
||||
--allow the emulator to reset/migrate parts of the config when their meaning
|
||||
--has changed across versions.
|
||||
version=3
|
||||
}
|
@ -4,7 +4,7 @@ ocemu {
|
||||
{"gpu", "c1-gpu-tier3", 0, 160, 50, 3},
|
||||
{"gpu", "c1-gpu-tier1", 0, 50, 16, 1},
|
||||
{"screen_sdl2", "c1-screen-tier3", -1, 160, 50, 3},
|
||||
-- {"screen_sdl2", "c1-screen-tier1", -1, 50, 16, 1},
|
||||
{"screen_sdl2", "c1-screen-tier1", -1, 50, 16, 1},
|
||||
{"modem", "c1-modem", 1, false},
|
||||
{"eeprom", "c1-eeprom", 9, "lua/bios.lua"},
|
||||
{"filesystem", "c1-tmpfs", -1, "tmpfs", "tmpfs", false, 5},
|
||||
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This is released into the public domain.
|
||||
# No warranty is provided, implied or otherwise.
|
||||
|
||||
cp ocemu.cfg.default ocemu.cfg && rm -rf c1-sda c1-sdb tmpfs
|
||||
mkdir c1-sda c1-sdb
|
||||
echo -n c1-sda > c1-eeprom/data.bin
|
||||
cd ..
|
||||
./package.sh $*
|
||||
cp inst.lua laboratory/c1-sda/init.lua
|
@ -3,8 +3,11 @@
|
||||
# This is released into the public domain.
|
||||
# No warranty is provided, implied or otherwise.
|
||||
|
||||
cp ocemu.cfg.default ocemu.cfg && rm -rf c1-sda c1-sdb
|
||||
cp ocemu.cfg.default ocemu.cfg && rm -rf c1-sda c1-sdb tmpfs
|
||||
mkdir c1-sda c1-sdb
|
||||
echo -n c1-sda > c1-eeprom/data.bin
|
||||
|
||||
./update.sh
|
||||
cd ..
|
||||
cp -r code/* laboratory/c1-sdb/
|
||||
cp -r repository/* laboratory/c1-sdb/
|
||||
lua clawmerge.lua repository/data/app-claw/local.lua code/data/app-claw/local.lua > laboratory/c1-sdb/data/app-claw/local.lua
|
||||
cp -r laboratory/c1-sdb/* laboratory/c1-sda/
|
||||
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This is released into the public domain.
|
||||
# No warranty is provided, implied or otherwise.
|
||||
|
||||
cd ..
|
||||
cp -r code/* laboratory/c1-sdb/
|
||||
cp -r repository/* laboratory/c1-sdb/
|
||||
lua claw/clawconv.lua laboratory/c1-sdb/data/app-claw/ < claw/code-claw.lua > /dev/null
|
||||
lua claw/clawconv.lua laboratory/c1-sdb/data/app-claw/ < claw/repo-claw.lua >> /dev/null
|
||||
cp -r laboratory/c1-sdb/* laboratory/c1-sda/
|
28
mkucinst.lua
Normal file
28
mkucinst.lua
Normal file
@ -0,0 +1,28 @@
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
os.execute("tar -cf code.tar code")
|
||||
os.execute("cat insthead.lua > inst.lua")
|
||||
local f = io.open("inst.lua", "ab")
|
||||
|
||||
local df = io.open("code.tar", "rb")
|
||||
local sc = 0
|
||||
while true do
|
||||
local d = df:read(512)
|
||||
if not d then break end
|
||||
sc = sc + 1
|
||||
end
|
||||
df:close()
|
||||
local df = io.open("code.tar", "rb")
|
||||
f:write("dieCB = function () end")
|
||||
f:write("sC = " .. sc .. "\n")
|
||||
while true do
|
||||
local d = df:read(512)
|
||||
if d then
|
||||
f:write(string.format("sector(%q)", d))
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
df:close()
|
||||
f:close()
|
11
package-gold.sh
Executable file
11
package-gold.sh
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This is released into the public domain.
|
||||
# No warranty is provided, implied or otherwise.
|
||||
|
||||
stat repobuild/data/app-claw/local.lua && rm -rf repobuild
|
||||
mkdir repobuild
|
||||
cp -r code/* repobuild/
|
||||
cp -r repository/* repobuild/
|
||||
cp inst-gold.lua repobuild/inst.lua
|
||||
lua clawmerge.lua repository/data/app-claw/local.lua code/data/app-claw/local.lua > repobuild/data/app-claw/local.lua
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
# THIS SOFTWARE.
|
||||
|
||||
./package.sh bdvlite deflate
|
||||
|
@ -1,21 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
# THIS SOFTWARE.
|
||||
|
||||
# Package repository using supplied inst.lua (use inst-gold.lua for repository branch)
|
||||
|
||||
# this is a guard check to avoid removing repobuild if it's blatantly
|
||||
# not the actual repobuild directory (this is an rm -rf after all)
|
||||
stat repobuild/data/app-claw 1>/dev/null 2>/dev/null && rm -rf repobuild
|
||||
|
||||
mkdir -p repobuild
|
||||
cp -r code/* repobuild/
|
||||
cp -r repository/* repobuild/
|
||||
cp $1 repobuild/inst.lua
|
||||
lua claw/clawconv.lua repobuild/data/app-claw/ < claw/code-claw.lua > repobuild/data/app-claw/local.c2l
|
||||
lua claw/clawconv.lua repobuild/data/app-claw/ < claw/repo-claw.lua >> repobuild/data/app-claw/local.c2l
|
33
package.sh
33
package.sh
@ -1,27 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2018-2021 by KittenOS NEO contributors
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
# THIS SOFTWARE.
|
||||
# This is released into the public domain.
|
||||
# No warranty is provided, implied or otherwise.
|
||||
|
||||
rm code/data/app-claw/*
|
||||
mkdir -p code/data/app-claw
|
||||
lua claw/clawconv.lua code/data/app-claw/ < claw/code-claw.lua > /dev/null
|
||||
rm code.tar
|
||||
# Hey, look behind you, there's nothing to see here.
|
||||
# ... ok, are they seriously all named "Mann"?
|
||||
cd code
|
||||
tar --mtime=0 --owner=gray:0 --group=mann:0 -cf ../code.tar .
|
||||
cd ..
|
||||
tar --owner=gray:0 --group=mann:0 -cf code.tar code
|
||||
lua heroes.lua `wc -c code.tar` | lua bonecrunch.lua > inst.lua
|
||||
echo -n "--[[" >> inst.lua
|
||||
cat com2/code.tar.bd >> inst.lua
|
||||
echo -n "]]" >> inst.lua
|
||||
|
||||
# The Installer Creator
|
||||
cd inst
|
||||
lua build.lua `git status --porcelain=2 --branch | grep branch.oid | grep -E -o "[0-9a-f]*$" -` ../code.tar $* > ../inst.lua
|
||||
lua status.lua ../inst.lua
|
||||
cd ..
|
||||
|
||||
# Common Repository Setup Code
|
||||
./package-repo.sh inst.lua
|
||||
stat repobuild/data/app-claw/local.lua && rm -rf repobuild
|
||||
mkdir repobuild
|
||||
cp -r code/* repobuild/
|
||||
cp -r repository/* repobuild/
|
||||
cp inst.lua repobuild/
|
||||
lua clawmerge.lua repository/data/app-claw/local.lua code/data/app-claw/local.lua > repobuild/data/app-claw/local.lua
|
||||
|
609
preSH-Ancient-Est-2-10-2017.lua
Normal file
609
preSH-Ancient-Est-2-10-2017.lua
Normal file
@ -0,0 +1,609 @@
|
||||
-- KOSNEO inst.
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- PADPADPADPADPADPADPADPAD
|
||||
|
||||
local C, O, G, D = component, computer
|
||||
local sAddr = C.list("screen", true)()
|
||||
if sAddr then
|
||||
G = C.list("gpu", true)()
|
||||
if G then
|
||||
G = C.proxy(G)
|
||||
G.bind(sAddr)
|
||||
G.setForeground(0xFFFFFF)
|
||||
G.setBackground(0x000000)
|
||||
G.setResolution(50, 5)
|
||||
G.setDepth(1)
|
||||
G.fill(1, 1, 50, 5, " ")
|
||||
G.setBackground(0xFFFFFF)
|
||||
G.setForeground(0x000000)
|
||||
G.fill(1, 2, 50, 1, " ")
|
||||
G.set(2, 2, "KittenOS NEO Installer")
|
||||
end
|
||||
end
|
||||
|
||||
D = C.proxy(O.getBootAddress())
|
||||
|
||||
local file = nil
|
||||
local fileName = "Starting..."
|
||||
local fileSizeRm = 0
|
||||
local ws = 0
|
||||
|
||||
local convoct
|
||||
convoct = function (oct)
|
||||
local v = oct:byte(#oct) - 0x30
|
||||
if #oct > 1 then
|
||||
return (convoct(oct:sub(1, #oct - 1)) * 8) + v
|
||||
end
|
||||
return v
|
||||
end
|
||||
local function sectorCore(sector)
|
||||
if ws > 0 then
|
||||
ws = ws - 1
|
||||
return
|
||||
end
|
||||
if file then
|
||||
local takeaway = math.min(512, fileSizeRm)
|
||||
D.write(file, sector:sub(1, takeaway))
|
||||
fileSizeRm = fileSizeRm - takeaway
|
||||
if fileSizeRm == 0 then
|
||||
D.close(file)
|
||||
file = nil
|
||||
end
|
||||
else
|
||||
local name = sector:sub(1, 100):gsub("\x00", "")
|
||||
local sz = convoct(sector:sub(125, 135))
|
||||
if name:sub(1, 5) ~= "code/" then
|
||||
ws = math.ceil(sz / 512)
|
||||
else
|
||||
if name:sub(#name, #name) == "/" then
|
||||
ws = math.ceil(sz / 512)
|
||||
D.makeDirectory(name:sub(6))
|
||||
else
|
||||
fileName = name:sub(6)
|
||||
file = D.open(fileName, "wb")
|
||||
fileSizeRm = sz
|
||||
if file then
|
||||
if fileSizeRm == 0 then
|
||||
D.close(file)
|
||||
file = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local dieCB = function () end
|
||||
|
||||
local sectorNum = 0
|
||||
local sectorCount = 0
|
||||
|
||||
local function sector(n)
|
||||
sectorCore(n)
|
||||
sectorNum = sectorNum + 1
|
||||
if G then
|
||||
local a = sectorNum / sectorCount
|
||||
G.fill(1, 2, 50, 1, " ")
|
||||
G.set(2, 2, "KittenOS NEO Installer : " .. fileName)
|
||||
G.setForeground(0xFFFFFF)
|
||||
G.setBackground(0x000000)
|
||||
G.fill(2, 4, 48, 1, " ")
|
||||
G.setBackground(0xFFFFFF)
|
||||
G.setForeground(0x000000)
|
||||
G.fill(2, 4, math.ceil(48 * a), 1, " ")
|
||||
end
|
||||
if sectorNum % 8 == 0 then
|
||||
O.pullSignal(0.05)
|
||||
end
|
||||
if sectorNum == sectorCount then
|
||||
dieCB()
|
||||
O.shutdown(true)
|
||||
end
|
||||
end
|
||||
|
||||
sectorCount = 260
|
||||
D.remove("init-symsear.lua")
|
||||
D.rename("init.lua", "init-symsear.lua")
|
||||
local instHandle = D.open("init-symsear.lua", "rb")
|
||||
dieCB = function ()
|
||||
D.close(instHandle)
|
||||
D.remove("init-symsear.lua")
|
||||
end
|
||||
local syms = {" ","s","e","t","a","i","\24","(","r",".","\
|
||||
","p","\"","o","c","m",", ","\1","l","n",")","d","u","\17","\9","x","-","\7","\6","\8","\4","\13","\2","\3","\5","g","\14","\21","\11"," then\
|
||||
","1","w"," ","\12","\18","\22","f","F","y",",","\20","re","b","k"," = ","\23","return "," local ","\16","v"," if ","\
|
||||
","\15","\19","\
|
||||
"," ","[","en","/","0","]","path","nction (","\
|
||||
","se","h"," =","or","S","T","le","\
|
||||
local ",")\
|
||||
","= fu","on"," == ","ne",")\
|
||||
","functio","\
|
||||
end\
|
||||
","D","{"," t","n ","oc","lo"," end\
|
||||
","\0\0\0\0\0\0\0\0\0","un"," i","W","\0\0\0\0\0\0","fu","et"," end\
|
||||
","then ","nd","ni","A","ing"," tab","loca","etting",")\
|
||||
","ct","C","P","}","\
|
||||
end\
|
||||
",")\
|
||||
","onit","= ","end\
|
||||
","\0","I","Y"," do\
|
||||
","return\
|
||||
","le.inser"," = func","= \"","al"," r"," e","in","he","nc"," e","j","donkonit","tion ()",") do\
|
||||
"," the","\
|
||||
",")\
|
||||
","ur","#","+","N","cursor",".inse",", v ","nction (w"," neo.req"," for "," then\
|
||||
","\0\0\0\0\0\0\0","nd\
|
||||
","()\
|
||||
","neo.","ath","table","l ","do","2","3",":","H"," = nil\
|
||||
","nd\
|
||||
e","hen\
|
||||
","\7local ","indowCore",")\
|
||||
end\
|
||||
","d\") end\
|
||||
"," = false","if ","pairs(","dow","string\"","ti","O","uestAcces","nd\
|
||||
if ","icode."," if","v in ","pkg, pid","000","750\0000001","end\
|
||||
e","750\0000000"," else\
|
||||
","window","end","00",".neo.sys.","neoux.tc","= {}\
|
||||
","(window, ","5","=","E","R",") end\
|
||||
"," cursor","request","ode/app"," return e","\" the","equire("," "," then",".neo.pub.","hile true"," end"," en","\0\0","B","M"," ret","for ","in ipai"," true\
|
||||
","close","code.sub","error(\"","return t","oroutine"," end\
|
||||
if","end\
|
||||
en","tion ","\", funct",":sub(","vailable"," end\
|
||||
"," l"," == \"","prima"," if type(","ryWindow","window.s"," end\
|
||||
","L","X","~","on ("," in ipair"," for _, v"," for k","\0\0\0\0\0cod","lose()\
|
||||
"," = funct","rror(\"Exp","nsurePath","s.primary","primary","buildingS","unic"," "," re","surfaces","disallowe","ackground","neoux.","ccess","selectUnk"," end\
|
||||
"," = uni","\
|
||||
end\
|
||||
"," f","7","Z","z","for k","rue\
|
||||
end\
|
||||
","ode.len("," end\
|
||||
","lse\
|
||||
",") end","end\
|
||||
"," fu",":sub(1, ","sub(1, 4)"," ","neo","the","if not "," th","tion","unknownA","end\
|
||||
","[1] == \"","= unico","Acces","\
|
||||
end\
|
||||
\
|
||||
l","n\
|
||||
","\") end\
|
||||
","de.len("," end","\" then\
|
||||
","0\0000001","urface","nd\
|
||||
","()\
|
||||
","(surfaces"," if ","\0\0\0\0\0\0\0\0","unc","urn","\
|
||||
"," end\
|
||||
"," neoux","ction","\
|
||||
end\
|
||||
","\
|
||||
","neoux","\24\0\0\0\0\0\0\0\0","\
|
||||
end"," end\
|
||||
end\
|
||||
","\
|
||||
end\
|
||||
"," if "," err","s[1] == \"","unicode."," window"," if ","ocal fun","= false","\0\0\0\0\0\0\0000","\0\0\0\0\0\0\00000","code","_, v in i","()\
|
||||
","d\
|
||||
","f ev == \""," return",", bg, fg"," end"," neoux.","\0\0\0","w.close(","\
|
||||
if ev"," i"," if not ","if kc == ",")\
|
||||
end\
|
||||
","indow","onkonit","00175","table.",", bg, fg)"," l"," end\
|
||||
",") == \"","d\
|
||||
"," return ","rn","ca","q"," tabl"," error(\"","end\
|
||||
re"," in ","hen err","nd\
|
||||
en","nd\
|
||||
","\
|
||||
end","turn ","x.neo.","ion ("," table","false","string","e.len(","d\
|
||||
"," re","1, unicod","cursorX ","local ","end\
|
||||
end\
|
||||
","cal","\" then e","nd\
|
||||
if k","ion","00644\00000"," end\
|
||||
","\
|
||||
end"," window."," e","if not","== \"",", func"," neo.",", functi","\
|
||||
end\
|
||||
end"," r","end\
|
||||
","ion (w)\
|
||||
","\
|
||||
end"," = false\
|
||||
"," ret","tu"," end\
|
||||
","f ","unction","= nil\
|
||||
","th","n\
|
||||
","6","U","_","requir","eturn\
|
||||
"," funct","eturn tr","\
|
||||
\
|
||||
local"," table.","eques","rn ",")\
|
||||
r",".insert(","ode.",")\
|
||||
end","== ","\0\0\0\0\0\0\0c","n\
|
||||
","\0\0\0\0\0","()\
|
||||
"," = nil","able.","n\
|
||||
"," = n","return","000644\0000","Access","able","etu","d\
|
||||
","\
|
||||
if ","end\
|
||||
end","nction (p","ub(1, 4) "," return "," return","lse\
|
||||
","abl","= uni","for k, ","\0\0\0\0\0\0\0\0c","cursorY","ble","bg, fg)\
|
||||
","\
|
||||
e","ind","ret","tring\"","000000"," neo","pairs","then\
|
||||
",")\
|
||||
","le.inse","loc","\
|
||||
end","n error","\
|
||||
end\
|
||||
\
|
||||
","if s[1] =","lse\
|
||||
","turn","ursor","function","neou","\0\0\0\0\0\0c","function ","\0000001","end\
|
||||
e","eo.","Access(\""," re"," lo","\
|
||||
e",")\
|
||||
end","urn ","\
|
||||
re"," end\
|
||||
e"," = f","\0\0\0\0","cal ","\0000000644\0","in ip","\
|
||||
en"," return",")\
|
||||
i","ction ","\
|
||||
end\
|
||||
","ode","equire(\"","r(\"Expect","ctio"," cursorY","if","%","4","<","G","\
|
||||
local f","\
|
||||
ret"," for ","d\
|
||||
if"," erro","true\
|
||||
end","ed\") end","hen ","nd\
|
||||
en","al ","on ","] then\
|
||||
","string\")","for _, ","unicode.l","[1] == ","true\
|
||||
","uestAc","nd\
|
||||
end\
|
||||
"," for k, "," if ev ","then\
|
||||
","\
|
||||
en",")\
|
||||
en","do\
|
||||
","e.ins",".primary"," true","coroutine","return\
|
||||
","airs(",") end\
|
||||
","nd\
|
||||
end\
|
||||
\
|
||||
","\
|
||||
return","window, ","end\
|
||||
e","end\
|
||||
end","750\0000","eturn t",", functio"," e","d\") end","en\
|
||||
","ocal","icode.len","e\
|
||||
","n\
|
||||
","w.close()"," uni","sub(","n ipairs("," for ","end\
|
||||
","ion ()","end\
|
||||
en","quest","cursorY ","eturn","unicode.s","x.neo.pub"," = neo","hen\
|
||||
","then\
|
||||
","string\") ","in ipa"," retur","indowCor"," re","750\00000"," do\
|
||||
",")\
|
||||
if "," then ret","\") end"," en","n\
|
||||
","ipairs"," then err","d\
|
||||
en","= f"," local",".neo.","\24\0\0\0\0\0\0\0","func","()\
|
||||
",")\
|
||||
en","curs","\
|
||||
loca","ode/apps","nd\
|
||||
if "," i"," = neo.r","kg, pid, ","\
|
||||
i","win","code.sub(","require","wind"," else\
|
||||
","close()"," end\
|
||||
e","\
|
||||
\
|
||||
local "," then re","\
|
||||
e",".request","wnAvailab","tion (","\
|
||||
local ","error(","\0000001750\0","n\
|
||||
","d\
|
||||
"," ","uestA","reques","end\
|
||||
end\
|
||||
\
|
||||
","ion ()\
|
||||
"," curso","then\
|
||||
","0001750","surfac",".close("," function","= neo.","if type("," loc","d\
|
||||
e","oroutine."," do\
|
||||
"," else\
|
||||
","tion ()\
|
||||
",", v in ","window.","neo.re","0000","\000000","\
|
||||
end\
|
||||
","ipairs("," ret","\"x.neo.pu","error","\
|
||||
i","\
|
||||
end","()\
|
||||
","= nil\
|
||||
","nsert(","n erro","rror(\"","nil\
|
||||
","cursorX ="," do\
|
||||
"," for","turn f","en\
|
||||
"," table.","\
|
||||
","\") end\
|
||||
","\") end\
|
||||
",".close()\
|
||||
","\
|
||||
re","d\
|
||||
e","\
|
||||
end\
|
||||
","ownAvaila","000644\00000"," false\
|
||||
","\
|
||||
re","false\
|
||||
","ion ()\
|
||||
",")\
|
||||
e","urn end\
|
||||
",")\
|
||||
if","x.neo.sys","indow, ","then\
|
||||
",")\
|
||||
if t","cti","ion ","ion (w","\" then"," = nil\
|
||||
","then","e\" then\
|
||||
"," if","on (w)\
|
||||
",") do\
|
||||
"," en","tAccess(\"","surePath"," end\
|
||||
end","\
|
||||
end\
|
||||
","e.inse"," table.i"," local","oca","n (","0 then\
|
||||
",") end\
|
||||
"," loc","se\
|
||||
","do\
|
||||
","nd\
|
||||
end\
|
||||
"," then e","0000644\0","ion ()\
|
||||
","ocal ","end\
|
||||
if ","e\
|
||||
"," then\
|
||||
"," local","icode.le","\" then "," ==","] == \"","eoux","ndow","\0\0\0\0\0c","nownAvail"," functi","0\000000000","eoux.tc","hen error"," = neo.","table.ins"," window","(window","d\
|
||||
if ","\
|
||||
if ","\
|
||||
local","end\
|
||||
e","nd\
|
||||
end","insert("," local ","k, v i","surface","eturn ","\
|
||||
loc","sub(1, ","end\
|
||||
if ","io","!","$","&","'","*","8","9",";",">","?","@","J","K","Q","V","\\","^","|","<22>","…","ˆ","‰","Œ","<22>","Ž","<22>","<22>","’","“","”","˜","¦","¬","¼","½","Â","ï",}
|
||||
local bytBuf = ""
|
||||
local bitBuf = ""
|
||||
local function getByte()
|
||||
if bytBuf == "" then
|
||||
bytBuf = D.read(instHandle, 64)
|
||||
end
|
||||
local r = bytBuf:byte()
|
||||
bytBuf = bytBuf:sub(2)
|
||||
return r
|
||||
end
|
||||
while true do
|
||||
if getByte() == 0 then break end
|
||||
end
|
||||
local function pb(c, p) if c % (p * 2) ~= c % p then bitBuf = bitBuf .. "1" else bitBuf = bitBuf .. "0" end end
|
||||
local stn = 0
|
||||
local function getBit()
|
||||
if bitBuf == "" then
|
||||
local c = getByte()
|
||||
c = (c - stn) % 256 stn = stn + 3
|
||||
pb(c, 1)
|
||||
pb(c, 2)
|
||||
pb(c, 4)
|
||||
pb(c, 8)
|
||||
pb(c, 16)
|
||||
pb(c, 32)
|
||||
pb(c, 64)
|
||||
pb(c, 128)
|
||||
end
|
||||
local bit = bitBuf:sub(1, 1) == "1"
|
||||
bitBuf = bitBuf:sub(2)
|
||||
return bit
|
||||
end
|
||||
local buf = ""
|
||||
local mode = false
|
||||
local bc2 = 10
|
||||
while true do
|
||||
local bc = getBit()
|
||||
local v = 0
|
||||
if bc then bc = bc2 v = 64 else bc = 6 end
|
||||
for bit = 0, bc - 1 do
|
||||
if getBit() then v = v + (2 ^ bit) end
|
||||
end
|
||||
buf = buf .. syms[v]
|
||||
if mode then
|
||||
while #buf >= 512 do
|
||||
sector(buf:sub(1, 512))
|
||||
buf = buf:sub(513)
|
||||
end
|
||||
else
|
||||
if #buf == 27939 then
|
||||
stn = 0
|
||||
bc2 = 11
|
||||
bitBuf = ""
|
||||
syms = {}
|
||||
while #buf > 0 do
|
||||
local len = buf:byte()
|
||||
if len > 127 then error("symlen") end
|
||||
buf = buf:sub(2)
|
||||
local ch = buf:sub(1, len)
|
||||
buf = buf:sub(len + 1)
|
||||
table.insert(syms, ch)
|
||||
end
|
||||
mode = true
|
||||
end
|
||||
end
|
||||
end
|
||||
--[[ |