about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2021-11-15 19:28:46 +0100
committerbptato <nincsnevem662@gmail.com>2021-11-15 19:36:15 +0100
commitdc70358d994894ba707e0fb42660036eba603d38 (patch)
tree96122416a2748ed88240bc500e2633be734e5224
parentf802b92f0071700e3aacf560d2a90fb47b3baf6b (diff)
downloadchawan-dc70358d994894ba707e0fb42660036eba603d38.tar.gz
Fix some whitespace bugs
-rw-r--r--src/html/parser.nim18
-rw-r--r--src/io/buffer.nim31
-rw-r--r--src/layout/box.nim1
-rw-r--r--src/layout/engine.nim53
4 files changed, 53 insertions, 50 deletions
diff --git a/src/html/parser.nim b/src/html/parser.nim
index 68295dbe..3f1ca218 100644
--- a/src/html/parser.nim
+++ b/src/html/parser.nim
@@ -18,6 +18,7 @@ type
     in_style: bool
     in_noscript: bool
     in_body: bool
+    skip_lf: bool
     elementNode: Element
     textNode: Text
     commentNode: Comment
@@ -208,15 +209,6 @@ proc processDocumentAddNode(state: var HTMLParseState, newNode: Node) =
     else:
       state.elementNode = state.elementNode.ownerDocument.head
 
-  #> If the next token is a U+000A LINE FEED (LF) character token, then ignore
-  #> that token and move on to the next one. (Newlines at the start of pre
-  #> blocks are ignored as an authoring convenience.)
-  elif state.elementNode.tagType == TAG_PRE:
-    if state.elementNode.childNodes.len == 1 and
-        state.elementNode.childNodes[0].nodeType == TEXT_NODE and
-        Text(state.elementNode.childNodes[0]).data == "\n":
-      discard state.elementNode.childNodes.pop()
-
   insertNode(state.elementNode, newNode)
 
 proc processDocumentEndNode(state: var HTMLParseState) =
@@ -267,6 +259,8 @@ proc processDocumentStartElement(state: var HTMLParseState, element: Element, ta
       state.elementNode = state.elementNode.ownerDocument.head
   of TAG_BODY:
     add = false
+  of TAG_PRE:
+    state.skip_lf = true
   else: discard
 
   if not state.in_body and not (element.tagType in HeadTagTypes):
@@ -420,8 +414,10 @@ proc processDocumentPart(state: var HTMLParseState, buf: string) =
       if state.in_comment:
         state.commentNode.data &= $r
       else:
-        processDocumentText(state)
-        state.textNode.data &= $r
+        if not (state.skip_lf and r == Rune('\n')):
+          processDocumentText(state)
+          state.textNode.data &= $r
+        state.skip_lf = false
 
 proc parseHtml*(inputStream: Stream): Document =
   let document = newDocument()
diff --git a/src/io/buffer.nim b/src/io/buffer.nim
index 05581551..0f83fe99 100644
--- a/src/io/buffer.nim
+++ b/src/io/buffer.nim
@@ -204,14 +204,11 @@ proc clearBuffer*(buffer: Buffer) =
   buffer.hovertext = ""
 
 proc clearDisplay*(buffer: Buffer) =
-  var i = 0
-  while i < buffer.display.len:
-    buffer.display[i].runes.setLen(0)
-    inc i
+  buffer.prevdisplay = buffer.display
+  buffer.display = newFixedGrid(buffer.width, buffer.height)
 
 proc refreshDisplay*(buffer: Buffer) =
   var y = 0
-  buffer.prevdisplay = buffer.display
   buffer.clearDisplay()
 
   for line in buffer.lines[buffer.fromy..
@@ -231,7 +228,7 @@ proc refreshDisplay*(buffer: Buffer) =
         inc n
       buffer.display[dls + j - n].runes.add(line[i].rune)
       buffer.display[dls + j - n].formatting = line[i].formatting
-      buffer.display[dls + j - n].nodes.add(line[i].nodes)
+      buffer.display[dls + j - n].nodes = line[i].nodes
       j += line[i].rune.width()
       inc i
 
@@ -610,7 +607,8 @@ proc updateCursor(buffer: Buffer) =
     buffer.cursory = buffer.lastVisibleLine - 1
 
   if buffer.cursorx >= buffer.currentLineWidth() - 1:
-    buffer.cursorLineEnd()
+    buffer.cursorx = max(buffer.currentLineWidth() - 1, 0)
+    buffer.fromx = max(buffer.cursorx - buffer.width + 1, 0)
 
   if buffer.lines.len == 0:
     buffer.cursory = 0
@@ -620,7 +618,7 @@ proc updateCursor(buffer: Buffer) =
 #  practically means we're re-interpreting all style-sheets AND re-applying all
 #  rules way too often
 #* reshape also calls redraw so the entire window gets re-painted too which
-#  looks pretty bad
+#  looks pretty bad (tick)
 #* and finally it re-arranges all CSS boxes too, which is a rather
 #  resource-intensive operation
 #overall the second point is the easiest to solve, then the first and finally
@@ -696,7 +694,6 @@ proc renderDocument*(buffer: Buffer) =
   buffer.updateCursor()
 
 proc reshapeBuffer*(buffer: Buffer) =
-  buffer.display = newFixedGrid(buffer.width, buffer.height)
   #TODO
   #buffer.statusmsg = newFixedGrid(buffer.width)
   if buffer.showsource:
@@ -710,10 +707,7 @@ proc cursorBufferPos(buffer: Buffer) =
   termGoto(x, y)
 
 proc clearStatusMessage(buffer: Buffer) =
-  var i = 0
-  while i < buffer.statusmsg.len:
-    buffer.statusmsg[i].runes.setLen(0)
-    inc i
+  buffer.statusmsg = newFixedGrid(buffer.width)
 
 proc setStatusMessage*(buffer: Buffer, str: string) =
   buffer.clearStatusMessage()
@@ -748,6 +742,7 @@ proc displayBuffer(buffer: Buffer) =
 
 proc displayStatusMessage(buffer: Buffer) =
   termGoto(0, buffer.height)
+  print(SGR())
   print(buffer.generateStatusMessage())
   print(EL())
 
@@ -827,19 +822,25 @@ proc inputLoop(attrs: TermAttributes, buffer: Buffer): bool =
       buffer.redraw = true
     else: discard
     stdout.hideCursor()
-    buffer.updateHover()
 
     if buffer.refreshTermAttrs():
       buffer.redraw = true
       buffer.reshape = true
 
+    if buffer.redraw:
+      buffer.refreshDisplay()
+      buffer.displayBuffer()
+      buffer.redraw = false
+
+    #TODO
+    buffer.updateHover()
     if buffer.reshape:
       buffer.reshapeBuffer()
       buffer.reshape = false
       buffer.redraw = true #?
     if buffer.redraw:
       buffer.refreshDisplay()
-      buffer.displayBuffer()
+      buffer.displayBufferSwapOutput()
       buffer.redraw = false
 
     if not nostatus:
diff --git a/src/layout/box.nim b/src/layout/box.nim
index 271fbd10..bee93363 100644
--- a/src/layout/box.nim
+++ b/src/layout/box.nim
@@ -30,6 +30,7 @@ type
     marginy*: int
     conty*: bool
     whitespace*: bool
+    ws_initial*: bool
 
   InlineContext* = object
     cssvalues*: CSSComputedValues
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 52069b6f..7d279b87 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -10,6 +10,7 @@ func newContext*(box: CSSBox): Context =
   new(result)
   result.fromx = box.x
   result.whitespace = true
+  result.ws_initial = true
 
 func newBlockBox*(parent: CSSBox, vals: CSSComputedValues): CSSBlockBox =
   new(result)
@@ -17,19 +18,18 @@ func newBlockBox*(parent: CSSBox, vals: CSSComputedValues): CSSBlockBox =
   result.x = parent.x
   if parent.context.conty:
     inc parent.height
-    #eprint "inc n"
+    #eprint "CONTY N"
     inc parent.context.fromy
     parent.context.conty = false
   result.y = parent.context.fromy
   let mtop = vals[PROPERTY_MARGIN_TOP].length.cells()
   if mtop > parent.bcontext.marginy:
     result.y += mtop - parent.bcontext.marginy
-    #eprint "my", mtop, parent.bcontext.marginy
     parent.bcontext.marginy = mtop
+    #eprint "M-TOP", mtop - parent.bcontext.marginy
 
   result.width = parent.width
   result.context = newContext(parent)
-  #eprint "inc to", result.y
   result.context.fromy = result.y
   result.cssvalues = vals
 
@@ -59,7 +59,8 @@ proc inlineWrap(ibox: var CSSInlineBox, rowi: var int, fromx: var int, rowbox: v
   inc rowi
   fromx = ibox.x
   ibox.context.whitespace = true
-  ibox.context.conty = true
+  ibox.context.ws_initial = true
+  ibox.context.conty = false
   rowbox = CSSRowBox(x: ibox.x, y: ibox.y + rowi)
   rowbox.setup(ibox.cssvalues, ibox.bcontext.nodes)
 
@@ -87,25 +88,29 @@ proc processInlineBox(parent: CSSBox, str: string): CSSBox =
     if rowbox.width + r.width() > ibox.width:
       inlineWrap(ibox, rowi, fromx, rowbox)
     if r.isWhitespace():
+      let wsr = ibox.cssvalues[PROPERTY_WHITESPACE].whitespace
       if ibox.context.whitespace:
-        continue
-      else:
-        let wsr = ibox.cssvalues[PROPERTY_WHITESPACE].whitespace
-
-        case wsr
-        of WHITESPACE_NORMAL, WHITESPACE_NOWRAP:
-          r = Rune(' ')
-        of WHITESPACE_PRE, WHITESPACE_PRE_LINE, WHITESPACE_PRE_WRAP:
-          if r == Rune('\n'):
-            inlineWrap(ibox, rowi, fromx, rowbox)
-            ibox.context.whitespace = false
+        if ibox.context.ws_initial:
+          ibox.context.ws_initial = false
+          if not (wsr in {WHITESPACE_PRE, WHITESPACE_PRE_LINE, WHITESPACE_PRE_WRAP}):
             continue
-
-        case wsr
-        of WHITESPACE_NORMAL, WHITESPACE_NOWRAP, WHITESPACE_PRE_LINE:
-          ibox.context.whitespace = true
         else:
+          continue
+      case wsr
+      of WHITESPACE_NORMAL, WHITESPACE_NOWRAP:
+        r = Rune(' ')
+      of WHITESPACE_PRE, WHITESPACE_PRE_LINE, WHITESPACE_PRE_WRAP:
+        if r == Rune('\n'):
+          inlineWrap(ibox, rowi, fromx, rowbox)
           ibox.context.whitespace = false
+          ibox.context.ws_initial = true
+          continue
+        r = Rune(' ')
+      case wsr
+      of WHITESPACE_NORMAL, WHITESPACE_NOWRAP, WHITESPACE_PRE_LINE:
+        ibox.context.whitespace = true
+      else:
+        ibox.context.whitespace = false
     else:
       ibox.context.whitespace = false
     rowbox.width += r.width()
@@ -127,7 +132,7 @@ proc processInlineBox(parent: CSSBox, str: string): CSSBox =
 proc processElemBox(parent: CSSBox, elem: Element): CSSBox =
   case elem.cssvalues[PROPERTY_DISPLAY].display
   of DISPLAY_BLOCK:
-    #eprint "START", elem.tagType
+    #eprint "START", elem.tagType, parent.context.fromy
     result = newBlockBox(parent, elem.cssvalues)
     CSSBlockBox(result).tag = $elem.tagType
   of DISPLAY_INLINE:
@@ -143,18 +148,18 @@ proc add(parent: var CSSBox, box: CSSBox) =
   if box of CSSBlockBox:
     parent.context.fromx = 0
     parent.context.whitespace = true
+    parent.context.ws_initial = true
     if box.context.conty:
+      #eprint "CONTY A"
       inc box.height
-      #eprint "inc a"
       inc box.context.fromy
       box.context.conty = false
     let mbot = box.cssvalues[PROPERTY_MARGIN_BOTTOM].length.cells()
-    #eprint "inc b", mbot
     box.context.fromy += mbot
     box.bcontext.marginy = mbot
-    #eprint "END", CSSBlockBox(box).tag
+    #eprint "M-BOT", mbot
+    #eprint "END", CSSBlockBox(box).tag, box.context.fromy
   parent.height += box.height
-  #eprint "parent to", box.context.fromy
   parent.context.fromy = box.context.fromy
   parent.children.add(box)