Add files via upload
more fonts, and a python font generation program will be uploaded in a few days
This commit is contained in:
53
UTF-8 print for CC/README.md
Normal file
53
UTF-8 print for CC/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
<a href=#en>English</a> <a href=#zh>中文</a>
|
||||
|
||||
<div id="en"></div>
|
||||
|
||||
## Introduction
|
||||
|
||||
A pixel-based UTF-8 printing program
|
||||

|
||||
|
||||
> $\color{red} \bf Note:$
|
||||
> The CC compiler reads UTF-8 characters as '?',
|
||||
> `print("Hello World")` has the same effect as `print("????")`.
|
||||
> To fix this, read files in `"rb"` mode for proper input handling.
|
||||
|
||||
## How to Create Fonts
|
||||
- Font files should return a table where keys are UTF-8 code points, and values are corresponding character bitmaps.
|
||||
- Each bitmap is a table of equal-length strings representing a 2x3 pixel grid defined by Computer Craft. To use the bottom-right pixel, subtract 128 from the char code to invert `backgroundColor` and `textColor`.
|
||||
- A single font file may contain bitmaps of different sizes, but it **must** include a bitmap for 'H' (ASCII:72) to indicate the maximum height of the font.
|
||||
- The final output uses the maximum bitmap height in the FontFamily as the baseline for bottom-aligned text.
|
||||
- The FontFamily **must** include a '-' (ASCII:45) bitmap for potential word splitting during auto-wrapping.
|
||||
|
||||
## Technical Details
|
||||
|
||||
- `require` a fusion-pixel-12px font consumes approximately **10.5MB** of memory.
|
||||
- `require` a fusion-pixel-8px font consumes approximately **6MB** of memory.
|
||||
- 8px characters occupy 3 rows vertically, while 12px characters occupy 4 rows.
|
||||
- Fonts are sourced from <a href="https://github.com/TakWolf/fusion-pixel-font/releases">fusion-pixel-font</a>.
|
||||
|
||||
<div id="zh"></div>
|
||||
|
||||
## 介绍
|
||||
|
||||
一个基于像素打印的utf8打印程序
|
||||

|
||||
|
||||
> $\color{red} \bf 注意:$
|
||||
> CC 编译器会把utf8字符读作 '?',
|
||||
> `print("你好世界")` 与 `print("????")` 的效果相同, 可以`"rb"`模式读取文件以设置输入
|
||||
|
||||
|
||||
## 如何制作Font
|
||||
- 字体文件返回一个table,键值为utf8编码,值为和对应字体的bitmap。
|
||||
- bitmap为一个包含等长string的table,string中的char属于computer craft定义的2*3像素点阵(如需使用右下角像素,将char的码值减128表示反转backgroundColor 和 textColor)
|
||||
- 单个字体文件中可以有不同尺寸的bitmap,且**需要**有'H'(ascII:72)的bitmap表示该文件中最大bitmap高度
|
||||
- 会以FontFamily出现的最大bitmap高度为基准,最终输出下对齐的文本
|
||||
- FontFamily中**需要**'-'(ascII:45)的bitmap以供自动换行时可能的切断单词使用
|
||||
|
||||
## 技术细节
|
||||
|
||||
- `require`一个fusion-pixel-12px字体,大约消耗**10.5MB**内存
|
||||
- `require`一个fusion-pixel-8px字体,大约消耗**6MB**内存
|
||||
- 8px字符实际占用3格高的字符数, 12px字符实际占用4格高
|
||||
- 字体来自 <a href="https://github.com/TakWolf/fusion-pixel-font/releases"> fusion-pixel-font </a>
|
||||
74
UTF-8 print for CC/example_basic.lua
Normal file
74
UTF-8 print for CC/example_basic.lua
Normal file
@@ -0,0 +1,74 @@
|
||||
---@module "cctAPI"
|
||||
local monitor = peripheral.find("monitor")
|
||||
local computer = term.redirect(monitor)
|
||||
|
||||
-- suggested
|
||||
monitor.setTextScale(0.5)
|
||||
|
||||
term.setBackgroundColor(colors.black)
|
||||
term.setTextColor(colors.white)
|
||||
term.clear()
|
||||
term.setCursorPos(1, 1)
|
||||
|
||||
local function pirntBorderNum()
|
||||
local termWidth, termHeight = term.getSize()
|
||||
local n = math.floor((termWidth - 1) / 10) + 1
|
||||
local str = "0123456789"
|
||||
local tc = string.rep("48", 5)
|
||||
local bc = string.rep("84", 5)
|
||||
term.setCursorPos(1, 1)
|
||||
|
||||
for i = 1, n do
|
||||
term.blit(str, tc, bc)
|
||||
end
|
||||
local num = 1
|
||||
local colorToggle = false
|
||||
term.setCursorPos(1, 2)
|
||||
for y = 2, termHeight do
|
||||
term.setCursorPos(1, y)
|
||||
if colorToggle then
|
||||
term.setBackgroundColor(colors.lightGray)
|
||||
term.setTextColor(colors.yellow)
|
||||
colorToggle = false
|
||||
else
|
||||
term.setBackgroundColor(colors.yellow)
|
||||
term.setTextColor(colors.lightGray)
|
||||
colorToggle = true
|
||||
end
|
||||
term.write(tostring(num))
|
||||
|
||||
num = num + 1
|
||||
if num == 10 then
|
||||
num = 0
|
||||
end
|
||||
end
|
||||
term.setCursorPos(2, 2)
|
||||
term.setBackgroundColor(colors.black)
|
||||
term.setTextColor(colors.white)
|
||||
end
|
||||
pirntBorderNum()
|
||||
local M = require("utf8textutils")
|
||||
|
||||
-- NOTION:
|
||||
-- CC compiler reads utf8 code as '?'
|
||||
-- "print("你好世界")" will act the same as "print("????")"
|
||||
-- read file in "rb" mode instead
|
||||
local file = fs.open("text", "rb")
|
||||
M.printUtf8(file.readLine())
|
||||
|
||||
local cfg1 = M.getCfg()
|
||||
cfg1.fontFamily = M.getFontFamily("fonts/fusion-pixel-8px-proportional-zh_hans")
|
||||
cfg1.textColor = colors.blue
|
||||
cfg1.backgroundColor = colors.green
|
||||
cfg1.autoWrapMode = "b"
|
||||
|
||||
M.printUtf8(M.sub(file.readLine(), 3, -1), cfg1)
|
||||
|
||||
local samplestr = "abcdefghijklmnopqrstuvwxyz"
|
||||
local samplestr2 = samplestr:upper()
|
||||
local samplestr1 = "0123456789"
|
||||
cfg1.fontFamily = M.getFontFamily("fonts/fusion-pixel-12px-proportional-zh_hans")
|
||||
--only if no utf8 character in str
|
||||
M.printUtf8(samplestr, cfg1)
|
||||
M.printUtf8(samplestr2, cfg1)
|
||||
M.printUtf8(samplestr1, cfg1)
|
||||
49
UTF-8 print for CC/example_scrollingtext.lua
Normal file
49
UTF-8 print for CC/example_scrollingtext.lua
Normal file
@@ -0,0 +1,49 @@
|
||||
---@module "cctAPI"
|
||||
local monitor = peripheral.find("monitor")
|
||||
local computer = term.redirect(monitor)
|
||||
|
||||
-- suggested
|
||||
monitor.setTextScale(0.5)
|
||||
|
||||
term.clear()
|
||||
term.setCursorPos(1, 1)
|
||||
|
||||
local M = require("utf8textutils")
|
||||
|
||||
---@param str string
|
||||
---@param fps number films per second
|
||||
local function pirntScrolling(str, fps)
|
||||
str = str .. " "
|
||||
local termWidth = term.getSize()
|
||||
local cfg1 = M.getCfg("noauto")
|
||||
cfg1.masking = { 2, 2, termWidth - 1, cfg1.fontFamily.maxHeight + 1 }
|
||||
|
||||
local spf = 1 / fps
|
||||
---@type FontFamily
|
||||
local fontFamily = cfg1.fontFamily
|
||||
local wid = 0
|
||||
for _, code in M.codes(str) do
|
||||
local bm = M.getCharMap(code, fontFamily)
|
||||
wid = wid + #bm[1]
|
||||
end
|
||||
|
||||
local cursorX = 2
|
||||
local cursorY = 2
|
||||
local maskingWidth = cfg1.masking[3] - cfg1.masking[1]
|
||||
local repeatNum = math.max(maskingWidth, wid)
|
||||
while true do
|
||||
cursorX = 2
|
||||
for i = 1, repeatNum do
|
||||
term.setCursorPos(cursorX, cursorY)
|
||||
M.printUtf8(str, cfg1)
|
||||
|
||||
term.setCursorPos(cursorX + repeatNum, cursorY)
|
||||
M.printUtf8(str, cfg1)
|
||||
cursorX = cursorX - 1
|
||||
|
||||
os.sleep(spf)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
pirntScrolling("hello -- by AAAB60", 5)
|
||||
188150
UTF-8 print for CC/fonts/fusion-pixel-12px-proportional-ja.lua
Normal file
188150
UTF-8 print for CC/fonts/fusion-pixel-12px-proportional-ja.lua
Normal file
File diff suppressed because it is too large
Load Diff
188150
UTF-8 print for CC/fonts/fusion-pixel-12px-proportional-ko.lua
Normal file
188150
UTF-8 print for CC/fonts/fusion-pixel-12px-proportional-ko.lua
Normal file
File diff suppressed because it is too large
Load Diff
188150
UTF-8 print for CC/fonts/fusion-pixel-12px-proportional-latin.lua
Normal file
188150
UTF-8 print for CC/fonts/fusion-pixel-12px-proportional-latin.lua
Normal file
File diff suppressed because it is too large
Load Diff
188150
UTF-8 print for CC/fonts/fusion-pixel-12px-proportional-zh_hans.lua
Normal file
188150
UTF-8 print for CC/fonts/fusion-pixel-12px-proportional-zh_hans.lua
Normal file
File diff suppressed because it is too large
Load Diff
188150
UTF-8 print for CC/fonts/fusion-pixel-12px-proportional-zh_hant.lua
Normal file
188150
UTF-8 print for CC/fonts/fusion-pixel-12px-proportional-zh_hant.lua
Normal file
File diff suppressed because it is too large
Load Diff
110312
UTF-8 print for CC/fonts/fusion-pixel-8px-proportional-ja.lua
Normal file
110312
UTF-8 print for CC/fonts/fusion-pixel-8px-proportional-ja.lua
Normal file
File diff suppressed because it is too large
Load Diff
110312
UTF-8 print for CC/fonts/fusion-pixel-8px-proportional-ko.lua
Normal file
110312
UTF-8 print for CC/fonts/fusion-pixel-8px-proportional-ko.lua
Normal file
File diff suppressed because it is too large
Load Diff
110312
UTF-8 print for CC/fonts/fusion-pixel-8px-proportional-latin.lua
Normal file
110312
UTF-8 print for CC/fonts/fusion-pixel-8px-proportional-latin.lua
Normal file
File diff suppressed because it is too large
Load Diff
110312
UTF-8 print for CC/fonts/fusion-pixel-8px-proportional-zh_hans.lua
Normal file
110312
UTF-8 print for CC/fonts/fusion-pixel-8px-proportional-zh_hans.lua
Normal file
File diff suppressed because it is too large
Load Diff
110312
UTF-8 print for CC/fonts/fusion-pixel-8px-proportional-zh_hant.lua
Normal file
110312
UTF-8 print for CC/fonts/fusion-pixel-8px-proportional-zh_hant.lua
Normal file
File diff suppressed because it is too large
Load Diff
494
UTF-8 print for CC/utf8textutils.lua
Normal file
494
UTF-8 print for CC/utf8textutils.lua
Normal file
@@ -0,0 +1,494 @@
|
||||
---@module "cctAPI"
|
||||
|
||||
---example:
|
||||
---```
|
||||
---for pos, code in codes("你好world") do
|
||||
--- print(pos, code)
|
||||
---end
|
||||
------>
|
||||
---1 20320
|
||||
---4 22909
|
||||
---7 119
|
||||
---8 111
|
||||
---9 114
|
||||
---10 108
|
||||
---11 100
|
||||
---```
|
||||
---@param str string
|
||||
---@return fun():pos:integer, code:integer
|
||||
local function codes(str)
|
||||
local len = #str
|
||||
local i = 0
|
||||
|
||||
local function illegalChar()
|
||||
error("Illegal UTF-8 character at position " .. tostring(i))
|
||||
end
|
||||
|
||||
return function()
|
||||
i = i + 1
|
||||
---@diagnostic disable-next-line
|
||||
if i > len then return end
|
||||
|
||||
local pos = i
|
||||
local byte = string.byte(str, i)
|
||||
|
||||
-- Single-byte character
|
||||
if byte < 0x80 then
|
||||
return pos, byte
|
||||
|
||||
-- Multi-byte sequences
|
||||
elseif byte >= 0xC0 then
|
||||
local bytes_remaining, code = 0, 0
|
||||
|
||||
if byte < 0xE0 then -- 2-byte sequence
|
||||
bytes_remaining = 1
|
||||
code = byte - 0xC0
|
||||
elseif byte < 0xF0 then -- 3-byte sequence
|
||||
bytes_remaining = 2
|
||||
code = byte - 0xE0
|
||||
elseif byte < 0xF8 then -- 4-byte sequence
|
||||
bytes_remaining = 3
|
||||
code = byte - 0xF0
|
||||
else
|
||||
illegalChar()
|
||||
end
|
||||
|
||||
-- Validate remaining bytes
|
||||
if i + bytes_remaining > len then
|
||||
illegalChar()
|
||||
end
|
||||
|
||||
-- Calculate code point
|
||||
for j = 1, bytes_remaining do
|
||||
i = i + 1
|
||||
local next_byte = string.byte(str, i)
|
||||
if next_byte < 0x80 or next_byte >= 0xC0 then
|
||||
illegalChar()
|
||||
end
|
||||
code = code * 0x40 + (next_byte - 0x80)
|
||||
end
|
||||
|
||||
return pos, code
|
||||
else
|
||||
illegalChar()
|
||||
---@diagnostic disable-next-line
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@type FontFamily
|
||||
local defaultFontFamily = {
|
||||
maxHeight = 4,
|
||||
[1] = require("fonts/fusion-pixel-12px-proportional-zh_hans")
|
||||
}
|
||||
|
||||
---@param str string read in `"rb"` mode from file
|
||||
---@param nStartPos integer? 1~n, -n~-1 to represent pos reverse
|
||||
---@param nEndPos integer? 1~n, -n~-1 to represent pos reverse
|
||||
---@return string substring sub string of utf8 character from `nStartPos` to `nEndPos`
|
||||
local function sub(str, nStartPos, nEndPos)
|
||||
local charPos = 0
|
||||
local utf8charPosToStr = {}
|
||||
|
||||
for pos, _ in codes(str) do
|
||||
charPos = charPos + 1
|
||||
utf8charPosToStr[charPos] = pos
|
||||
end
|
||||
|
||||
nStartPos = nStartPos or 1
|
||||
nEndPos = nEndPos or charPos
|
||||
nStartPos = nStartPos < 0 and math.max(1, charPos + nStartPos + 1) or math.min(charPos, nStartPos)
|
||||
nEndPos = nEndPos < 0 and math.max(1, charPos + nEndPos + 1) or math.min(charPos, nEndPos)
|
||||
|
||||
local startByte = utf8charPosToStr[nStartPos]
|
||||
local endByte = utf8charPosToStr[nEndPos + 1] and utf8charPosToStr[nEndPos + 1] - 1 or #str
|
||||
return string.sub(str, startByte, endByte)
|
||||
end
|
||||
|
||||
---@class FontFamily
|
||||
---@field maxHeight integer
|
||||
---@diagnostic disable-next-line
|
||||
---@field [integer] Font get from `require(font_name)`
|
||||
|
||||
---@param ... string module names of font, font should be
|
||||
---@return FontFamily
|
||||
local function getFontFamily(...)
|
||||
local fonts = { maxHeight = 0 }
|
||||
|
||||
for i, path in ipairs({ ... }) do
|
||||
if not fs.exists(path .. ".lua") then
|
||||
error("Font module not found: " .. path)
|
||||
end
|
||||
|
||||
local font = require(path)
|
||||
if not font[72] then
|
||||
error("'H'(ascII:72) not found in font " .. path)
|
||||
end
|
||||
|
||||
fonts[i] = font
|
||||
fonts.maxHeight = math.max(fonts.maxHeight, #font[72])
|
||||
end
|
||||
|
||||
return fonts
|
||||
end
|
||||
---@alias bitmap string[] the bitmap of a character
|
||||
|
||||
---@param code integer
|
||||
---@param fontFamily FontFamily
|
||||
---@return bitmap
|
||||
local function getCharMap(code, fontFamily)
|
||||
local cm
|
||||
for _, font in ipairs(fontFamily) do
|
||||
cm = font[code]
|
||||
if cm then
|
||||
return cm
|
||||
end
|
||||
end
|
||||
error(("char of utf8 %d is not supported"):format(code))
|
||||
end
|
||||
|
||||
---@class Config
|
||||
---@field fontFamily FontFamily?
|
||||
---@field textColor number?
|
||||
---@field backgroundColor number?
|
||||
---@field masking [integer, integer, integer, integer]?
|
||||
---@field autoScroll boolean
|
||||
---@field autoNewLine boolean
|
||||
---@field autoWrapMode "n"|"b"|"-"?
|
||||
---@field autoWrapLen integer?
|
||||
---@field avoidBorder boolean
|
||||
---@field tabLen integer?
|
||||
|
||||
---@see Config
|
||||
---@param preset "noauto"?
|
||||
---@return Config
|
||||
local function getCfg(preset)
|
||||
---@type Config
|
||||
local base = {
|
||||
fontFamily = defaultFontFamily,
|
||||
textColor = nil,
|
||||
backgroundColor = nil,
|
||||
masking = nil,
|
||||
autoScroll = true,
|
||||
autoNewLine = true,
|
||||
autoWrapMode = "b",
|
||||
autoWrapLen = nil,
|
||||
avoidBorder = true,
|
||||
tabLen = 2
|
||||
}
|
||||
if preset == "noauto" then
|
||||
base.autoScroll = false
|
||||
base.autoNewLine = false
|
||||
base.autoWrapMode = "n"
|
||||
end
|
||||
return base
|
||||
end
|
||||
|
||||
|
||||
---`str` should be read in `"rb"` mode from file <br>
|
||||
---`cfg` see [`getCfg()`](lua://Config)
|
||||
---### Config
|
||||
---- **textColor**
|
||||
---- **backgroundColor**
|
||||
---- **fontFamily** use [`getFontFamily()`](lua://FontFamily) to modify
|
||||
---- **masking** representing x1, y1, x2, y2 of 2 coordinates, concent out of the rectange range won't print
|
||||
---- **autoScroll** if true, if next line is over-height, [`term.scroll()`](https://tweaked.cc/module/term.html#v:scroll) will be called, masking will also be scrolled
|
||||
---- **autoNewLine** if true, the output will be like a `\n` added to the end
|
||||
---- **autoWrapMode** <br>
|
||||
----- `"n"` do not auto wrap<br>
|
||||
----- `"b"` English letter will not be broken<br>
|
||||
----- `"-"` English letter will be broken by a `'-'`<br>
|
||||
---here 'letter' matches regex `(?<![a-zA-Z'])[a-zA-Z']+-?`<br>
|
||||
---actually realized avoid using `luautf8` or regex matching
|
||||
---- **autoWrapLen** the maximum distance a line goes from the terminal's left
|
||||
---- **avoidBorder** if true, autoScroll and autoWrap will avoid printing border pixels, which have render issue<br>
|
||||
---for example, autoWrap will start new line at pos (2, y) instead of (1, y)
|
||||
---- **tabLen** the count of `' '` to replace `'\t'`
|
||||
---@param str string
|
||||
---@param cfg Config?
|
||||
local function printUtf8(str, cfg)
|
||||
local cursorX, cursorY = term.getCursorPos()
|
||||
local termWidth, termHeight = term.getSize()
|
||||
|
||||
local cfg = cfg or getCfg()
|
||||
local oriTextColor, oriBackgroundColor = term.getTextColor(), term.getBackgroundColor()
|
||||
local textColor = cfg.textColor or oriTextColor
|
||||
local backgroundColor = cfg.backgroundColor or oriBackgroundColor
|
||||
local masking = cfg.masking
|
||||
local autoScroll = cfg.autoScroll or true
|
||||
local autoNewLine = cfg.autoNewLine
|
||||
local autoWrapMode = cfg.autoWrapMode or "b"
|
||||
local autoWrapLen = cfg.autoWrapLen or termWidth
|
||||
local avoidBorder = cfg.avoidBorder
|
||||
local fontFamily = cfg.fontFamily or defaultFontFamily
|
||||
local tabLen = cfg.tabLen or 2
|
||||
str = string.gsub(str, '\t', string.rep(" ", tabLen))
|
||||
local fontHeight = fontFamily.maxHeight
|
||||
if avoidBorder and autoWrapMode ~= "n" then
|
||||
autoWrapLen = math.min(termWidth - 1, autoWrapLen)
|
||||
cursorX = math.max(2, cursorX)
|
||||
cursorY = math.max(2, cursorY)
|
||||
end
|
||||
local maxHeight = avoidBorder and termHeight - 1 or termHeight
|
||||
---@type integer[]
|
||||
local letterBuffer = {}
|
||||
local dashWidth = #getCharMap(45, fontFamily)[1]
|
||||
---@type { pos: [integer, integer], code: integer }[]
|
||||
local charBuffer = {}
|
||||
|
||||
---@param x integer
|
||||
---@param y integer
|
||||
---@return boolean
|
||||
local function bInMasking(x, y)
|
||||
---@diagnostic disable-next-line
|
||||
return x >= masking[1] and x <= masking[3] and y >= masking[2] and y <= masking[4]
|
||||
end
|
||||
---add new line to charBuffer
|
||||
local function posNewLine()
|
||||
cursorX = avoidBorder and 2 or 1
|
||||
if autoScroll and cursorY + fontHeight > maxHeight then
|
||||
-- scroll term and masking
|
||||
term.scroll(fontHeight)
|
||||
for _, char in ipairs(charBuffer) do
|
||||
char.pos[2] = char.pos[2] - fontHeight
|
||||
end
|
||||
if masking then
|
||||
masking[2] = masking[2] - fontHeight
|
||||
masking[4] = masking[4] - fontHeight
|
||||
end
|
||||
else
|
||||
cursorY = cursorY + fontHeight
|
||||
end
|
||||
end
|
||||
---print char in charBuffer
|
||||
local function printChar()
|
||||
local bIsLastReversed = false
|
||||
term.setTextColor(textColor)
|
||||
term.setBackgroundColor(backgroundColor)
|
||||
for _, char in ipairs(charBuffer) do
|
||||
---@type bitmap
|
||||
local charMap
|
||||
local code = char.code
|
||||
for _, font in ipairs(fontFamily) do
|
||||
if font[code] then
|
||||
charMap = font[code]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local width, height = #charMap[1], #charMap
|
||||
local cursorX, cursorY = unpack(char.pos)
|
||||
if height < fontHeight then
|
||||
if bIsLastReversed then
|
||||
bIsLastReversed = false
|
||||
term.setTextColor(textColor)
|
||||
term.setBackgroundColor(backgroundColor)
|
||||
end
|
||||
for _ = 1, fontHeight - height do
|
||||
term.setCursorPos(cursorX, cursorY)
|
||||
term.write(string.rep(" ", width))
|
||||
cursorY = cursorY + 1
|
||||
end
|
||||
end
|
||||
for y = 1, height do
|
||||
local posY = cursorY + y - 1
|
||||
term.setCursorPos(cursorX, posY)
|
||||
local sCharMapBuffer = charMap[y]
|
||||
for x = 1, width do
|
||||
if not masking or bInMasking(cursorX + x - 1, posY) then
|
||||
local code = string.byte(sCharMapBuffer, x)
|
||||
if code < 128 then
|
||||
code = code + 128
|
||||
if not bIsLastReversed then
|
||||
bIsLastReversed = true
|
||||
term.setTextColor(backgroundColor)
|
||||
term.setBackgroundColor(textColor)
|
||||
end
|
||||
else
|
||||
if bIsLastReversed then
|
||||
bIsLastReversed = false
|
||||
term.setTextColor(textColor)
|
||||
term.setBackgroundColor(backgroundColor)
|
||||
end
|
||||
end
|
||||
term.write(string.char(code))
|
||||
else
|
||||
term.setCursorPos(cursorX + x, posY)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
term.setTextColor(oriTextColor)
|
||||
term.setBackgroundColor(oriBackgroundColor)
|
||||
if autoNewLine then
|
||||
term.setCursorPos(1, cursorY + fontHeight)
|
||||
else
|
||||
term.setCursorPos(cursorX, cursorY)
|
||||
end
|
||||
end
|
||||
local bIsLetter = false
|
||||
local function releaseLetter()
|
||||
if bIsLetter then
|
||||
if autoWrapMode == "-" then
|
||||
local widthSum = cursorX - 1
|
||||
local widthBuffer = {}
|
||||
for index, letter in ipairs(letterBuffer) do
|
||||
widthBuffer[index] = #getCharMap(letter, fontFamily)[1]
|
||||
end
|
||||
local ind = 1
|
||||
local letterBufferLen = #letterBuffer
|
||||
local lastDashPos = 1
|
||||
|
||||
|
||||
while ind <= letterBufferLen do
|
||||
widthSum = widthSum + widthBuffer[ind]
|
||||
if widthSum > autoWrapLen then
|
||||
while widthSum + dashWidth > autoWrapLen do
|
||||
if ind == lastDashPos then
|
||||
-- when have to insert dash in the first character, posNewLine() or throw
|
||||
if ind == 1 and cursorX ~= (avoidBorder and 2 or 1) then
|
||||
widthSum = 0
|
||||
else
|
||||
error("dash too wide or autoWrapLen too small")
|
||||
end
|
||||
end
|
||||
widthSum = widthSum - widthBuffer[ind]
|
||||
ind = ind - 1
|
||||
end
|
||||
-- pos letters before dash
|
||||
for i = lastDashPos, ind do
|
||||
charBuffer[#charBuffer + 1] = {
|
||||
pos = { cursorX, cursorY },
|
||||
code = letterBuffer[i]
|
||||
}
|
||||
cursorX = cursorX + widthBuffer[i]
|
||||
end
|
||||
if widthSum >= 0 then
|
||||
-- add dash
|
||||
charBuffer[#charBuffer + 1] = {
|
||||
pos = { cursorX, cursorY },
|
||||
code = 45
|
||||
}
|
||||
end
|
||||
-- reset
|
||||
widthSum = 0
|
||||
lastDashPos = ind + 1
|
||||
posNewLine()
|
||||
end
|
||||
ind = ind + 1
|
||||
end
|
||||
-- pos letters after dash
|
||||
for i = lastDashPos, letterBufferLen do
|
||||
charBuffer[#charBuffer + 1] = {
|
||||
pos = { cursorX, cursorY },
|
||||
code = letterBuffer[i]
|
||||
}
|
||||
cursorX = cursorX + widthBuffer[i]
|
||||
end
|
||||
elseif autoWrapMode == "b" then
|
||||
local widthSum = cursorX - 1
|
||||
local widthBuffer = {}
|
||||
local ind = 1
|
||||
local letterBufferLen = #letterBuffer
|
||||
while ind <= letterBufferLen do
|
||||
local charMapWidth = #getCharMap(letterBuffer[ind], fontFamily)[1]
|
||||
widthBuffer[ind] = charMapWidth
|
||||
widthSum = widthSum + charMapWidth
|
||||
ind = ind + 1
|
||||
end
|
||||
|
||||
local forceNewLineFlag = false
|
||||
if widthSum > autoWrapLen then
|
||||
if cursorX == (avoidBorder and 2 or 1) then
|
||||
forceNewLineFlag = true
|
||||
else
|
||||
widthSum = widthSum - cursorX + 1
|
||||
if widthSum > autoWrapLen then
|
||||
forceNewLineFlag = true
|
||||
else
|
||||
posNewLine()
|
||||
end
|
||||
end
|
||||
end
|
||||
if forceNewLineFlag then
|
||||
for i = 1, letterBufferLen do
|
||||
if cursorX + widthBuffer[i] > autoWrapLen then
|
||||
posNewLine()
|
||||
end
|
||||
charBuffer[#charBuffer + 1] = {
|
||||
pos = { cursorX, cursorY },
|
||||
code = letterBuffer[i]
|
||||
}
|
||||
cursorX = cursorX + widthBuffer[i]
|
||||
end
|
||||
else
|
||||
for i = 1, letterBufferLen do
|
||||
charBuffer[#charBuffer + 1] = {
|
||||
pos = { cursorX, cursorY },
|
||||
code = letterBuffer[i]
|
||||
}
|
||||
cursorX = cursorX + widthBuffer[i]
|
||||
end
|
||||
end
|
||||
elseif autoWrapMode == "n" then
|
||||
for _, letter in ipairs(letterBuffer) do
|
||||
charBuffer[#charBuffer + 1] = {
|
||||
pos = { cursorX, cursorY },
|
||||
code = letter
|
||||
}
|
||||
cursorX = cursorX + #getCharMap(letter, fontFamily)[1]
|
||||
end
|
||||
end
|
||||
letterBuffer = {}
|
||||
bIsLetter = false
|
||||
end
|
||||
end
|
||||
|
||||
local lastLR = false
|
||||
for _, code in codes(str) do
|
||||
-- handle break line, \r, \n and \r\n will be transferred
|
||||
if code == 13 then
|
||||
releaseLetter()
|
||||
lastLR = true
|
||||
posNewLine()
|
||||
elseif code == 10 and not lastLR then
|
||||
lastLR = false
|
||||
releaseLetter()
|
||||
posNewLine()
|
||||
|
||||
-- record letter for break line
|
||||
elseif code == 45 and bIsLetter then
|
||||
lastLR = false
|
||||
letterBuffer[#letterBuffer + 1] = code
|
||||
releaseLetter()
|
||||
elseif code >= 65 and code <= 90 or (code >= 97 and code <= 122) or code == 39 then
|
||||
lastLR = false
|
||||
letterBuffer[#letterBuffer + 1] = code
|
||||
bIsLetter = true
|
||||
|
||||
-- pos char
|
||||
else
|
||||
lastLR = false
|
||||
releaseLetter()
|
||||
local charMapWidth = #getCharMap(code, fontFamily)[1]
|
||||
if autoWrapMode ~= "n" and cursorX + charMapWidth - 1 > autoWrapLen then
|
||||
posNewLine()
|
||||
end
|
||||
charBuffer[#charBuffer + 1] = {
|
||||
pos = { cursorX, cursorY },
|
||||
code = code
|
||||
}
|
||||
cursorX = cursorX + charMapWidth
|
||||
end
|
||||
end
|
||||
releaseLetter()
|
||||
printChar()
|
||||
end
|
||||
return {
|
||||
codes = codes,
|
||||
printUtf8 = printUtf8,
|
||||
getFontFamily = getFontFamily,
|
||||
sub = sub,
|
||||
getCfg = getCfg,
|
||||
getCharMap = getCharMap
|
||||
}
|
||||
Reference in New Issue
Block a user