about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buffer/buffer.nim1
-rw-r--r--src/css/values.nim23
-rw-r--r--src/display/pager.nim3
-rw-r--r--src/io/term.nim5
-rw-r--r--src/layout/box.nim7
-rw-r--r--src/layout/engine.nim88
6 files changed, 88 insertions, 39 deletions
diff --git a/src/buffer/buffer.nim b/src/buffer/buffer.nim
index b8e2d69f..685fa4db 100644
--- a/src/buffer/buffer.nim
+++ b/src/buffer/buffer.nim
@@ -285,6 +285,7 @@ proc gotoAnchor(buffer: Buffer) =
       inc i
 
 proc windowChange(buffer: Buffer) =
+  buffer.viewport = Viewport(window: buffer.attrs)
   buffer.width = buffer.attrs.width
   buffer.height = buffer.attrs.height - 1
   buffer.reshape = true
diff --git a/src/css/values.nim b/src/css/values.nim
index 1d28484c..67200532 100644
--- a/src/css/values.nim
+++ b/src/css/values.nim
@@ -322,6 +322,29 @@ func cssLength(val: float64, unit: string): CSSLength =
   else:
     raise newException(CSSValueError, "Invalid unit")
 
+func parseDimensionValues*(s: string): Option[CSSLength] =
+  if s == "": return
+  var i = 0
+  while s[i] in AsciiWhitespace: inc i
+  if i >= s.len or s[i] notin AsciiDigit: return
+  var n: float64
+  while s[i] in AsciiDigit:
+    n *= 10
+    n += float64(decValue(s[i]))
+    inc i
+  if i >= s.len: return some(CSSLength(num: n, unit: UNIT_PX))
+  if s[i] == '.':
+    inc i
+    if i >= s.len: return some(CSSLength(num: n, unit: UNIT_PX))
+    var d = 1
+    while i < s.len and s[i] in AsciiDigit:
+      n += float64(decValue(s[i])) / float64(d)
+      inc d
+      inc i
+  if i >= s.len: return some(CSSLength(num: n, unit: UNIT_PX))
+  if s[i] == '%': return some(CSSLength(num: n, unit: UNIT_PERC))
+  return some(CSSLength(num: n, unit: UNIT_PX))
+
 func color(r, g, b: int): CSSColor =
   return CSSColor(rgba: rgba(r, g, b, 256))
 
diff --git a/src/display/pager.nim b/src/display/pager.nim
index 4d1d56e4..62137805 100644
--- a/src/display/pager.nim
+++ b/src/display/pager.nim
@@ -423,6 +423,9 @@ proc toggleSource*(pager: Pager) {.jsfunc.} =
 
 proc windowChange*(pager: Pager, attrs: WindowAttributes) =
   pager.attrs = attrs
+  pager.display = newFixedGrid(attrs.width, attrs.height - 1)
+  pager.statusmsg = newFixedGrid(attrs.width)
+  pager.term.windowChange(attrs)
   for container in pager.containers:
     container.windowChange(attrs)
 
diff --git a/src/io/term.nim b/src/io/term.nim
index e80eff29..0406907d 100644
--- a/src/io/term.nim
+++ b/src/io/term.nim
@@ -239,8 +239,9 @@ proc processFormat*(term: Terminal, format: var Format, cellf: Format): string =
 
   format = cellf
 
-proc updateWindow*(term: Terminal) =
-  term.attrs = getWindowAttributes(term.outfile)
+proc windowChange*(term: Terminal, attrs: WindowAttributes) =
+  term.attrs = attrs
+  term.cleared = false
 
 proc getCursorPos(term: Terminal): (int, int) =
   term.write(CSI("6n"))
diff --git a/src/layout/box.nim b/src/layout/box.nim
index bf6026da..ef4f7e8a 100644
--- a/src/layout/box.nim
+++ b/src/layout/box.nim
@@ -57,6 +57,7 @@ type
 
   TableBoxBuilder* = ref object of BlockBoxBuilder
     rowgroups*: seq[TableRowGroupBoxBuilder]
+    width*: Option[CSSLength] # WIDTH property
 
   InlineAtom* = ref object of RootObj
     offset*: Offset
@@ -129,10 +130,8 @@ type
   ListItemBox* = ref object of BlockBox
     marker*: InlineContext
 
-  TableCellBox* = ref object of BlockBox
-    colspan*: int
-
   CellWrapper* = object
+    builder*: TableCellBoxBuilder
     box*: BlockBox
     colspan*: int
 
@@ -143,6 +142,8 @@ type
 
   TableContext* = object
     colwidths*: seq[int]
+    reflow*: seq[bool]
+    colwidths_specified*: seq[int]
     rows*: seq[RowContext]
 
   InlineBlockBox* = ref object of InlineAtom
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 4ef81812..866fd786 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -366,14 +366,10 @@ proc setPreferredDimensions(bctx: BlockBox, width: int, height: Option[int]) =
   bctx.margin_left = preferred.margin_left
   bctx.margin_right = preferred.margin_right
 
-proc newBlockBox_common2(bctx: BlockBox, parent: BlockBox, box: BoxBuilder) {.inline.} =
-  bctx.viewport = parent.viewport
-  bctx.computed = box.computed
-  bctx.setPreferredDimensions(parent.compwidth, parent.compheight)
-
-proc newBlockBox_common(parent: BlockBox, box: BoxBuilder): BlockBox {.inline.} =
-  new(result)
-  result.newBlockBox_common2(parent, box)
+proc newBlockBox_common2(box: BlockBox, parent: BlockBox, builder: BoxBuilder) {.inline.} =
+  box.viewport = parent.viewport
+  box.computed = builder.computed
+  box.setPreferredDimensions(parent.compwidth, parent.compheight)
 
 proc newFlowRootBox(viewport: Viewport, box: BoxBuilder, parentWidth: int, parentHeight = none(int)): BlockBox {.inline.} =
   new(result)
@@ -382,32 +378,29 @@ proc newFlowRootBox(viewport: Viewport, box: BoxBuilder, parentWidth: int, paren
   result.setPreferredDimensions(parentWidth, parentHeight)
   result.shrink = result.computed{"width"}.auto
 
-proc newBlockBox(parent: BlockBox, box: BlockBoxBuilder): BlockBox =
-  result = newBlockBox_common(parent, box)
-  result.shrink = result.computed{"width"}.auto and parent.shrink
-
-proc newTableCellBox(parent: BlockBox, box: TableCellBoxBuilder): BlockBox =
+proc newBlockBox(parent: BlockBox, box: BoxBuilder, ignore_parent_shrink = false): BlockBox =
   new(result)
   result.newBlockBox_common2(parent, box)
-  result.shrink = result.computed{"width"}.auto
+  result.shrink = result.computed{"width"}.auto and (ignore_parent_shrink or parent.shrink)
+
+proc newTableCellBox(parent: BlockBox, box: TableCellBoxBuilder): BlockBox =
+  return newBlockBox(parent, box, true)
 
 proc newTableRowBox(parent: BlockBox, box: TableRowBoxBuilder): BlockBox =
-  new(result)
-  result.newBlockBox_common2(parent, box)
-  result.shrink = result.computed{"width"}.auto and parent.shrink
+  return newBlockBox(parent, box)
 
 proc newTableBox(parent: BlockBox, box: TableBoxBuilder): BlockBox =
-  new(result)
-  result.newBlockBox_common2(parent, box)
-  result.shrink = result.computed{"width"}.auto and parent.shrink
+  let table = newBlockBox(parent, box)
+  if box.width.isSome:
+    table.compwidth = box.width.get.px(parent.viewport, parent.compwidth)
+  return table
 
 proc newListItem(parent: BlockBox, builder: ListItemBoxBuilder): ListItemBox =
   new(result)
   result.newBlockBox_common2(parent, builder.content)
-  result.shrink = result.computed{"width"}.auto and parent.shrink
 
 proc newBlockBox(viewport: Viewport, box: BlockBoxBuilder): BlockBox =
-  result = newFlowRootBox(viewport, box, viewport.window.width_px)
+  return newFlowRootBox(viewport, box, viewport.window.width_px)
 
 proc newInlineBlock(viewport: Viewport, builder: InlineBlockBoxBuilder, parentWidth: int, parentHeight = none(int)): InlineBlockBox =
   new(result)
@@ -628,8 +621,11 @@ proc positionBlocks(bctx: BlockBox) =
   bctx.width += bctx.padding_left
   bctx.width += bctx.padding_right
 
-proc buildTableCell(box: TableCellBoxBuilder, parent: BlockBox): BlockBox =
+proc buildTableCell(box: TableCellBoxBuilder, parent: BlockBox, cellwidth = none(int)): BlockBox =
   result = parent.newTableCellBox(box)
+  if cellwidth.isSome:
+    result.compwidth = cellwidth.get
+    result.shrink = true
   if box.inlinelayout:
     result.buildInlineLayout(box.children)
   else:
@@ -646,11 +642,17 @@ proc preBuildTableRow(pctx: var TableContext, box: TableRowBoxBuilder, parent: B
     assert child.computed{"display"} == DISPLAY_TABLE_CELL
     let cellbuilder = TableCellBoxBuilder(child)
     let cell = buildTableCell(cellbuilder, parent)
-    ctx.cells[i] = CellWrapper(box: cell, colspan: cellbuilder.colspan)
+    ctx.cells[i] = CellWrapper(box: cell, builder: cellbuilder, colspan: cellbuilder.colspan)
+    let pwidth = cellbuilder.computed{"width"}
     if pctx.colwidths.len <= n:
       pctx.colwidths.setLen(n + 1)
+    if pctx.colwidths_specified.len <= n:
+      if not pwidth.auto:
+        pctx.colwidths_specified.setLen(n + 1)
     for i in n ..< n + cellbuilder.colspan:
       pctx.colwidths[i] = max(cell.width div cellbuilder.colspan, pctx.colwidths[i])
+      if not pwidth.auto:
+        pctx.colwidths_specified[i] = cell.compwidth
     n += cellbuilder.colspan
     ctx.width += cell.width
     inc i
@@ -661,15 +663,20 @@ proc buildTableRow(pctx: TableContext, ctx: RowContext, parent: BlockBox, builde
   var n = 0
   let row = newTableRowBox(parent, builder)
   for cellw in ctx.cells:
-    let cell = cellw.box
+    var cell = cellw.box
     cell.offset.x += x
-    let colspan = cellw.colspan
-    for i in n ..< n + colspan:
-      x += pctx.colwidths[i]
-    n += colspan
+    var w = 0
+    for i in n ..< n + cellw.colspan:
+      w += pctx.colwidths[i]
+    x += w
+    if pctx.reflow.len > n:
+      for i in n ..< min(n + cellw.colspan, pctx.reflow.len):
+        if pctx.reflow[i]:
+          cell = buildTableCell(cellw.builder, parent, some(w))
+    n += cellw.colspan
     row.nested.add(cell)
     row.height = max(row.height, cell.height)
-  row.width = ctx.width
+  row.width = x
   return row
 
 iterator rows(builder: TableBoxBuilder): TableRowBoxBuilder =
@@ -687,16 +694,25 @@ iterator rows(builder: TableBoxBuilder): TableRowBoxBuilder =
 proc buildTable(box: TableBoxBuilder, parent: BlockBox): BlockBox =
   let table = parent.newTableBox(box)
   var ctx: TableContext
+  var maxw = 0
   for row in box.rows:
-    ctx.rows.add(ctx.preBuildTableRow(row, table))
+    let rctx = ctx.preBuildTableRow(row, table)
+    ctx.rows.add(rctx)
+    maxw = max(rctx.width, maxw)
+  if maxw > table.compwidth and false: #TODO
+    for n in ctx.colwidths_specified:
+      maxw -= n
+    ctx.reflow.setLen(ctx.colwidths.len)
+    for i in 0 ..< ctx.colwidths.len:
+      if ctx.colwidths[i] != 0:
+        ctx.colwidths[i] -= (maxw - table.compwidth) div ctx.colwidths[i]
+        ctx.reflow[i] = true
   for roww in ctx.rows:
-    var x = 0
-    var n = 0
     let row = ctx.buildTableRow(roww, table, roww.builder)
     row.offset.y += table.height
     table.height += row.height
-    table.width = max(row.width, table.width)
     table.nested.add(row)
+    table.width = max(row.width, table.width)
   return table
 
 proc buildBlocks(bctx: BlockBox, blocks: seq[BoxBuilder], node: StyledNode) =
@@ -1050,6 +1066,10 @@ proc generateTableChildWrappers(box: TableBoxBuilder) =
 proc generateTableBox(styledNode: StyledNode, viewport: Viewport): TableBoxBuilder =
   let box = getTableBox(styledNode.computed)
   var blockgroup = newBlockGroup(box) #TODO this probably shouldn't exist
+  if styledNode.node != nil and styledNode.node.nodeType == ELEMENT_NODE:
+    #TODO put this in dom or something
+    let s = Element(styledNode.node).attr("width")
+    box.width = parseDimensionValues(s)
   var ibox: InlineBoxBuilder = nil
   var listItemCounter = 1
   for child in styledNode.children: