about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/css/cascade.nim5
-rw-r--r--src/css/values.nim14
-rw-r--r--src/display/term.nim13
-rw-r--r--src/local/container.nim27
-rw-r--r--src/render/renderdocument.nim33
-rw-r--r--src/server/buffer.nim28
6 files changed, 74 insertions, 46 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim
index 88f0c211..7741f80a 100644
--- a/src/css/cascade.nim
+++ b/src/css/cascade.nim
@@ -198,6 +198,8 @@ func calcPresentationalHints(element: Element): CSSComputedValues =
       of "disc": set_cv "list-style-type", LIST_STYLE_TYPE_DISC
       of "circle": set_cv "list-style-type", LIST_STYLE_TYPE_CIRCLE
       of "square": set_cv "list-style-type", LIST_STYLE_TYPE_SQUARE
+  template set_bgcolor_is_canvas =
+    set_cv "-cha-bgcolor-is-canvas", true
 
   case element.tagType
   of TAG_DIV:
@@ -225,7 +227,10 @@ func calcPresentationalHints(element: Element): CSSComputedValues =
   of TAG_IMG, TAG_CANVAS:
     map_width
     map_height
+  of TAG_HTML:
+    set_bgcolor_is_canvas
   of TAG_BODY:
+    set_bgcolor_is_canvas
     map_bgcolor
     map_text
   of TAG_TEXTAREA:
diff --git a/src/css/values.nim b/src/css/values.nim
index 0bf57675..93864212 100644
--- a/src/css/values.nim
+++ b/src/css/values.nim
@@ -41,7 +41,7 @@ type
     PROPERTY_MIN_WIDTH, PROPERTY_MIN_HEIGHT, PROPERTY_BACKGROUND_IMAGE,
     PROPERTY_CHA_COLSPAN, PROPERTY_CHA_ROWSPAN, PROPERTY_FLOAT,
     PROPERTY_VISIBILITY, PROPERTY_BOX_SIZING, PROPERTY_CLEAR,
-    PROPERTY_TEXT_TRANSFORM
+    PROPERTY_TEXT_TRANSFORM, PROPERTY_BGCOLOR_IS_CANVAS
 
   CSSValueType* = enum
     VALUE_NONE, VALUE_LENGTH, VALUE_COLOR, VALUE_CONTENT, VALUE_DISPLAY,
@@ -50,7 +50,7 @@ type
     VALUE_TEXT_ALIGN, VALUE_LIST_STYLE_POSITION, VALUE_POSITION,
     VALUE_CAPTION_SIDE, VALUE_LENGTH2, VALUE_BORDER_COLLAPSE, VALUE_QUOTES,
     VALUE_COUNTER_RESET, VALUE_IMAGE, VALUE_FLOAT, VALUE_VISIBILITY,
-    VALUE_BOX_SIZING, VALUE_CLEAR, VALUE_TEXT_TRANSFORM
+    VALUE_BOX_SIZING, VALUE_CLEAR, VALUE_TEXT_TRANSFORM, VALUE_BGCOLOR_IS_CANVAS
 
   CSSGlobalValueType* = enum
     VALUE_NOGLOBAL, VALUE_INITIAL, VALUE_INHERIT, VALUE_REVERT, VALUE_UNSET
@@ -224,6 +224,8 @@ type
       clear*: CSSClear
     of VALUE_TEXT_TRANSFORM:
       texttransform*: CSSTextTransform
+    of VALUE_BGCOLOR_IS_CANVAS:
+      bgcoloriscanvas*: bool
     of VALUE_NONE: discard
 
   CSSComputedValues* = ref array[CSSPropertyType, CSSComputedValue]
@@ -300,7 +302,8 @@ const PropertyNames = {
   "visibility": PROPERTY_VISIBILITY,
   "box-sizing": PROPERTY_BOX_SIZING,
   "clear": PROPERTY_CLEAR,
-  "text-transform": PROPERTY_TEXT_TRANSFORM
+  "text-transform": PROPERTY_TEXT_TRANSFORM,
+  "-cha-bgcolor-is-canvas": PROPERTY_BGCOLOR_IS_CANVAS
 }.toTable()
 
 const ValueTypes* = [
@@ -351,7 +354,8 @@ const ValueTypes* = [
   PROPERTY_VISIBILITY: VALUE_VISIBILITY,
   PROPERTY_BOX_SIZING: VALUE_BOX_SIZING,
   PROPERTY_CLEAR: VALUE_CLEAR,
-  PROPERTY_TEXT_TRANSFORM: VALUE_TEXT_TRANSFORM
+  PROPERTY_TEXT_TRANSFORM: VALUE_TEXT_TRANSFORM,
+  PROPERTY_BGCOLOR_IS_CANVAS: VALUE_BGCOLOR_IS_CANVAS
 ]
 
 const InheritedProperties = {
@@ -1196,6 +1200,8 @@ proc getValueFromDecl(val: CSSComputedValue, d: CSSDeclaration,
     val.clear = ?cssClear(cval)
   of VALUE_TEXT_TRANSFORM:
     val.texttransform = ?cssTextTransform(cval)
+  of VALUE_BGCOLOR_IS_CANVAS:
+    return err() # internal value
   of VALUE_NONE:
     discard
   return ok()
diff --git a/src/display/term.nim b/src/display/term.nim
index cd2df219..a4c91e61 100644
--- a/src/display/term.nim
+++ b/src/display/term.nim
@@ -164,9 +164,7 @@ proc resetFormat(term: Terminal): string =
   when termcap_found:
     if term.isatty():
       return term.cap me
-    return SGR()
-  else:
-    return SGR()
+  return SGR()
 
 proc startFormat(term: Terminal, flag: FormatFlags): string =
   when termcap_found:
@@ -473,7 +471,8 @@ proc writeGrid*(term: Terminal, grid: FixedGrid, x = 0, y = 0) =
     for lx in x ..< x + grid.width:
       let i = ly * term.canvas.width + lx
       term.canvas[i] = grid[(ly - y) * grid.width + (lx - x)]
-      if i >= term.canvas.width and FLAG_OVERLINE in term.canvas[i].format.flags and term.emulateOverline:
+      let isol = FLAG_OVERLINE in term.canvas[i].format.flags
+      if i >= term.canvas.width and isol and term.emulateOverline:
         let w = grid[(ly - y) * grid.width + (lx - x)].width()
         let s = i - term.canvas.width
         var j = s
@@ -483,7 +482,8 @@ proc writeGrid*(term: Terminal, grid: FixedGrid, x = 0, y = 0) =
           if cell.str == "":
             cell.str = " "
           if cell.str == " ":
-            cell.format.fgcolor = grid[(ly - y) * grid.width + (lx - x)].format.fgcolor
+            let i = (ly - y) * grid.width + (lx - x)
+            cell.format.fgcolor = grid[i].format.fgcolor
           j += cell[].width()
 
 proc applyConfig(term: Terminal) =
@@ -520,7 +520,8 @@ proc outputGrid*(term: Terminal) =
   if term.config.display.force_clear:
     term.applyConfig()
   term.outfile.write(term.resetFormat())
-  let samesize = term.canvas.width == term.pcanvas.width and term.canvas.height == term.pcanvas.height
+  let samesize = term.canvas.width == term.pcanvas.width and
+    term.canvas.height == term.pcanvas.height
   if term.config.display.force_clear or not term.cleared or not samesize:
     term.outfile.write(term.generateFullOutput(term.canvas))
     term.cleared = true
diff --git a/src/local/container.nim b/src/local/container.nim
index 23c4c2d9..69bad5be 100644
--- a/src/local/container.nim
+++ b/src/local/container.nim
@@ -128,6 +128,7 @@ type
     marks: Table[string, PagePos]
     ishtml*: bool
     filter*: BufferFilter
+    bgcolor*: CellColor
 
 jsDestructor(Highlight)
 jsDestructor(Container)
@@ -470,11 +471,14 @@ proc requestLines*(container: Container, w = container.lineWindow): EmptyPromise
       container.lines[y] = res.lines[y]
       container.lines[y].str.mnormalize()
     container.updateCursor()
+    var isBgNew = container.bgcolor != res.bgcolor
+    if isBgNew:
+      container.bgcolor = res.bgcolor
     if res.numLines != container.numLines:
       container.setNumLines(res.numLines, true)
       container.triggerEvent(STATUS)
     let cw = container.fromy ..< container.fromy + container.height
-    if w.a in cw or w.b in cw or cw.a in w or cw.b in w:
+    if w.a in cw or w.b in cw or cw.a in w or cw.b in w or isBgNew:
       container.triggerEvent(UPDATE)
   )
 
@@ -1587,6 +1591,12 @@ proc readLines*(container: Container, handle: proc(line: SimpleFlexibleLine)) =
 
 proc drawLines*(container: Container, display: var FixedGrid,
     hlcolor: CellColor) =
+  let bgcolor = container.bgcolor
+  template set_fmt(cell, cf: typed) =
+    if cf.pos != -1:
+      cell.format = cf.format
+    if bgcolor != defaultColor and cell.format.bgcolor == defaultColor:
+      cell.format.bgcolor = bgcolor
   var r: Rune
   var by = 0
   let endy = min(container.fromy + display.height, container.numLines)
@@ -1605,8 +1615,7 @@ proc drawLines*(container: Container, display: var FixedGrid,
     var k = 0
     while k < w - container.fromx:
       display[dls + k].str &= ' '
-      if cf.pos != -1:
-        display[dls + k].format = cf.format
+      set_fmt display[dls + k], cf
       inc k
     let startw = w # save this for later
     # Now fill in the visible part of the row.
@@ -1625,14 +1634,18 @@ proc drawLines*(container: Container, display: var FixedGrid,
         let tk = k + rw
         while k < tk:
           display[dls + k].str &= ' '
-          if cf.pos != -1:
-            display[dls + k].format = cf.format
+          set_fmt display[dls + k], cf
           inc k
       else:
         display[dls + k].str &= r
-        if cf.pos != -1:
-          display[dls + k].format = cf.format
+        set_fmt display[dls + k], cf
         k += rw
+    if bgcolor != defaultColor:
+      # Fill the screen if bgcolor is not default.
+      while k < display.width:
+        display[dls + k].str &= ' '
+        display[dls + k].format.bgcolor = bgcolor
+        inc k
     # Finally, override cell formatting for highlighted cells.
     let hls = container.findHighlights(container.fromy + by)
     let aw = container.width - (startw - container.fromx) # actual width
diff --git a/src/render/renderdocument.nim b/src/render/renderdocument.nim
index 2a5ddccd..625984df 100644
--- a/src/render/renderdocument.nim
+++ b/src/render/renderdocument.nim
@@ -283,6 +283,8 @@ type RenderState = object
   # Position of the absolute positioning containing block:
   # https://drafts.csswg.org/css-position/#absolute-positioning-containing-block
   absolutePos: seq[Offset]
+  bgcolor: CellColor
+  root: bool
 
 proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState;
   box: BlockBox; offset: Offset; attrs: WindowAttributes)
@@ -378,14 +380,19 @@ proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState;
       state.absolutePos.add(offset)
       stack.add((nil, Offset(x: -1, y: -1)))
 
-    if box.computed{"visibility"} == VISIBILITY_VISIBLE:
+    if box.computed{"-cha-bgcolor-is-canvas"} and
+        state.bgcolor == defaultColor:
+      #TODO bgimage
       if box.computed{"background-color"}.a != 0: #TODO color blending
-        let ix = toInt(offset.x)
-        let iy = toInt(offset.y)
-        let iex = toInt(offset.x + box.size.w)
-        let iey = toInt(offset.y + box.size.h)
-        let color = box.computed{"background-color"}.cellColor()
-        grid.paintBackground(color, ix, iy, iex, iey, box.node, attrs)
+        state.bgcolor = box.computed{"background-color"}.cellColor()
+    elif box.computed{"visibility"} == VISIBILITY_VISIBLE:
+      if box.computed{"background-color"}.a != 0: #TODO color blending
+          let ix = toInt(offset.x)
+          let iy = toInt(offset.y)
+          let iex = toInt(offset.x + box.size.w)
+          let iey = toInt(offset.y + box.size.h)
+          let color = box.computed{"background-color"}.cellColor()
+          grid.paintBackground(color, ix, iy, iex, iey, box.node, attrs)
       if box.computed{"background-image"}.t == CONTENT_IMAGE and
           box.computed{"background-image"}.s != "":
         # ugly hack for background-image display... TODO actually display images
@@ -418,14 +425,16 @@ proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState;
       for i in countdown(box.nested.high, 0):
         stack.add((box.nested[i], offset))
 
-proc renderDocument*(styledRoot: StyledNode; attrs: WindowAttributes):
-    FlexibleGrid =
-  var grid: FlexibleGrid
+proc renderDocument*(grid: var FlexibleGrid; bgcolor: var CellColor;
+    styledRoot: StyledNode; attrs: WindowAttributes) =
+  grid.setLen(0)
   var state = RenderState(
-    absolutePos: @[Offset(x: 0, y: 0)]
+    absolutePos: @[Offset(x: 0, y: 0)],
+    root: true,
+    bgcolor: bgcolor
   )
   let rootBox = renderLayout(styledRoot, attrs)
   grid.renderBlockBox(state, rootBox, Offset(x: 0, y: 0), attrs)
   if grid.len == 0:
     grid.addLine()
-  return grid
+  bgcolor = state.bgcolor
diff --git a/src/server/buffer.nim b/src/server/buffer.nim
index 3c6dfa21..3804d1b9 100644
--- a/src/server/buffer.nim
+++ b/src/server/buffer.nim
@@ -119,6 +119,7 @@ type
     userstyle: CSSStylesheet
     htmlParser: HTML5ParserWrapper
     srenderer: ref StreamRenderer
+    bgcolor: CellColor
 
   InterfaceOpaque = ref object
     stream: Stream
@@ -624,9 +625,11 @@ proc do_reshape(buffer: Buffer) =
       buffer.uastyle
     else:
       buffer.quirkstyle
+    if buffer.document.cachedSheetsInvalid:
+      buffer.prevstyled = nil
     let styledRoot = buffer.document.applyStylesheets(uastyle,
       buffer.userstyle, buffer.prevstyled)
-    buffer.lines = renderDocument(styledRoot, buffer.attrs)
+    buffer.lines.renderDocument(buffer.bgcolor, styledRoot, buffer.attrs)
     buffer.prevstyled = styledRoot
 
 proc processData(buffer: Buffer): bool =
@@ -1108,7 +1111,6 @@ proc onload(buffer: Buffer) =
         # EOF
         res.atend = true
         buffer.finishLoad().then(proc() =
-          buffer.prevstyled = nil # for incremental rendering
           buffer.do_reshape()
           res.lines = buffer.lines.len
           buffer.state = LOADED
@@ -1123,20 +1125,10 @@ proc onload(buffer: Buffer) =
       buffer.resolveTask(LOAD, res)
     except ErrorAgain:
       break
-  if buffer.document != nil:
-    # incremental rendering: only if we cannot read the entire stream in one
-    # pass
-    #TODO this is too simplistic to be really useful
-    let uastyle = if buffer.document.mode != QUIRKS:
-      buffer.uastyle
-    else:
-      buffer.quirkstyle
-    if buffer.document.cachedSheetsInvalid:
-      buffer.prevstyled = nil
-    let styledRoot = buffer.document.applyStylesheets(uastyle,
-      buffer.userstyle, buffer.prevstyled)
-    buffer.lines = renderDocument(styledRoot, buffer.attrs)
-    buffer.prevstyled = styledRoot
+  # incremental rendering: only if we cannot read the entire stream in one
+  # pass
+  #TODO this could be improved
+  buffer.do_reshape()
 
 proc getTitle*(buffer: Buffer): string {.proxy.} =
   if buffer.document != nil:
@@ -1606,7 +1598,8 @@ proc findAnchor*(buffer: Buffer, anchor: string): bool {.proxy.} =
 
 type GetLinesResult* = tuple[
   numLines: int,
-  lines: seq[SimpleFlexibleLine]
+  lines: seq[SimpleFlexibleLine],
+  bgcolor: CellColor
 ]
 
 proc getLines*(buffer: Buffer, w: Slice[int]): GetLinesResult {.proxy.} =
@@ -1620,6 +1613,7 @@ proc getLines*(buffer: Buffer, w: Slice[int]): GetLinesResult {.proxy.} =
       line.formats.add(SimpleFormatCell(format: f.format, pos: f.pos))
     result.lines.add(line)
   result.numLines = buffer.lines.len
+  result.bgcolor = buffer.bgcolor
 
 macro bufferDispatcher(funs: static ProxyMap, buffer: Buffer,
     cmd: BufferCommand, packetid: int) =