diff options
-rw-r--r-- | src/io/buffer.nim | 93 | ||||
-rw-r--r-- | src/io/cell.nim | 81 | ||||
-rw-r--r-- | src/layout/box.nim | 4 | ||||
-rw-r--r-- | src/layout/engine.nim | 9 |
4 files changed, 112 insertions, 75 deletions
diff --git a/src/io/buffer.nim b/src/io/buffer.nim index 9196504b..da33ae34 100644 --- a/src/io/buffer.nim +++ b/src/io/buffer.nim @@ -200,6 +200,7 @@ proc clearDisplay*(buffer: Buffer) = buffer.display = newFixedGrid(buffer.width, buffer.height) proc refreshDisplay*(buffer: Buffer) = + var r: Rune var y = 0 buffer.clearDisplay() @@ -207,21 +208,31 @@ proc refreshDisplay*(buffer: Buffer) = buffer.lastVisibleLine - 1]: var w = 0 var i = 0 + var j = 0 while w < buffer.fromx and i < line.len: - w += line[i].rune.width() - inc i + fastRuneAt(line.str, i, r) + w += r.width() + inc j let dls = y * buffer.width - var j = 0 + var k = 0 var n = 0 - while w < buffer.fromx + buffer.width and i < line.len: - w += line[i].rune.width() - if line[i].rune.width() == 0 and j != 0: + var cf = line.findFormat(j) + var nf = line.findNextFormat(j) + while w < buffer.fromx + buffer.width and i < line.str.len: + fastRuneAt(line.str, i, r) + w += r.width() + if nf.pos != -1 and nf.pos <= j: + cf = nf + nf = line.findNextFormat(j) + if r.width() == 0 and k != 0: inc n - buffer.display[dls + j - n].runes.add(line[i].rune) - buffer.display[dls + j - n].formatting = line[i].formatting - j += line[i].rune.width() - inc i + buffer.display[dls + k - n].runes.add(r) + if cf.pos != -1: + buffer.display[dls + k - n].formatting = cf.formatting + buffer.display[dls + k - n].nodes = cf.nodes + k += r.width() + inc j inc y @@ -528,7 +539,7 @@ proc refreshTermAttrs*(buffer: Buffer): bool = if newAttrs != buffer.attrs: buffer.attrs = newAttrs buffer.width = newAttrs.width - buffer.height = newAttrs.height + buffer.height = newAttrs.height - 1 return true return false @@ -546,46 +557,47 @@ func formatFromLine(line: CSSRowBox): Formatting = result.strike = true proc setRowBox(buffer: Buffer, line: CSSRowBox) = - if line.runes.len == 0: - return + var r: Rune let x = line.x let y = line.y - let format = line.formatFromLine() while buffer.lines.len <= y: buffer.addLine() var i = 0 + var j = 0 var cx = 0 - while cx < x and i < buffer.lines[y].len: - cx += buffer.lines[y][i].rune.width() - inc i + while cx < x and i < buffer.lines[y].str.len: + fastRuneAt(buffer.lines[y].str, i, r) + cx += r.width() + inc j - var oline = buffer.lines[y].subline(i) - buffer.lines[y].setLen(i) - var j = 0 - var nx = cx + let ostr = buffer.lines[y].str.substr(i) + let oformats = buffer.lines[y].formats.subformats(j) + buffer.lines[y].str.setLen(i) + buffer.lines[y].setLen(j) - #TODO not sure - while nx < x: - buffer.lines.addCell(y, Rune(' ')) - inc nx + buffer.lines.addFormat(y, j, line.formatFromLine(), line.nodes) - buffer.lines.addFormat(y, format) - while j < line.runes.len: - buffer.lines.addCell(y, line.runes[j]) - nx += line.runes[j].width() - inc j + var nx = cx + if nx < x: + buffer.lines[y].str &= ' '.repeat(x - nx) + nx = x + + buffer.lines[y].str &= line.str + nx += line.str.width() i = 0 - while cx < nx and i < oline.len: - cx += oline[i].rune.width() - inc i + j = 0 + while cx < nx and i < ostr.len: + fastRuneAt(ostr, i, r) + cx += r.width() + inc j - if i < oline.len: - let nol = oline.subLine(i) - buffer.lines[y].add(nol) + if i < ostr.len: + let oline = FlexibleLine(str: ostr.substr(i), formats: oformats.subformats(j)) + buffer.lines[y].add(oline) proc updateCursor(buffer: Buffer) = if buffer.fromy > buffer.lastVisibleLine - 1: @@ -633,6 +645,7 @@ proc renderPlainText*(buffer: Buffer, text: string) = while i < text.len: if text[i] == '\n': buffer.addLine() + buffer.lines.addFormat(buffer.lines.len - 1, format) inc y x = 0 inc i @@ -640,17 +653,17 @@ proc renderPlainText*(buffer: Buffer, text: string) = inc i elif text[i] == '\t': for i in 0..8: - buffer.lines.addCell(Rune(' '), format) + buffer.lines[^1].str &= ' ' inc i elif text[i] == '\e': i = format.parseAnsiCode(text, i) elif text[i].isControlChar(): - buffer.lines.addCell(Rune('^'), format) - buffer.lines.addCell(Rune(text[i].getControlLetter()), format) + buffer.lines.addCell(Rune('^')) + buffer.lines.addCell(Rune(text[i].getControlLetter())) inc i else: fastRuneAt(text, i, r) - buffer.lines.addCell(r, format) + buffer.lines.addCell(r) buffer.updateCursor() proc renderDocument*(buffer: Buffer) = diff --git a/src/io/cell.nim b/src/io/cell.nim index 40ce2c57..74b07353 100644 --- a/src/io/cell.nim +++ b/src/io/cell.nim @@ -21,15 +21,12 @@ type formatting*: Formatting nodes*: seq[Node] - FlexibleCell* = object of Cell - rune*: Rune - - FormattingCell = object of Cell - pos: int + FormattingCell* = object of Cell + pos*: int FlexibleLine* = object str*: string - formats: seq[FormattingCell] + formats*: seq[FormattingCell] FlexibleGrid* = seq[FlexibleLine] @@ -38,6 +35,12 @@ type FixedGrid* = seq[FixedCell] +#TODO ????? +func `==`*(a: FixedCell, b: FixedCell): bool = + return a.formatting == b.formatting and + a.runes == b.runes and + a.nodes == b.nodes + func newFixedGrid*(w: int, h: int = 1): FixedGrid = return newSeq[FixedCell](w * h) @@ -53,8 +56,7 @@ func len*(line: FlexibleLine): int = func newFormatting*(): Formatting = return Formatting(fgcolor: defaultColor, bgcolor: defaultColor) -func `[]`*(line: FlexibleLine, pos: int): FlexibleCell = - result.rune = line.str.runeAtPos(pos) +func findFormat*(line: FlexibleLine, pos: int): FormattingCell = var i = 0 while i < line.formats.len: if line.formats[i].pos > pos: @@ -62,26 +64,49 @@ func `[]`*(line: FlexibleLine, pos: int): FlexibleCell = inc i dec i if i != -1: - result.formatting = line.formats[i].formatting + result = line.formats[i] else: - result.formatting = newFormatting() + result.pos = -1 -func subLine*(line: FlexibleLine, i: int): FlexibleLine = - for f in line.formats: - if f.pos >= i: - result.formats.add(f) - result.str = line.str.runeSubstr(i) +func findNextFormat*(line: FlexibleLine, pos: int): FormattingCell = + var i = 0 + while i < line.formats.len: + if line.formats[i].pos > pos: + break + inc i + if i < line.formats.len: + result = line.formats[i] + else: + result.pos = -1 -proc setLen*(line: var FlexibleLine, i: int) = - var nf = newSeq[FormattingCell]() - for f in line.formats: - if f.pos < i: - nf.add(f) - line.str = line.str.runeSubstr(0, i) +func subformats*(formats: seq[FormattingCell], pos: int): seq[FormattingCell] = + var i = 0 + while i < formats.len: + if formats[i].pos >= pos: + if result.len == 0 and i > 0: + var f = formats[i - 1] + f.pos = 0 + result.add(f) + var f = formats[i] + f.pos -= pos + result.add(f) + inc i + + if result.len == 0 and i > 0: + var f = formats[i - 1] + f.pos = 0 + result.add(f) + +proc setLen*(line: var FlexibleLine, len: int) = + for i in 0 ..< line.formats.len: + if line.formats[i].pos >= len: + line.formats.setLen(i) + break + #line.formats = line.formats.filter((x) => x.pos < len) proc add*(a: var FlexibleLine, b: FlexibleLine) = let l = a.len - a.formats.add(b.formats.map((x) => FormattingCell(formatting: x.formatting, pos: l + x.pos))) + a.formats.add(b.formats.map((x) => FormattingCell(formatting: x.formatting, nodes: x.nodes, pos: l + x.pos))) a.str &= b.str proc addLine*(grid: var FlexibleGrid) = @@ -90,16 +115,14 @@ proc addLine*(grid: var FlexibleGrid) = proc addFormat*(grid: var FlexibleGrid, y: int, format: Formatting) = grid[y].formats.add(FormattingCell(formatting: format, pos: grid[y].len)) -proc addCell*(grid: var FlexibleGrid, y: int, r: Rune) = - grid[y].str &= $r +proc addFormat*(grid: var FlexibleGrid, y: int, pos: int, format: Formatting, nodes: seq[Node]) = + grid[y].formats.add(FormattingCell(formatting: format, nodes: nodes, pos: pos)) -proc addCell*(grid: var FlexibleGrid, y: int, r: Rune, format: Formatting) = - if grid[y].formats.len == 0 or grid[y].formats[^1].formatting != format: - grid[y].formats.add(FormattingCell(formatting: format, pos: grid[y].len)) +proc addCell*(grid: var FlexibleGrid, y: int, r: Rune) = grid[y].str &= $r -proc addCell*(grid: var FlexibleGrid, r: Rune, format: Formatting) = - grid.addCell(grid.len - 1, r, format) +proc addCell*(grid: var FlexibleGrid, r: Rune) = + grid.addCell(grid.len - 1, r) template inc_check(i: int) = inc i diff --git a/src/layout/box.nim b/src/layout/box.nim index bee93363..07bc5f5b 100644 --- a/src/layout/box.nim +++ b/src/layout/box.nim @@ -1,5 +1,3 @@ -import unicode - import types/enums import css/style import html/dom @@ -50,7 +48,7 @@ type fontstyle*: CSSFontStyle fontweight*: int textdecoration*: CSSTextDecoration - runes*: seq[Rune] + str*: string nodes*: seq[Node] CSSInlineBox* = ref CSSInlineBoxObj diff --git a/src/layout/engine.nim b/src/layout/engine.nim index 506770b9..71dab4c2 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -84,8 +84,10 @@ proc processInlineBox(parent: CSSBox, str: string): CSSBox = rowbox.setup(ibox.cssvalues, ibox.bcontext.nodes) var r: Rune while i < str.len: + var rw = 0 case str[i] of ' ', '\n', '\t': + rw = 1 inc i let wsr = ibox.cssvalues[PROPERTY_WHITESPACE].whitespace if ibox.context.whitespace: @@ -113,12 +115,13 @@ proc processInlineBox(parent: CSSBox, str: string): CSSBox = else: ibox.context.whitespace = false fastRuneAt(str, i, r) + rw = r.width() if rowbox.width + r.width() > ibox.width: inlineWrap(ibox, rowi, fromx, rowbox) - rowbox.width += r.width() - rowbox.runes.add(r) - if rowbox.runes.len > 0: + rowbox.width += rw + rowbox.str &= $r + if rowbox.str.len > 0: ibox.content.add(rowbox) ibox.context.fromx = fromx + rowbox.width ibox.context.conty = true |