From d29c2bc7d739fd95f3fda118e5d9ae80a67101f4 Mon Sep 17 00:00:00 2001 From: gamax92 Date: Fri, 19 Jun 2015 19:02:16 -0600 Subject: [PATCH] Moar fixes wrap unicode.lower/upper since utf8's handling of numbers differs than oc's handling of numbers move getCharWidth out of unicode.lua and into main.lua Fix characters being rendered when they should be hidden by a wide character Fix wide characters not setting the overlapping cell as a space Fix the overlapping character not being rendered when the wide character is removed Fix fill treating wide characters as not wide characters Fix set being crashed on invalid characters Change checkArg and compCheckArg to non merge versions, and edit the error message in compCheckArg to be similar to actual error messages --- src/apis/unicode.lua | 19 ++++++++++------- src/component/screen_sdl2.lua | 32 +++++++++++++++++++++------- src/main.lua | 39 +++++++++++++++++++++-------------- 3 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/apis/unicode.lua b/src/apis/unicode.lua index 2f16edb..0ca88b8 100644 --- a/src/apis/unicode.lua +++ b/src/apis/unicode.lua @@ -3,21 +3,24 @@ local env = ... local utf8 = require("utf8") env.unicode = { - lower = utf8.lower, - upper = utf8.upper, char = utf8.char, len = utf8.len, reverse = utf8.reverse, sub = utf8.sub, } -local function getCharWidth(char) - if unifont[char] ~= nil then - return #unifont[char] / 32 - end - return 1 +function env.unicode.lower(str) + cprint("unicode.lower", str) + if type(str) == "number" then str = tostring(str) end + checkArg(1,str,"string") + return utf8.lower(str) +end +function env.unicode.upper(str) + cprint("unicode.upper", str) + if type(str) == "number" then str = tostring(str) end + checkArg(1,str,"string") + return utf8.upper(str) end - function env.unicode.isWide(str) cprint("unicode.isWide", str) checkArg(1,str,"string") diff --git a/src/component/screen_sdl2.lua b/src/component/screen_sdl2.lua index 67d7461..742aa7e 100644 --- a/src/component/screen_sdl2.lua +++ b/src/component/screen_sdl2.lua @@ -111,8 +111,8 @@ function elsa.draw() SDL.renderPresent(renderer) end -local char8 = ffi.new("uint32_t[?]", 8*16); -local char16 = ffi.new("uint32_t[?]", 16*16); +local char8 = ffi.new("uint32_t[?]", 8*16) +local char16 = ffi.new("uint32_t[?]", 16*16) local function renderChar(char,x,y,fg,bg) if unifont[char] == nil then char = 63 @@ -139,15 +139,31 @@ local function renderChar(char,x,y,fg,bg) SDL.updateTexture(texture, ffi.new("SDL_Rect",{x=x,y=y,w=size*4,h=16}), pchar, (size*4) * ffi.sizeof("uint32_t")) end -local function setPos(x,y,c,fg,bg) - local renderchange = screen.txt[y][x] ~= utf8.char(c) or screen.bg[y][x] ~= scrbgc or (screen.txt[y][x] ~= " " and screen.fg[y][x] ~= scrfgc) +local function screenSet(x,y,c) screen.txt[y][x] = utf8.char(c) screen.fg[y][x] = scrfgc screen.bg[y][x] = scrbgc screen.fgp[y][x] = scrfgp screen.bgp[y][x] = scrbgp +end + +local function setPos(x,y,c,fg,bg) + local renderchange = screen.txt[y][x] ~= utf8.char(c) or screen.bg[y][x] ~= scrbgc or (screen.txt[y][x] ~= " " and screen.fg[y][x] ~= scrfgc) + local charWidth = getCharWidth(c) + local renderafter = getCharWidth(utf8.byte(screen.txt[y][x])) > 1 and charWidth == 1 and x < width + if x > 1 and getCharWidth(utf8.byte(screen.txt[y][x-1])) > 1 then + renderchange = false + else + screenSet(x,y,c) + end if renderchange then renderChar(c,(x-1)*8,(y-1)*16,fg,bg) + if charWidth > 1 and x < width then + screenSet(x+1,y,32) + end + end + if renderafter then + renderChar(32,x*8,(y-1)*16,screen.fg[y][x+1],screen.bg[y][x+1]) end end @@ -248,14 +264,14 @@ function cec.fill(x1, y1, w, h, char) -- Fills a portion of the screen at the sp if w <= 0 or h <= 0 then return true end - local x2 = x1+w-1 + local code = utf8.byte(char) + local x2 = x1+(w*getCharWidth(code))-1 local y2 = y1+h-1 if x2 < 1 or y2 < 1 or x1 > width or y1 > height then return true end - local code = utf8.byte(char) for y = y1,y2 do - for x = x1,x2 do + for x = x1,x2,getCharWidth(code) do setPos(x,y,code,scrfgc,scrbgc) end end @@ -305,7 +321,7 @@ function cec.set(x, y, value, vertical) -- Plots a string value to the screen at if x >= 1 then setPos(x,y,c,scrfgc,scrbgc) end - x = x + #unifont[c]/32 + x = x + getCharWidth(c) if x > width then break end end end diff --git a/src/main.lua b/src/main.lua index 340c33a..d50339a 100644 --- a/src/main.lua +++ b/src/main.lua @@ -45,27 +45,28 @@ machine = { signals = {}, } -local function _checkArg(pos, n, have, ...) +local function check(have, want, ...) + if not want then + return false + else + return have == want or check(have, ...) + end +end + +function checkArg(n, have, ...) have = type(have) - local function check(want, ...) - if not want then - return false - else - return have == want or check(...) - end - end - if not check(...) then + if not check(have, ...) then local msg = string.format("bad argument #%d (%s expected, got %s)", n, table.concat({...}, " or "), have) - error(msg, pos) + error(msg, 3) end end -function checkArg(...) - _checkArg(4, ...) -end - -function compCheckArg(...) - _checkArg(5, ...) +function compCheckArg(n, have, ...) + have = type(have) + if not check(have, ...) then + local msg = string.format("bad arguments #%d (%s expected, got %s)", n, table.concat({...}, " or "), have) + error(msg, 4) + end end if true then @@ -236,6 +237,12 @@ for line in elsa.filesystem.lines("unifont.hex") do local a,b = line:match("(.+):(.*)") unifont[tonumber(a,16)] = b end +function getCharWidth(char) + if unifont[char] ~= nil then + return #unifont[char] / 32 + end + return 1 +end -- load api's into environment elsa.filesystem.load("apis/computer.lua")(env)