Advertisement
MAG_Gen

LZSS algorithm for CraftOS from CC:Tweaked minecraft mod.

Sep 17th, 2023 (edited)
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 48.03 KB | Source Code | 0 0
  1. --backup color
  2. local fg,bg=term.getTextColor(),term.getBackgroundColor()
  3. --init file locals
  4. local file1,file2,st_file
  5. local lzss_api={
  6. ["Original LZSS"]=[===[ --[[----------------------------------------------------------------------------
  7.  
  8.     LZSS - encoder / decoder
  9.  
  10.     This is free and unencumbered software released into the public domain.
  11.  
  12.     Anyone is free to copy, modify, publish, use, compile, sell, or
  13.     distribute this software, either in source code form or as a compiled
  14.     binary, for any purpose, commercial or non-commercial, and by any
  15.     means.
  16.  
  17.     In jurisdictions that recognize copyright laws, the author or authors
  18.     of this software dedicate any and all copyright interest in the
  19.     software to the public domain. We make this dedication for the benefit
  20.     of the public at large and to the detriment of our heirs and
  21.     successors. We intend this dedication to be an overt act of
  22.     relinquishment in perpetuity of all present and future rights to this
  23.     software under copyright law.
  24.  
  25.     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26.     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  27.     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  28.     IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  29.     OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  30.     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  31.     OTHER DEALINGS IN THE SOFTWARE.
  32.  
  33.     For more information, please refer to <http://unlicense.org/>
  34.  
  35. --]] --------------------------------------------------------------------------------------------------------------------------------------------------------
  36. local M = {}
  37. local string, table = string, table
  38.  
  39.  ------------------------------------------------------------------------------
  40. local POS_BITS = 12
  41. local LEN_BITS = 16 - POS_BITS
  42. local POS_SIZE = bit32.lshift(1,POS_BITS)
  43. local LEN_SIZE = bit32.lshift(1,LEN_BITS)
  44. local LEN_MIN = 3
  45.  
  46.  ------------------------------------------------------------------------------
  47. function M.pack(input)
  48.     local offset, output = 1, {}
  49.     local window = ''
  50.  
  51.     local function search()
  52.         for i = LEN_SIZE + LEN_MIN - 1, LEN_MIN, -1 do
  53.             local str = string.sub(input, offset, offset + i - 1)
  54.             local pos = string.find(window, str, 1, true)
  55.             if pos then
  56.                 return pos, str
  57.             end
  58.         end
  59.     end
  60.  
  61.     while offset <= #input do
  62.         local flags, buffer = 0, {}
  63.  
  64.         for i = 0, 7 do
  65.             if offset <= #input then
  66.                 local pos, str = search()
  67.                 if pos and #str >= LEN_MIN then
  68.                     local tmp = bit32.bor(bit32.lshift(pos-1,LEN_BITS), #str - LEN_MIN)
  69.                     buffer[#buffer + 1] = string.pack('>I2', tmp)
  70.                 else
  71.                     flags = bit32.bor(flags,bit32.lshift(1,i))
  72.                     str = string.sub(input, offset, offset)
  73.                     buffer[#buffer + 1] = str
  74.                 end
  75.                 window = string.sub(window .. str, -POS_SIZE)
  76.                 offset = offset + #str
  77.             else
  78.                 break
  79.             end
  80.         end
  81.  
  82.         if #buffer > 0 then
  83.             output[#output + 1] = string.char(flags)
  84.             output[#output + 1] = table.concat(buffer)
  85.         end
  86.     end
  87.  
  88.     return table.concat(output)
  89. end
  90.  
  91.  ------------------------------------------------------------------------------
  92. function l_unpack(input)
  93.     local offset, output = 1, {}
  94.     local window = ''
  95.  
  96.     while offset <= #input do
  97.         local flags = string.byte(input, offset)
  98.         offset = offset + 1
  99.  
  100.         for i = 1, 8 do
  101.             local str = nil
  102.             if bit32.band(flags,1) ~= 0 then
  103.                 if offset <= #input then
  104.                     str = string.sub(input, offset, offset)
  105.                     offset = offset + 1
  106.                 end
  107.             else
  108.                 if offset + 1 <= #input then
  109.                     local tmp = string.unpack('>I2', input, offset)
  110.                     offset = offset + 2
  111.                     local pos = bit32.rshift(tmp,LEN_BITS) + 1
  112.                     local len = bit32.band(tmp,LEN_SIZE - 1) + LEN_MIN
  113.                     str = string.sub(window, pos, pos + len - 1)
  114.                 end
  115.             end
  116.             flags = bit32.rshift(flags,1)
  117.             if str then
  118.                 output[#output + 1] = str
  119.                 window = string.sub(window .. str, -POS_SIZE)
  120.             end
  121.         end
  122.     end
  123.  
  124.     return table.concat(output)
  125. end
  126. M.unpack=l_unpack
  127. ------------------------------------------------------------------------------
  128. function M.unpackfile(filename) -- my own function to unpack files fast
  129.     local file, err, str = fs.open(filename,'rb')
  130.     str = file and file.readAll() or error(err)
  131.     file.close()
  132.     return l_unpack(str:gsub("#!lzss\n","",1))
  133. end
  134.  
  135. _G.lzss=M]===],
  136. --Minified
  137. ["Minified LZSS"]=[==[U=function(I)local o,r,w,f,t,p,s=1,'',''while#I>=o do f=I:byte(o)o=o+1
  138. for _=0,7 do s=nil
  139. if 0<A(f,1)then
  140. if#I>=o then s=S(I,o,o)o=o+1
  141. end
  142. elseif#I>=o+1 then
  143. t=F:unpack(I,o)p=1+R(t,4)s=S(w,p,p+A(t,15)+2)o=o+2
  144. end
  145. f=R(f,1)if s then w=S(w..s,C)r=r..s end
  146. end
  147. end
  148. return r
  149. end
  150. _G.lzss={pack=function(I)local L,o,r,w,f,b,s,p=B.lshift,1,'',''while#I>=o do
  151. f,b=0,''for i=0,7 do
  152. if#I>=o then
  153. for j=17,2,-1 do
  154. s=S(I,o,o+j)p=w:find(s,1,1)if p then break end
  155. end
  156. if p and#s>=3 then
  157. b=b..F:pack(B.bor(L(p-1,4),#s-3))else
  158. f=B.bor(f,L(1,i))s=S(I,o,o)b=b..s
  159. end
  160. w=S(w..s,C)o=o+#s
  161. else
  162. break
  163. end
  164. end
  165. if#b>0 then
  166. r=r..r.char(f)..b
  167. end
  168. end
  169. return r
  170. end,unpack=U,unpackfile=function(N)local f,e,s=fs.open(N,'rb')
  171. s=f and f.readAll()or error(e)f.close()return U(s:gsub("#!lzss\n","",1))end}F='>I2'B=bit32
  172. A=B.band
  173. R=B.rshift
  174. S=F.sub
  175. C=-4^6]==],
  176. ["LZSS Unpack-Only"]=[==[U=function(I)local o,r,w,f,t,p,s=1,'',''while#I>=o do f=I:byte(o)o=o+1
  177. for _=0,7 do s=nil
  178. if 0<A(f,1)then
  179. if#I>=o then s=S(I,o,o)o=o+1
  180. end
  181. elseif#I>=o+1 then
  182. t=F:unpack(I,o)p=1+R(t,4)s=S(w,p,p+A(t,15)+2)o=o+2
  183. end
  184. f=R(f,1)if s then w=S(w..s,C)r=r..s end
  185. end
  186. end
  187. return r
  188. end
  189. _G.lzss={unpack=U,unpackfile=function(N)local f,e,s=fs.open(N,'rb')
  190. s=f and f.readAll()or error(e)f.close()return U(s:gsub("#!lzss\n","",1))end}F='>I2'B=bit32
  191. A=B.band
  192. R=B.rshift
  193. S=F.sub
  194. C=-4^6]==]}
  195. local lzss_prog_code=[=[local F,I,O,a,E,C,X,D,P,o,t,R,T,H,f,_,e=...,0,0,{...},error,fs.combine,fs.exists,fs.isDir,print,fs.open,{unpack=".unlzss",pack=".lzss"},'run','true','#!lzss\n't=t[F]f=F==R
  196. if#a<2 or f then F=f and a[2]or F if F and X(F)then I,O=load(lzss.unpackfile(F),"@"..F,_,_ENV)return(I or E(O))(select(f and 3 or 2,...))end
  197. P"Usage: lzss <act> <src> [dest] [rewrite] [hashbang]"else
  198. e=t and lzss[F]or E"Unknown action!"_=C(a[2])f=X(_)or E"No matching files!"R=a[3]or#t<6 and(_:find"%.unlzss"and _:sub(1,-8)or _..t)or _:find"%.lzss"and _:sub(1,-6)or _..t
  199. f=R and(X(R)and T~=a[4]or fs.isReadOnly(R))and E('Destination "'..R..'" exist or read-only!')f=function(a,s,d,h)if D(s)then
  200. fs.makeDir(d)for _,v in pairs(fs.list(s))do f(a,C(s,v),C(d,v))end
  201. else
  202. F,e=o(s,'rb')s=F and F.readAll():gsub('^'..H,"")or E(e)F.close()F,e=o(d,'wb')_=F or E(e)_=h..a(s)I=I+#s O=O+#_ F.write(_)F.close()end
  203. end
  204. f(e,_,R,(T~=a[5]or#t>6)and""or H)P(("In: %.2f Kb's\nOut:%.2f Kb's"):format(I/1024,O/1024))end]=]
  205.  
  206.  
  207. --Install function
  208. local install = function(lzss_path,type_api,lzss_prog,api,startup)
  209.     lzss_path=lzss_path:find"/$" and lzss_path or lzss_path.."/"
  210.     lzss_path=lzss_path:find"^/" and lzss_path:sub(2,-1) or lzss_path
  211.     if startup then
  212.         local startup_code=""
  213.         if lzss_prog then
  214.             local locals="local p,l,a,c,d,t='"..lzss_path:gsub("'","\'").."','lzss.lua','lzss_api.lua',require'cc.shell.completion'd,t={c.dirOrFile,true},{c.choice,{'true','false'}}shell.run(p..a)"
  215.             local prog=[[shell.setAlias('lzss',p..l)shell.setCompletionFunction(p..l,c.build({c.choice,{"pack ","unpack ","run "}},d,d,t,t))]]
  216.             startup_code=locals..prog
  217.         else
  218.             startup_code="shell.run('"..lzss_path:gsub("'","\'").."lzss_api.lua')"
  219.         end
  220.         startup.write(startup_code)--make startup
  221.     end
  222.     if lzss_prog then
  223.         lzss_prog.write(lzss_prog_code)--make prog
  224.     end
  225.     api.write(lzss_api[type_api])--make api
  226. end
  227.  
  228. --QUITE RUN
  229. --Args: -lzss=*path_to_lzss_folder* --startup=*startup_file* --func
  230.  
  231. if #{...}>0 then --quite run
  232.     local type_api="Minified LZSS"
  233.     local path_to_lzss
  234.     local path_to_startup
  235.     local install_prog=false
  236.     for _,k in pairs{...}do --for all args
  237.         if k:find"^%-L=" or k:find"^%-%-lzss=" then -- path to lzss
  238.             path_to_lzss=k:match"=(.+)$"
  239.             print("LZSS> path:",path_to_lzss)
  240.         elseif k:find"^%-S=" or k:find"^%-%-startup=" then --install startup (path to startup)
  241.             path_to_startup=k:match"=(.+)$"
  242.             print("LZSS> startup:",path_to_startup)
  243.         elseif k:find"^%-O" or k:find"^%-%-original"  then --install original unminified LZSS
  244.             type_api="Original LZSS"
  245.             print("LZSS> API:",type_api)
  246.         elseif k:find"^%-U" or k:find"^%-%-unpack%-only" then --install unpack function only (UNRECOMENDED!)
  247.             type_api="LZSS Unpack-Only"
  248.             print("LZSS> API:",type_api)
  249.         elseif k:find"^%-P" or k:find"^%-%-program" then --install the LZSS shell Launcher (simple archiver with size of 598 bytes
  250.             install_prog=true
  251.             print("LZSS> launcher: enabled")
  252.         elseif k:find"^%-M" or k:find"^%-%-minified" then --install the minified LZSS version
  253.             type_api="Minified LZSS"
  254.             print("LZSS> API:",type_api)
  255.         elseif k:find"^%-H" or k:find"^%-%-help" then
  256.             print("Usage:\n"..
  257.                   "  lzss_install *no_args* --launch UI\n"..
  258.                   "\n"..
  259.                   "  -H --help --Show this message and exit\n"..
  260.                   "  -L=*path* --lzss=*path*\n"..
  261.                   "        --Set path to installation folder\n"..
  262.                   "  -S=*path* --startup=*path*\n"..
  263.                   "        --Enable startup and set the name of startup file\n"..
  264.                   "  -P --program\n"..
  265.                   "        --Enable launching LZSS from shell\n"..
  266.                   "  -U --unpack-only\n"..
  267.                   "        --Set API version to unpack-only (UNRECOMENDED)\n"..
  268.                   "  -M --minified\n"..
  269.                   "        --Set API version to minified (default, recomended)\n"..
  270.                   "  -O --original\n"..
  271.                   "        --Set API version to original (license included)")
  272.             return
  273.         else
  274.             error("Unexpected argument: "..k)
  275.         end
  276.     end
  277.     if not path_to_lzss then error"Path to instalation directory not set! Use <-L=*path_to_dir*> or <--lzss=*path_to_dir*>.\nP.S:(You can launch lzss_install with no args to use GUI)"end
  278.     print("\nLZSS> API:",fs.combine(path_to_lzss,"lzss_api.lua"))
  279.     local tmp1,err1=fs.open(fs.combine(path_to_lzss,"lzss_api.lua"),"w")
  280.     file2=tmp1 or error(err1)
  281.     if install_prog then
  282.         print("LZSS> launcher:",fs.combine(path_to_lzss,"lzss.lua"))
  283.         local tmp2,err2=fs.open(fs.combine(path_to_lzss,"lzss.lua"),"w")
  284.         file1=tmp2 or error(err2)
  285.     end
  286.     if path_to_startup then
  287.         local tmp3,err3=fs.open(path_to_startup,"w")
  288.         st_file=tmp3 or error(err3)
  289.     end
  290.     install(path_to_lzss, type_api ,file1 ,file2 , st_file)
  291.     print("LZSS> Instalation complete...")
  292.     print("LZSS> Please reload OS...")
  293. else --no args - interface launch required
  294.  
  295. ------------------------------------------------------------------------------------
  296. ------------------------------------------------------------------------------------
  297. ------------------------------------------------------------------------------------
  298. --PrimeUI INIT SECTION (This part of code was created by JackMacWindows)
  299. local expect = require "cc.expect".expect
  300.  
  301. -- Initialization code
  302. local PrimeUI = {}
  303. do
  304.     local coros = {}
  305.     local restoreCursor
  306.  
  307.     --- Adds a task to run in the main loop.
  308.     ---@param func function The function to run, usually an `os.pullEvent` loop
  309.     function PrimeUI.addTask(func)
  310.         expect(1, func, "function")
  311.         local t = {coro = coroutine.create(func)}
  312.         coros[#coros+1] = t
  313.         _, t.filter = coroutine.resume(t.coro)
  314.     end
  315.  
  316.     --- Sends the provided arguments to the run loop, where they will be returned.
  317.     ---@param ... any The parameters to send
  318.     function PrimeUI.resolve(...)
  319.         coroutine.yield(coros, ...)
  320.     end
  321.  
  322.     --- Clears the screen and resets all components. Do not use any previously
  323.     --- created components after calling this function.
  324.     function PrimeUI.clear()
  325.         -- Reset the screen.
  326.         term.setCursorPos(1, 1)
  327.         term.setCursorBlink(false)
  328.         term.setBackgroundColor(colors.black)
  329.         term.setTextColor(colors.white)
  330.         term.clear()
  331.         -- Reset the task list and cursor restore function.
  332.         coros = {}
  333.         restoreCursor = nil
  334.     end
  335.  
  336.     --- Sets or clears the window that holds where the cursor should be.
  337.     ---@param win window|nil The window to set as the active window
  338.     function PrimeUI.setCursorWindow(win)
  339.         expect(1, win, "table", "nil")
  340.         restoreCursor = win and win.restoreCursor
  341.     end
  342.  
  343.     --- Gets the absolute position of a coordinate relative to a window.
  344.     ---@param win window The window to check
  345.     ---@param x number The relative X position of the point
  346.     ---@param y number The relative Y position of the point
  347.     ---@return number x The absolute X position of the window
  348.     ---@return number y The absolute Y position of the window
  349.     function PrimeUI.getWindowPos(win, x, y)
  350.         if win == term then return x, y end
  351.         while win ~= term.native() and win ~= term.current() do
  352.             if not win.getPosition then return x, y end
  353.             local wx, wy = win.getPosition()
  354.             x, y = x + wx - 1, y + wy - 1
  355.             _, win = debug.getupvalue(select(2, debug.getupvalue(win.isColor, 1)), 1) -- gets the parent window through an upvalue
  356.         end
  357.         return x, y
  358.     end
  359.  
  360.     --- Runs the main loop, returning information on an action.
  361.     ---@return any ... The result of the coroutine that exited
  362.     function PrimeUI.run()
  363.         while true do
  364.             -- Restore the cursor and wait for the next event.
  365.             if restoreCursor then restoreCursor() end
  366.             local ev = table.pack(os.pullEvent())
  367.             -- Run all coroutines.
  368.             for _, v in ipairs(coros) do
  369.                 if v.filter == nil or v.filter == ev[1] then
  370.                     -- Resume the coroutine, passing the current event.
  371.                     local res = table.pack(coroutine.resume(v.coro, table.unpack(ev, 1, ev.n)))
  372.                     -- If the call failed, bail out. Coroutines should never exit.
  373.                     if not res[1] then error(res[2], 2) end
  374.                     -- If the coroutine resolved, return its values.
  375.                     if res[2] == coros then return table.unpack(res, 3, res.n) end
  376.                     -- Set the next event filter.
  377.                     v.filter = res[2]
  378.                 end
  379.             end
  380.         end
  381.     end
  382. end
  383.  
  384. --- Draws a line of text at a position.
  385. ---@param win window The window to draw on
  386. ---@param x number The X position of the left side of the text
  387. ---@param y number The Y position of the text
  388. ---@param text string The text to draw
  389. ---@param fgColor color|nil The color of the text (defaults to white)
  390. ---@param bgColor color|nil The color of the background (defaults to black)
  391. function PrimeUI.label(win, x, y, text, fgColor, bgColor)
  392.     expect(1, win, "table")
  393.     expect(2, x, "number")
  394.     expect(3, y, "number")
  395.     expect(4, text, "string")
  396.     fgColor = expect(5, fgColor, "number", "nil") or colors.white
  397.     bgColor = expect(6, bgColor, "number", "nil") or colors.black
  398.     win.setCursorPos(x, y)
  399.     win.setTextColor(fgColor)
  400.     win.setBackgroundColor(bgColor)
  401.     win.write(text)
  402. end
  403.  
  404. --- Draws a horizontal line at a position with the specified width.
  405. ---@param win window The window to draw on
  406. ---@param x number The X position of the left side of the line
  407. ---@param y number The Y position of the line
  408. ---@param width number The width/length of the line
  409. ---@param fgColor color|nil The color of the line (defaults to white)
  410. ---@param bgColor color|nil The color of the background (defaults to black)
  411. function PrimeUI.horizontalLine(win, x, y, width, fgColor, bgColor)
  412.     expect(1, win, "table")
  413.     expect(2, x, "number")
  414.     expect(3, y, "number")
  415.     expect(4, width, "number")
  416.     fgColor = expect(5, fgColor, "number", "nil") or colors.white
  417.     bgColor = expect(6, bgColor, "number", "nil") or colors.black
  418.     -- Use drawing characters to draw a thin line.
  419.     win.setCursorPos(x, y)
  420.     win.setTextColor(fgColor)
  421.     win.setBackgroundColor(bgColor)
  422.     win.write(("\x8C"):rep(width))
  423. end
  424.  
  425. --- Creates a clickable button on screen with text.
  426. ---@param win window The window to draw on
  427. ---@param x number The X position of the button
  428. ---@param y number The Y position of the button
  429. ---@param text string The text to draw on the button
  430. ---@param action function|string A function to call when clicked, or a string to send with a `run` event
  431. ---@param fgColor color|nil The color of the button text (defaults to white)
  432. ---@param bgColor color|nil The color of the button (defaults to light gray)
  433. ---@param clickedColor color|nil The color of the button when clicked (defaults to gray)
  434. function PrimeUI.button(win, x, y, text, action, fgColor, bgColor, clickedColor)
  435.     expect(1, win, "table")
  436.     expect(2, x, "number")
  437.     expect(3, y, "number")
  438.     expect(4, text, "string")
  439.     expect(5, action, "function", "string")
  440.     fgColor = expect(6, fgColor, "number", "nil") or colors.white
  441.     bgColor = expect(7, bgColor, "number", "nil") or colors.gray
  442.     clickedColor = expect(8, clickedColor, "number", "nil") or colors.lightGray
  443.     -- Draw the initial button.
  444.     win.setCursorPos(x, y)
  445.     win.setBackgroundColor(bgColor)
  446.     win.setTextColor(fgColor)
  447.     win.write(" " .. text .. " ")
  448.     -- Get the screen position and add a click handler.
  449.     PrimeUI.addTask(function()
  450.         local buttonDown = false
  451.         while true do
  452.             local event, button, clickX, clickY = os.pullEvent()
  453.             local screenX, screenY = PrimeUI.getWindowPos(win, x, y)
  454.             if event == "mouse_click" and button == 1 and clickX >= screenX and clickX < screenX + #text + 2 and clickY == screenY then
  455.                 -- Initiate a click action (but don't trigger until mouse up).
  456.                 buttonDown = true
  457.                 -- Redraw the button with the clicked background color.
  458.                 win.setCursorPos(x, y)
  459.                 win.setBackgroundColor(clickedColor)
  460.                 win.setTextColor(fgColor)
  461.                 win.write(" " .. text .. " ")
  462.             elseif event == "mouse_up" and button == 1 and buttonDown then
  463.                 -- Finish a click event.
  464.                 if clickX >= screenX and clickX < screenX + #text + 2 and clickY == screenY then
  465.                     -- Trigger the action.
  466.                     if type(action) == "string" then PrimeUI.resolve("button", action)
  467.                     else action() end
  468.                 end
  469.                 -- Redraw the original button state.
  470.                 win.setCursorPos(x, y)
  471.                 win.setBackgroundColor(bgColor)
  472.                 win.setTextColor(fgColor)
  473.                 win.write(" " .. text .. " ")
  474.             end
  475.         end
  476.     end)
  477. end
  478.  
  479. --- Adds an action to trigger when a key is pressed.
  480. ---@param key key The key to trigger on, from `keys.*`
  481. ---@param action function|string A function to call when clicked, or a string to use as a key for a `run` return event
  482. function PrimeUI.keyAction(key, action)
  483.     expect(1, key, "number")
  484.     expect(2, action, "function", "string")
  485.     PrimeUI.addTask(function()
  486.         while true do
  487.             local _, param1 = os.pullEvent("key") -- wait for key
  488.             if param1 == key then
  489.                 if type(action) == "string" then PrimeUI.resolve("keyAction", action)
  490.                 else action() end
  491.             end
  492.         end
  493.     end)
  494. end
  495.  
  496. --- Adds an action to trigger when a key is pressed with modifier keys.
  497. ---@param key key The key to trigger on, from `keys.*`
  498. ---@param withCtrl boolean Whether Ctrl is required
  499. ---@param withAlt boolean Whether Alt is required
  500. ---@param withShift boolean Whether Shift is required
  501. ---@param action function|string A function to call when clicked, or a string to use as a key for a `run` return event
  502. function PrimeUI.keyCombo(key, withCtrl, withAlt, withShift, action)
  503.     expect(1, key, "number")
  504.     expect(2, withCtrl, "boolean")
  505.     expect(3, withAlt, "boolean")
  506.     expect(4, withShift, "boolean")
  507.     expect(5, action, "function", "string")
  508.     PrimeUI.addTask(function()
  509.         local heldCtrl, heldAlt, heldShift = false, false, false
  510.         while true do
  511.             local event, param1, param2 = os.pullEvent() -- wait for key
  512.             if event == "key" then
  513.                 -- check if key is down, all modifiers are correct, and that it's not held
  514.                 if param1 == key and heldCtrl == withCtrl and heldAlt == withAlt and heldShift == withShift and not param2 then
  515.                     if type(action) == "string" then PrimeUI.resolve("keyCombo", action)
  516.                     else action() end
  517.                 -- activate modifier keys
  518.                 elseif param1 == keys.leftCtrl or param1 == keys.rightCtrl then heldCtrl = true
  519.                 elseif param1 == keys.leftAlt or param1 == keys.rightAlt then heldAlt = true
  520.                 elseif param1 == keys.leftShift or param1 == keys.rightShift then heldShift = true end
  521.             elseif event == "key_up" then
  522.                 -- deactivate modifier keys
  523.                 if param1 == keys.leftCtrl or param1 == keys.rightCtrl then heldCtrl = false
  524.                 elseif param1 == keys.leftAlt or param1 == keys.rightAlt then heldAlt = false
  525.                 elseif param1 == keys.leftShift or param1 == keys.rightShift then heldShift = false end
  526.             end
  527.         end
  528.     end)
  529. end
  530.  
  531. --- Creates a scrollable window, which allows drawing large content in a small area.
  532. ---@param win window The parent window of the scroll box
  533. ---@param x number The X position of the box
  534. ---@param y number The Y position of the box
  535. ---@param width number The width of the box
  536. ---@param height number The height of the outer box
  537. ---@param innerHeight number The height of the inner scroll area
  538. ---@param allowArrowKeys boolean|nil Whether to allow arrow keys to scroll the box (defaults to true)
  539. ---@param showScrollIndicators boolean|nil Whether to show arrow indicators on the right side when scrolling is available, which reduces the inner width by 1 (defaults to false)
  540. ---@param fgColor number|nil The color of scroll indicators (defaults to white)
  541. ---@param bgColor color|nil The color of the background (defaults to black)
  542. ---@return window inner The inner window to draw inside
  543. function PrimeUI.scrollBox(win, x, y, width, height, innerHeight, allowArrowKeys, showScrollIndicators, fgColor, bgColor)
  544.     expect(1, win, "table")
  545.     expect(2, x, "number")
  546.     expect(3, y, "number")
  547.     expect(4, width, "number")
  548.     expect(5, height, "number")
  549.     expect(6, innerHeight, "number")
  550.     expect(7, allowArrowKeys, "boolean", "nil")
  551.     expect(8, showScrollIndicators, "boolean", "nil")
  552.     fgColor = expect(9, fgColor, "number", "nil") or colors.white
  553.     bgColor = expect(10, bgColor, "number", "nil") or colors.black
  554.     if allowArrowKeys == nil then allowArrowKeys = true end
  555.     -- Create the outer container box.
  556.     local outer = window.create(win == term and term.current() or win, x, y, width, height)
  557.     outer.setBackgroundColor(bgColor)
  558.     outer.clear()
  559.     -- Create the inner scrolling box.
  560.     local inner = window.create(outer, 1, 1, width - (showScrollIndicators and 1 or 0), innerHeight)
  561.     inner.setBackgroundColor(bgColor)
  562.     inner.clear()
  563.     -- Draw scroll indicators if desired.
  564.     if showScrollIndicators then
  565.         outer.setBackgroundColor(bgColor)
  566.         outer.setTextColor(fgColor)
  567.         outer.setCursorPos(width, height)
  568.         outer.write(innerHeight > height and "\31" or " ")
  569.     end
  570.     -- Get the absolute position of the window.
  571.     x, y = PrimeUI.getWindowPos(win, x, y)
  572.     -- Add the scroll handler.
  573.     PrimeUI.addTask(function()
  574.         local scrollPos = 1
  575.         while true do
  576.             -- Wait for next event.
  577.             local ev = table.pack(os.pullEvent())
  578.             -- Update inner height in case it changed.
  579.             innerHeight = select(2, inner.getSize())
  580.             -- Check for scroll events and set direction.
  581.             local dir
  582.             if ev[1] == "key" and allowArrowKeys then
  583.                 if ev[2] == keys.up then dir = -1
  584.                 elseif ev[2] == keys.down then dir = 1 end
  585.             elseif ev[1] == "mouse_scroll" and ev[3] >= x and ev[3] < x + width and ev[4] >= y and ev[4] < y + height then
  586.                 dir = ev[2]
  587.             end
  588.             -- If there's a scroll event, move the window vertically.
  589.             if dir and (scrollPos + dir >= 1 and scrollPos + dir <= innerHeight - height) then
  590.                 scrollPos = scrollPos + dir
  591.                 inner.reposition(1, 2 - scrollPos)
  592.             end
  593.             -- Redraw scroll indicators if desired.
  594.             if showScrollIndicators then
  595.                 outer.setBackgroundColor(bgColor)
  596.                 outer.setTextColor(fgColor)
  597.                 outer.setCursorPos(width, 1)
  598.                 outer.write(scrollPos > 1 and "\30" or " ")
  599.                 outer.setCursorPos(width, height)
  600.                 outer.write(scrollPos < innerHeight - height and "\31" or " ")
  601.             end
  602.         end
  603.     end)
  604.     return inner
  605. end
  606.  
  607. --- Creates a text input box.
  608. ---@param win window The window to draw on
  609. ---@param x number The X position of the left side of the box
  610. ---@param y number The Y position of the box
  611. ---@param width number The width/length of the box
  612. ---@param action function|string A function or `run` event to call when the enter key is pressed
  613. ---@param fgColor color|nil The color of the text (defaults to white)
  614. ---@param bgColor color|nil The color of the background (defaults to black)
  615. ---@param replacement string|nil A character to replace typed characters with
  616. ---@param history string[]|nil A list of previous entries to provide
  617. ---@param completion function|nil A function to call to provide completion
  618. ---@param default string|nil A string to return if the box is empty
  619. function PrimeUI.inputBox(win, x, y, width, action, fgColor, bgColor, replacement, history, completion, default)
  620.     expect(1, win, "table")
  621.     expect(2, x, "number")
  622.     expect(3, y, "number")
  623.     expect(4, width, "number")
  624.     expect(5, action, "function", "string")
  625.     fgColor = expect(6, fgColor, "number", "nil") or colors.white
  626.     bgColor = expect(7, bgColor, "number", "nil") or colors.black
  627.     expect(8, replacement, "string", "nil")
  628.     expect(9, history, "table", "nil")
  629.     expect(10, completion, "function", "nil")
  630.     expect(11, default, "string", "nil")
  631.     -- Create a window to draw the input in.
  632.     local box = window.create(win, x, y, width, 1)
  633.     box.setTextColor(fgColor)
  634.     box.setBackgroundColor(bgColor)
  635.     box.clear()
  636.     -- Call read() in a new coroutine.
  637.     PrimeUI.addTask(function()
  638.         -- We need a child coroutine to be able to redirect back to the window.
  639.         local coro = coroutine.create(read)
  640.         -- Run the function for the first time, redirecting to the window.
  641.         local old = term.redirect(box)
  642.         local ok, res = coroutine.resume(coro, replacement, history, completion, default)
  643.         term.redirect(old)
  644.         -- Run the coroutine until it finishes.
  645.         while coroutine.status(coro) ~= "dead" do
  646.             -- Get the next event.
  647.             local ev = table.pack(os.pullEvent())
  648.             -- Redirect and resume.
  649.             old = term.redirect(box)
  650.             ok, res = coroutine.resume(coro, table.unpack(ev, 1, ev.n))
  651.             term.redirect(old)
  652.             -- Pass any errors along.
  653.             if not ok then error(res) end
  654.         end
  655.         -- Send the result to the receiver.
  656.         if type(action) == "string" then PrimeUI.resolve("inputBox", action, res)
  657.         else action(res) end
  658.         -- Spin forever, because tasks cannot exit.
  659.         while true do os.pullEvent() end
  660.     end)
  661. end
  662.  
  663. --- Creates a list of entries with toggleable check boxes.
  664. ---@param win window The window to draw on
  665. ---@param x number The X coordinate of the inside of the box
  666. ---@param y number The Y coordinate of the inside of the box
  667. ---@param width number The width of the inner box
  668. ---@param height number The height of the inner box
  669. ---@param selections {string: string|boolean} A list of entries to show, where the value is whether the item is pre-selected (or `"R"` for required/forced selected)
  670. ---@param action function|string|nil A function or `run` event that's called when a selection is made
  671. ---@param fgColor color|nil The color of the text (defaults to white)
  672. ---@param bgColor color|nil The color of the background (defaults to black)
  673. function PrimeUI.checkSelectionBox(win, x, y, width, height, selections, action, fgColor, bgColor)
  674.     expect(1, win, "table")
  675.     expect(2, x, "number")
  676.     expect(3, y, "number")
  677.     expect(4, width, "number")
  678.     expect(5, height, "number")
  679.     expect(6, selections, "table")
  680.     expect(7, action, "function", "string", "nil")
  681.     fgColor = expect(8, fgColor, "number", "nil") or colors.white
  682.     bgColor = expect(9, bgColor, "number", "nil") or colors.black
  683.     -- Calculate how many selections there are.
  684.     local nsel = 0
  685.     for _ in pairs(selections) do nsel = nsel + 1 end
  686.     -- Create the outer display box.
  687.     local outer = window.create(win, x, y, width, height)
  688.     outer.setBackgroundColor(bgColor)
  689.     outer.clear()
  690.     -- Create the inner scroll box.
  691.     local inner = window.create(outer, 1, 1, width - 1, nsel)
  692.     inner.setBackgroundColor(bgColor)
  693.     inner.setTextColor(fgColor)
  694.     inner.clear()
  695.     -- Draw each line in the window.
  696.     local lines = {}
  697.     local nl, selected = 1, 1
  698.     for k, v in pairs(selections) do
  699.         inner.setCursorPos(1, nl)
  700.         inner.write((v and (v == "R" and "[-] " or "[\xD7] ") or "[ ] ") .. k)
  701.         lines[nl] = {k, not not v}
  702.         nl = nl + 1
  703.     end
  704.     -- Draw a scroll arrow if there is scrolling.
  705.     if nsel > height then
  706.         outer.setCursorPos(width, height)
  707.         outer.setBackgroundColor(bgColor)
  708.         outer.setTextColor(fgColor)
  709.         outer.write("\31")
  710.     end
  711.     -- Set cursor blink status.
  712.     inner.setCursorPos(2, selected)
  713.     inner.setCursorBlink(true)
  714.     PrimeUI.setCursorWindow(inner)
  715.     -- Get screen coordinates & add run task.
  716.     local screenX, screenY = PrimeUI.getWindowPos(win, x, y)
  717.     PrimeUI.addTask(function()
  718.         local scrollPos = 1
  719.         while true do
  720.             -- Wait for an event.
  721.             local ev = table.pack(os.pullEvent())
  722.             -- Look for a scroll event or a selection event.
  723.             local dir
  724.             if ev[1] == "key" then
  725.                 if ev[2] == keys.up then dir = -1
  726.                 elseif ev[2] == keys.down then dir = 1
  727.                 elseif ev[2] == keys.space and selections[lines[selected][1]] ~= "R" then
  728.                     -- (Un)select the item.
  729.                     lines[selected][2] = not lines[selected][2]
  730.                     inner.setCursorPos(2, selected)
  731.                     inner.write(lines[selected][2] and "\xD7" or " ")
  732.                     -- Call the action if passed; otherwise, set the original table.
  733.                     if type(action) == "string" then PrimeUI.resolve("checkSelectionBox", action, lines[selected][1], lines[selected][2])
  734.                     elseif action then action(lines[selected][1], lines[selected][2])
  735.                     else selections[lines[selected][1]] = lines[selected][2] end
  736.                     -- Redraw all lines in case of changes.
  737.                     for i, v in ipairs(lines) do
  738.                         local vv = selections[v[1]] == "R" and "R" or v[2]
  739.                         inner.setCursorPos(2, i)
  740.                         inner.write((vv and (vv == "R" and "-" or "\xD7") or " "))
  741.                     end
  742.                     inner.setCursorPos(2, selected)
  743.                 end
  744.             elseif ev[1] == "mouse_scroll" and ev[3] >= screenX and ev[3] < screenX + width and ev[4] >= screenY and ev[4] < screenY + height then
  745.                 dir = ev[2]
  746.             end
  747.             -- Scroll the screen if required.
  748.             if dir and (selected + dir >= 1 and selected + dir <= nsel) then
  749.                 selected = selected + dir
  750.                 if selected - scrollPos < 0 or selected - scrollPos >= height then
  751.                     scrollPos = scrollPos + dir
  752.                     inner.reposition(1, 2 - scrollPos)
  753.                 end
  754.                 inner.setCursorPos(2, selected)
  755.             end
  756.             -- Redraw scroll arrows and reset cursor.
  757.             outer.setCursorPos(width, 1)
  758.             outer.write(scrollPos > 1 and "\30" or " ")
  759.             outer.setCursorPos(width, height)
  760.             outer.write(scrollPos < nsel - height + 1 and "\31" or " ")
  761.             inner.restoreCursor()
  762.         end
  763.     end)
  764. end
  765.  
  766. --- Creates a text box that wraps text and can have its text modified later.
  767. ---@param win window The parent window of the text box
  768. ---@param x number The X position of the box
  769. ---@param y number The Y position of the box
  770. ---@param width number The width of the box
  771. ---@param height number The height of the box
  772. ---@param text string The initial text to draw
  773. ---@param fgColor color|nil The color of the text (defaults to white)
  774. ---@param bgColor color|nil The color of the background (defaults to black)
  775. ---@return function redraw A function to redraw the window with new contents
  776. function PrimeUI.textBox(win, x, y, width, height, text, fgColor, bgColor)
  777.     expect(1, win, "table")
  778.     expect(2, x, "number")
  779.     expect(3, y, "number")
  780.     expect(4, width, "number")
  781.     expect(5, height, "number")
  782.     expect(6, text, "string")
  783.     fgColor = expect(7, fgColor, "number", "nil") or colors.white
  784.     bgColor = expect(8, bgColor, "number", "nil") or colors.black
  785.     -- Create the box window.
  786.     local box = window.create(win, x, y, width, height)
  787.     -- Override box.getSize to make print not scroll.
  788.     function box.getSize()
  789.         return width, math.huge
  790.     end
  791.     -- Define a function to redraw with.
  792.     local function redraw(_text)
  793.         expect(1, _text, "string")
  794.         -- Set window parameters.
  795.         box.setBackgroundColor(bgColor)
  796.         box.setTextColor(fgColor)
  797.         box.clear()
  798.         box.setCursorPos(1, 1)
  799.         -- Redirect and draw with `print`.
  800.         local old = term.redirect(box)
  801.         print(_text)
  802.         term.redirect(old)
  803.     end
  804.     redraw(text)
  805.     return redraw
  806. end
  807.  
  808. --- Draws a thin border around a screen region.
  809. ---@param win window The window to draw on
  810. ---@param x number The X coordinate of the inside of the box
  811. ---@param y number The Y coordinate of the inside of the box
  812. ---@param width number The width of the inner box
  813. ---@param height number The height of the inner box
  814. ---@param fgColor color|nil The color of the border (defaults to white)
  815. ---@param bgColor color|nil The color of the background (defaults to black)
  816. function PrimeUI.borderBox(win, x, y, width, height, fgColor, bgColor)
  817.     expect(1, win, "table")
  818.     expect(2, x, "number")
  819.     expect(3, y, "number")
  820.     expect(4, width, "number")
  821.     expect(5, height, "number")
  822.     fgColor = expect(6, fgColor, "number", "nil") or colors.white
  823.     bgColor = expect(7, bgColor, "number", "nil") or colors.black
  824.     -- Draw the top-left corner & top border.
  825.     win.setBackgroundColor(bgColor)
  826.     win.setTextColor(fgColor)
  827.     win.setCursorPos(x - 1, y - 1)
  828.     win.write("\x9C" .. ("\x8C"):rep(width))
  829.     -- Draw the top-right corner.
  830.     win.setBackgroundColor(fgColor)
  831.     win.setTextColor(bgColor)
  832.     win.write("\x93")
  833.     -- Draw the right border.
  834.     for i = 1, height do
  835.         win.setCursorPos(win.getCursorPos() - 1, y + i - 1)
  836.         win.write("\x95")
  837.     end
  838.     -- Draw the left border.
  839.     win.setBackgroundColor(bgColor)
  840.     win.setTextColor(fgColor)
  841.     for i = 1, height do
  842.         win.setCursorPos(x - 1, y + i - 1)
  843.         win.write("\x95")
  844.     end
  845.     -- Draw the bottom border and corners.
  846.     win.setCursorPos(x - 1, y + height)
  847.     win.write("\x8D" .. ("\x8C"):rep(width) .. "\x8E")
  848. end
  849.  
  850. --- Draws a block of text inside a window with word wrapping, optionally resizing the window to fit.
  851. ---@param win window The window to draw in
  852. ---@param text string The text to draw
  853. ---@param resizeToFit boolean|nil Whether to resize the window to fit the text (defaults to false). This is useful for scroll boxes.
  854. ---@param fgColor color|nil The color of the text (defaults to white)
  855. ---@param bgColor color|nil The color of the background (defaults to black)
  856. ---@return number lines The total number of lines drawn
  857. function PrimeUI.drawText(win, text, resizeToFit, fgColor, bgColor)
  858.     expect(1, win, "table")
  859.     expect(2, text, "string")
  860.     expect(3, resizeToFit, "boolean", "nil")
  861.     fgColor = expect(4, fgColor, "number", "nil") or colors.white
  862.     bgColor = expect(5, bgColor, "number", "nil") or colors.black
  863.     -- Set colors.
  864.     win.setBackgroundColor(bgColor)
  865.     win.setTextColor(fgColor)
  866.     -- Redirect to the window to use print on it.
  867.     local old = term.redirect(win)
  868.     -- Draw the text using print().
  869.     local lines = print(text)
  870.     -- Redirect back to the original terminal.
  871.     term.redirect(old)
  872.     -- Resize the window if desired.
  873.     if resizeToFit then
  874.         -- Get original parameters.
  875.         local x, y = win.getPosition()
  876.         local w = win.getSize()
  877.         -- Resize the window.
  878.         win.reposition(x, y, w, lines)
  879.     end
  880.     return lines
  881. end
  882.  
  883. --- Runs a function or action after the specified time period, with optional canceling.
  884. ---@param time number The amount of time to wait for, in seconds
  885. ---@param action function|string The function to call when the timer completes, or a `run` event to send
  886. ---@return function cancel A function to cancel the timer
  887. function PrimeUI.timeout(time, action)
  888.     expect(1, time, "number")
  889.     expect(2, action, "function", "string")
  890.     -- Start the timer.
  891.     local timer = os.startTimer(time)
  892.     -- Add a task to wait for the timer.
  893.     PrimeUI.addTask(function()
  894.         while true do
  895.             -- Wait for a timer event.
  896.             local _, tm = os.pullEvent("timer")
  897.             if tm == timer then
  898.                 -- Fire the timer action.
  899.                 if type(action) == "string" then PrimeUI.resolve("timeout", action)
  900.                 else action() end
  901.             end
  902.         end
  903.     end)
  904.     -- Return a function to cancel the timer.
  905.     return function() os.cancelTimer(timer) end
  906. end
  907.  
  908. --PrimeUI INIT END
  909. ------------------------------------------------------------------------------------
  910. ------------------------------------------------------------------------------------
  911. ------------------------------------------------------------------------------------
  912.  
  913.  
  914. local comp=require"cc.shell.completion"
  915. local main=term.current()
  916. x,y=6,10
  917. max_x,max_y=term.getSize()
  918.  
  919. local desc1=[[--PACKAGE DESCRIPTION--
  920.  
  921. This package has quiet install mode.
  922. Use `-H` or `--help` option for more information.
  923.  
  924. Controls:
  925.  Enter  == Continue
  926.  Ctrl+c == Exit / Cancel
  927.  Space  == Select option
  928.  
  929. Package version: 1.0
  930. Package creator: M.A.G.Gen.
  931. Git: https://github.com/MAGGen-hub
  932.  
  933. LZSS.lua creator: Sebastian Steinhauer
  934. Git: https://github.com/kieselsteini/lzss
  935.  
  936. PrimeUI creator: JackMacWindows
  937. Git: https://github.com/MCJack123/PrimeUI
  938.  
  939. ALL LICENCES ARE PUBLIC:
  940. For a more detailed acquaintance visit previously mentioned links.
  941.  
  942. What is LZSS:
  943. Lempel-Ziv-Storer-Szymanski (LZSS) is a lossless data compression algorithm, a derivative of LZ77, that was created in 1982 by James A. Storer and Thomas Szymanski.
  944.  
  945. This version of LZSS is taken from Sebastian Steinhauer Git and adapted to run under Lua5.1 (Lua VM used by CraftOS).
  946.  
  947. WARNING: Algorithm efficiency depends on count of repeating sequences of characters in input string.
  948. Compressed output can be bigger than input in some situations.
  949.  
  950. --END OF PACKAGE DESCRIPTION--
  951. ]]
  952.  
  953. mkgui=function(nobtn)
  954.     local lab="LZSS Installer V1.1"
  955.     PrimeUI.label(main,3,2,lab,colors.yellow)
  956.     PrimeUI.horizontalLine(main,3,3,#lab + 2,colors.yellow)
  957.     PrimeUI.borderBox(main,4,6,max_x-x,max_y-y,colors.yellow)
  958.     PrimeUI.keyCombo(keys.c,true,false,false,"exit")
  959.     if not nobtn then
  960.         PrimeUI.keyAction(keys.enter,"done")
  961.         PrimeUI.button(main,3,max_y-2,"Continue","done",colors.yellow,nil,colors.lightGray)
  962.         PrimeUI.button(main,14,max_y-2,"Cancel","exit",colors.yellow,nil,colors.lightGray)
  963.     else
  964.         PrimeUI.label(main,3,max_y-2," Continue ",colors.lightGray,colors.gray)
  965.         PrimeUI.button(main,14,max_y-2,"Cancel","exit",colors.yellow,nil,colors.lightGray)
  966.     end
  967. end
  968.  
  969. --DESCRIPTION SHOW--
  970. PrimeUI.clear()
  971. mkgui()
  972. local scroll_box=PrimeUI.scrollBox(main,4,6,max_x-x, max_y-y,999,true,true)
  973. PrimeUI.drawText(scroll_box,desc1,true)
  974. local _,act = PrimeUI.run()
  975. local ind=1
  976.  
  977. --MODULES SELECT
  978. local st_name=("Startup (0.04~0.26)Kb's")
  979. local sh_lzss=("Shell LZSS launcher %0.2fKb's"):format(#lzss_prog_code/1024.0)
  980. PrimeUI.clear()
  981. local api_done=false
  982. local wnd=window.create(term.current(),4,8,max_x-x,3)--API chooser window
  983. local desc2={
  984.     ["Original LZSS"]=("Original LZSS with %0.2fKb's size."):format(#lzss_api["Original LZSS"]/1024),
  985.     ["Minified LZSS"]=("Minified API with %0.2fKb's size."):format(#lzss_api["Minified LZSS"]/1024.0),
  986.     ["LZSS Unpack-Only"]=("LZSS Unpack function only. %0.2fKb's size. Unrecomended!"):format(#lzss_api["LZSS Unpack-Only"]/1024.0)}
  987. local sel_desk=desc2["Minified LZSS"]
  988. local api={
  989.     ["Original LZSS"]=false,
  990.     ["Minified LZSS"]=true,
  991.     ["LZSS Unpack-Only"]=false}
  992. local mod={
  993.     [st_name]=true,
  994.     [sh_lzss]=true}
  995.  
  996. if act=="done" then
  997.     local key,value
  998.     --API
  999.     repeat
  1000.         PrimeUI.clear()
  1001.         mkgui()
  1002.         PrimeUI.label(main,4,6,"Select API and modules to install:",colors.yellow)
  1003.         PrimeUI.textBox(main,4,15,max_x-x,1,sel_desk,colors.yellow)
  1004.         PrimeUI.checkSelectionBox(wnd,1, 1,max_x-x,3,api,
  1005.             function(k)
  1006.                 for k in pairs(api)do api[k]=false end
  1007.                 api[k]=true
  1008.                 sel_desk=desc2[k]
  1009.                 PrimeUI.resolve(_,"api")
  1010.             end)
  1011.         PrimeUI.addTask(--task to put cursor on it's place
  1012.                 function()
  1013.                     for k,v in pairs(api)do
  1014.                         if not v then os.queueEvent("key",keys.down,false)
  1015.                         else break end
  1016.                     end
  1017.                     while true do coroutine.yield() end
  1018.                 end)
  1019.             --wnd.redraw()PrimeUI.checkSelectionBox(main,4,12,max_x-x,2,mod,function(k,v)end)
  1020.         _,act,key,value=PrimeUI.run()
  1021.     until act~="api"
  1022. end
  1023.  
  1024. if act=="done"then
  1025.     --Modules
  1026.     PrimeUI.clear()
  1027.     mkgui()
  1028.     PrimeUI.label(main,4,6,"Select API to install:",colors.yellow)
  1029.     PrimeUI.textBox(main,4,15,max_x-x,3,"Choose additional modules",colors.yellow)
  1030.     wnd.redraw()
  1031.     PrimeUI.checkSelectionBox(main,4,12,max_x-x,2,mod,function(k,v)mod[k]=v end)
  1032.     _,act=PrimeUI.run()
  1033. end
  1034.  
  1035. local lzss_folder,prev_folder,err
  1036. --SELECT LZSS FOLDER
  1037. if act=="done" then
  1038.     local histor={"/","/progs/lzss","/programs/lzss","/disk/lzss","/lib/lzss","/apis/lzss","/lzss"}-- posible names for directory
  1039.     --wnd.reposition(4,9)
  1040.     --wnd.clear()
  1041.     repeat
  1042.         lzss_folder=nil
  1043.         PrimeUI.clear()
  1044.         mkgui(true)
  1045.         PrimeUI.label(main,4,6,"Choose instalation folder (use \x12):",colors.yellow)
  1046.         paintutils.drawLine(4,8,max_x-x+3,8,colors.gray)
  1047.         PrimeUI.inputBox(main,5,8,max_x-x-2,"done",colors.yellow,colors.gray,nil,histor,
  1048.             function(sLine) if #sLine>0 then return comp.dir(shell,sLine)end end,histor[#histor])
  1049.        
  1050.         PrimeUI.textBox(main,4,9,max_x-x,3,err or"",colors.red)
  1051.         _,act,lzss_folder=PrimeUI.run()--attempt to get the way
  1052.         _,err=pcall(function()
  1053.             if lzss_folder then --create files if posible
  1054.                 if prev_folder~=lzss_folder and fs.isDir(lzss_folder) and (fs.exists(fs.combine(lzss_folder,"lzss.lua")) or fs.exists(fs.combine(lzss_folder,"lzss_api.lua")))then
  1055.                     prev_folder=lzss_folder
  1056.                     error("Warning! Files 'lzss.lua' and 'lzss_api.lua' will be rewriten! Are you sure? [Enter]")
  1057.                 end
  1058.                 local tmp1,err1
  1059.                 if mod[sh_lzss] then
  1060.                     tmp1,err1=fs.open(fs.combine(lzss_folder,"lzss.lua"),"w")
  1061.                     err1=tmp1 or error(err1)
  1062.                 end
  1063.                 local tmp2,err2=fs.open(fs.combine(lzss_folder,"lzss_api.lua"),"w")
  1064.                 err2=tmp2 or error(err2)
  1065.                
  1066.                 file1=tmp1
  1067.                 file2=tmp2
  1068.             end
  1069.         end)
  1070.         histor[#histor+1]=lzss_folder~=histor[#histor] and lzss_folder or nil
  1071.        
  1072.     until file2 or act=="exit"
  1073. end
  1074.  
  1075.  
  1076. err=nil
  1077. local st_path
  1078. --SELECT STARTUP
  1079. if act=="done" and mod[st_name] then
  1080.     local histor={"/startup.lua","/disk/startup.lua","/disk/startup/00_lzss.lua","/startup/lzss.lua","/startup/01_lzss.lua","/startup/00_lzss.lua"}
  1081.     repeat
  1082.         PrimeUI.clear()
  1083.         mkgui(true)
  1084.         PrimeUI.label(main,4,6,"Enter startup (use \x12):",colors.yellow)
  1085.         paintutils.drawLine(4,8,max_x-x+3,8,colors.gray)
  1086.         PrimeUI.inputBox(main,5,8,max_x-x-2,"done",colors.yellow,colors.gray,nil,histor,
  1087.             function(sLine) if #sLine>0 then return comp.dirOrFile(shell,sLine)end end, histor[#histor])
  1088.         PrimeUI.textBox(main,4,9,max_x-x,3,err or"",colors.red)
  1089.         _,act,st_path=PrimeUI.run()
  1090.         _,err=pcall(function()
  1091.                 if st_path then
  1092.                     local tmp,err1=fs.open(st_path,"w")
  1093.                     st_file=tmp or error(err1)
  1094.                 end
  1095.             end)
  1096.         histor[#histor+1]=st_path~=histor[#histor] and st_path or nil
  1097.     until st_file or act=="exit"
  1098. end
  1099.  
  1100. --SIZE DEMO PART
  1101. if act=="done" then
  1102.     local type_api="Minified LZSS"
  1103.     for k,v in pairs(api)do
  1104.         type_api=v and k or type_api
  1105.     end
  1106.     local s_api=#lzss_api[type_api]/1024
  1107.     local s_prog = mod[sh_lzss]and #lzss_prog_code/1024 or 0
  1108.     local s_stp = st_file and (((mod[sh_lzss] and 260 or 35) - 9 + #lzss_folder)/1024) or 0
  1109.     PrimeUI.clear()
  1110.     wnd.clear()
  1111.     mkgui()
  1112.     PrimeUI.label(main ,4,6,("Startup:   %6.2fKb's"):format(s_stp),colors.yellow)
  1113.     PrimeUI.label(main ,4,7,("    API:   %6.2fKb's"):format(s_api),colors.yellow)
  1114.     PrimeUI.label(main ,4,8,("   Prog:   %6.2fKb's"):format(s_prog),colors.yellow)
  1115.     PrimeUI.label(main ,4,9,("Total Size:%6.2fKb's"):format(s_api+s_prog+s_stp),colors.yellow)
  1116.     PrimeUI.label(main ,4,10,"Continue instalation?",colors.yellow)
  1117.     _,act=PrimeUI.run()
  1118. end
  1119.  
  1120. --INSTALL PART
  1121. if act=="done" then
  1122.     local type_api="Minified LZSS"
  1123.     for k,v in pairs(api)do
  1124.         type_api=v and k or type_api
  1125.     end
  1126.     install(lzss_folder,type_api,file1,file2,st_file)
  1127.  
  1128.     PrimeUI.clear()
  1129.     wnd.clear()
  1130.     mkgui()
  1131.     PrimeUI.label(main ,4,6,"Instalation completed...",colors.yellow)
  1132.     PrimeUI.label(main ,4,7,"Please reload OS...",colors.yellow)
  1133.     PrimeUI.label(main ,4,8,"Press any key to continue...",colors.yellow)
  1134.     PrimeUI.label(main ,4,9,"Program will exit automaticly after 5 seconds.",colors.yellow)
  1135.     PrimeUI.addTask(function()while true do
  1136.         local ev=os.pullEvent"key"
  1137.         ev=ev and PrimeUI.resolve()
  1138.         end
  1139.     end)
  1140.     PrimeUI.timeout(5,"done")
  1141.     PrimeUI.run()
  1142. end
  1143.  
  1144. --IF CANCELED
  1145. if act=="exit" then
  1146.     PrimeUI.clear()
  1147.     wnd.clear()
  1148.     mkgui()
  1149.     PrimeUI.label(main ,4,6,"Instalation canceled. Press any key to exit.",colors.red)
  1150.     PrimeUI.label(main ,4,7,"Program will exit automaticly after 3 seconds.",colors.yellow)
  1151.     PrimeUI.addTask(function()while true do
  1152.         local ev=os.pullEvent"key"
  1153.         ev=ev and PrimeUI.resolve()
  1154.         end
  1155.     end)
  1156.     PrimeUI.timeout(3,"done")
  1157.     PrimeUI.run()
  1158. end
  1159. end
  1160. --close all files
  1161. _=file1 and pcall(file1.close)
  1162. _=file2 and pcall(file2.close)
  1163. _=st_file and pcall(st_file.close)
  1164. if #{...}<1 then
  1165.    --restore color after UI and clear shell
  1166.    term.setTextColor(fg) term.setBackgroundColor(bg)
  1167.    shell.run"clear"
  1168. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement