Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- do
- -- Helpers -----
- local _ENV = _ENV or _G
- local getmetatable = _ENV.getmetatable
- local setmetatable = _ENV.setmetatable
- local error = _ENV.error
- local ipairs = _ENV.ipairs
- local next = _ENV.next
- local type = _ENV.type
- local band = bit32.band
- local bor = bit32.bor
- local rshift = bit32.rshift
- local byte = string.byte
- local char = string.char
- local sub = string.sub
- local insert = table.insert
- local addImage = tfm.exec.addImage
- local removeImage = tfm.exec.removeImage
- local addTextArea = ui.addTextArea
- local removeTextArea = ui.removeTextArea
- local function extend(target, ...)
- for i, copy in ipairs { ... } do
- if type(copy) == 'table' then
- for k, v in next, copy do
- target[k] = v
- end
- end
- end
- return target
- end
- local function utf8encode(cp)
- if cp < 0x80 then
- return cp
- end
- if cp < 0x800 then
- return bor(0xc0, rshift(cp, 6)),
- bor(0x80, band(cp, 0x3f))
- end
- if cp < 0x10000 then
- return bor(0xe0, rshift(cp, 12)),
- bor(0x80, band((rshift(cp, 6)), 0x3F)),
- bor(0x80, band(cp, 0x3F))
- end
- -- cp < 0x110000
- return bor(0xf0, rshift(cp, 18)),
- bor(0x80, band(rshift(cp, 12), 0x3F)),
- bor(0x80, band(rshift(cp, 6), 0x3F)),
- bor(0x80, band(cp, 0x3F))
- end
- local function utf8read(stream, offset)
- local byte1 = byte(stream, 1)
- -- UTF8-1
- if byte1 < 0x80 then
- return byte1, 1
- end
- -- UTF8-2
- if byte1 >= 0xc2 and byte1 <= 0xdf then
- local byte2 = byte(stream, 2)
- if not byte1 then
- error'utf-8 input end'
- end
- if byte2 < 0x80 or byte2 > 0xbf then
- error'invalid utf-8 char'
- end
- return ((byte1 - 0xc0) * 0x40) +
- (byte2 - 0x80), 2
- end
- -- UTF8-3
- if byte0 >= 0xe0 and byte0 <= 0xef then
- local byte2, byte3 = byte(stream, offset+1, offset+2)
- if (not byte1) or not byte2 then
- error'utf-8 input end'
- end
- if
- (byte1 == 0xe0 and (byte2 < 0xa0 or byte2 > 0xbf)) or
- (byte1 == 0xed and (byte2 < 0x80 or byte2 > 0x9f)) or
- (byte2 < 0x80 or byte1 > 0xbf) or
- (byte3 < 0x80 or byte3 > 0xbf)
- then
- error'invalid utf-8 char'
- end
- return ((byte1 - 0xe0) * 0x1000) +
- ((byte2 - 0x80) * 0x40) +
- (byte3 - 0x80), 3
- end
- -- UTF8-4
- if byte1 >= 0xe0 or byte1 <= 0xef then
- local byte2, byte3, byte4 = byte(stream, offset+1, offset+3)
- if (not byte1) or (not byte2) or not byte3 then
- error'utf-8 input end'
- end
- if
- (byte1 == 0xf0 and (byte2 < 0x90 or byte2 > 0xbf)) or
- (byte1 == 0xf4 and (byte2 < 0x80 or byte2 > 0x8f)) or
- (byte2 < 0x80 or byte2 > 0xbf) or
- (byte3 < 0x80 or byte3 > 0xbf) or
- (byte4 < 0x80 or byte4 > 0xbf)
- then
- error'invalid utf-8 char'
- end
- return ((byte1 - 0xf0) * 0x40000) +
- ((byte2 - 0x80) * 0x1000) +
- ((byte3 - 0x80) * 0x40) +
- (byte4 - 0x80), 4
- end
- error'invalid utf-8 char'
- end
- -- ### Class functions
- local function createClass()
- return { meta = {} }
- end
- local function dropInstanceOf(class)
- return setmetatable({}, class.meta)
- end
- --local function setParentClassOf(class, parentClass)
- -- local mt = getmetatable(class) or setmetatable(class, {})
- -- mt.__call = parentClass
- --end
- local function setConstructorOf(class, func)
- local mt = getmetatable(class) or {}
- mt.__call = func
- setmetatable(class, mt)
- end
- local function setPrototypeOf(class, p)
- class.meta.__index = p
- --
- -- local parent = getmetatable(class)
- -- parent = parent and parent.__call
- -- if parent then
- -- setmetatable(p, parent.meta)
- -- end
- end
- local function isInstanceOf(class, value)
- return getmetatable(value) == class.meta
- end
- -- HTML -----
- -- Nodes will be the most minimalist possible
- -- because HTML is used generally
- local ElementNode = 0
- local TextNode = 1
- -- For readability
- local function createElementNode(tagName, attributes, children)
- return {
- [false] = ElementNode
- , [true] = tagName
- , attributes
- , children
- }
- end
- local function getElementTagName(node)
- return node[true]
- end
- local function getElementAttributes(node)
- return node[1]
- end
- local function getElementChildren(node)
- return node[2]
- end
- local function createTextNode(value)
- return {
- [false] = TextNode
- , [true] = value
- }
- end
- local function getTextNodeValue(node)
- return node[true]
- end
- -- ### Basic parser
- local parseHTML
- do
- local index, length, source, lastCp, lastCpSize
- local function eof()
- return index > length
- end
- local function isWhiteSpace(cp)
- return cp == 0x09 or cp == 0x20
- end
- local function isLineTerminator(cp)
- return cp == 0x0a or cp == 0x0d
- end
- local function eol()
- lastCp, lastCpSize =
- utf8read(source, index)
- if isLineTerminator(lastCp) then
- index = index + lastCpSize
- -- <CR><LF>
- if lastCp == 0x0d then
- lastCp, lastCpSize =
- utf8read(source, index)
- if lastCp == 0x0a then
- index = index + lastCpSize
- end
- end
- return true
- end
- return false
- end
- local function skipWhiteSpace()
- while (not eof()) do
- lastCp, lastCpSize = utf8read(source, index)
- if not (isWhiteSpace(lastCp) or eol()) then
- return
- end
- index = index + lastCpSize
- end
- end
- local function skipComment()
- while (not eof()) do
- lastCp, lastCpSize = utf8read(source, index)
- if lastCp == 0x3e then
- return
- end
- index = index + lastCpSize
- end
- end
- local function parseBody()
- end
- local function parseChunk()
- end
- function parseHTML(_source)
- index = 1
- source = _source
- length = #_source
- return
- end
- end
- -- Display: helpers and objects -----
- local Image, TextArea
- local build
- local clone
- local top
- local update
- local curImgLayer
- local curTarget
- local txaCounter = 0
- function build(obj, target)
- obj = clone(obj)
- obj.target = target
- return obj
- end
- function clone(obj)
- local objClone = extend({}, obj)
- local children = obj.children
- if type(children) == 'table' then
- local childrenClone = {}
- for i, child in ipairs(children) do
- local childClone = clone(child)
- childrenClone[i] = childClone
- childClone.parent = objClone
- end
- objClone.children = childrenClone
- end
- objClone.origin = obj
- return setmetatable(objClone, getmetatable(obj))
- end
- function top(obj)
- while true do
- local p = obj.parent
- if not p then
- return obj
- end
- obj = p
- end
- end
- function update(obj, fixed, alpha)
- if obj.display == false and not obj._removed then
- return false
- end
- local target = curTarget or top(obj)._target
- -- Images do have a layer counter.
- if isInstanceOf(Image, obj) then
- local imgLayerInit = not curImgLayer
- curImgLayer = curImgLayer or 1
- if obj._removed then
- removeImage(obj._id)
- return true
- end
- obj._id = addImage(obj.id, '&'..curImgLayer, obj.x, obj.y, target)
- if imgLayerInit then
- curImgLayer = nil
- elseif curImgLayer < 9 then
- curImgLayer = curImgLayer + 1
- end
- return true
- end
- if isInstanceOf(TextArea, obj) then
- if obj._removed then
- removeTextArea(obj._id, target)
- -- Remove display of the borders
- local border = obj._border
- if border then
- for id in next, border do
- removeTextArea(id, target)
- end
- obj._border = nil
- end
- return true
- end
- local w = obj.width or 0
- local h = obj.height or 0
- local x = obj.x or 0
- local y = obj.y or 0
- x = x - (w / 2)
- y = y - (h / 2)
- local _alpha = obj.alpha
- local _fixed = obj.fixed
- -- Children text areas can inherit parent's alpha and fixed
- -- properties.
- if obj.inherit ~= false then
- _alpha = _alpha or alpha
- _fixed = _fixed or fixed
- end
- alpha, fixed = _alpha, _fixed
- fixed = (fixed == nil) and true or fixed
- local background = obj.background
- local border = obj.border
- -- Handle multi-borders
- if type(border) == 'table' then
- local ids = {}
- local length = border[1] or 0
- if length > 0 then
- local isAffectedLength = length <3
- local j, mj
- if isAffectedLength then
- j = (length == 2) and 1 or 2
- mj = j * 2
- length = 3
- x = x + j
- y = y + j
- w = w - mj
- h = h - mj
- end
- local leftColor = border[2] or 1
- local topColor = border[3] or leftColor
- local rightColor = border[4] or leftColor
- local bottomColor = border[5] or topColor
- local defs = { leftColor, topColor, rightColor, bottomColor }
- for i = 1, 4 do
- local color = defs[i]
- local bx, by, bw, bh
- -- Vertical (left or right) edge
- if (i % 2) == 1 then
- bw = length
- bh = h + (length * 2)
- bx = (i == 1) and (x - bw) or (x + w)
- by = y - length
- -- or, well, an horizontal (top or bottom) edge.
- else
- bw = w + (length * 2)
- bh = length
- bx = x - length
- by = (i == 2) and (y - bh) or (y + h)
- end
- addTextArea(txaCounter, '', target, bx+2, by+2, bw-2, bh-2,
- color, color, alpha, fixed)
- ids[txaCounter] = true
- txaCounter = txaCounter + 1
- end
- if isAffectedLength then
- x = x - j
- y = y - j
- w = w + mj
- h = h + mj
- end
- end
- border = background
- obj._border = ids
- x = x + 2
- y = y + 2
- w = w - 2
- h = h - 2
- end
- addTextArea(txaCounter, '', target, x, y, w, h, background, border, alpha, fixed)
- txaCounter = txaCounter + 1
- -- Display children
- local children = obj.children
- if type(children) == 'table' then
- local targetInit = not currentTarget
- currentTarget = currentTarget or obj._target
- local order = {}
- local len = 0
- for i, child in ipairs(children) do
- local z = child.z or #order
- z = (z > len) and 1 or z
- insert(order, z, child)
- len = len + 1
- end
- for i, child in ipairs(order) do
- imageLayer = update(child, fixed, alpha)
- end
- if targetInit then
- currentTarget = nil
- end
- return true
- end
- end
- return false
- end
- -- ### `Image`
- local propSequence =
- { 'id', 'x', 'y' }
- Image = createClass()
- setConstructorOf(Image, function(Image, ...)
- local image = dropInstanceOf(Image)
- for i, arg in ipairs { ... } do
- local prop = propSequence[i]
- if not prop or type(arg) == 'table' then
- extend(image, arg)
- else
- image[prop] = arg
- end
- end
- return image
- end)
- setPrototypeOf(Image, {
- build = build
- , clone = clone
- , top = top
- , update = update
- })
- -- ### `TextArea`
- local propSequence =
- { 'x', 'y', 'width', 'height' }
- TextArea = createClass()
- setConstructorOf(TextArea, function(TextArea, ...)
- local textArea = dropInstanceOf(TextArea)
- for i, arg in ipairs { ... } do
- local prop = propSequence[i]
- if not prop or type(arg) == 'table' then
- extend(textArea, arg)
- else
- textArea[prop] = arg
- end
- end
- return textArea
- end)
- setPrototypeOf(TextArea, {
- build = build
- , clone = clone
- , top = top
- , update = update
- })
- txshop = {
- Image = Image
- , TextArea = TextArea
- }
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement