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/parser.nim4
-rw-r--r--src/css/values.nim10
-rw-r--r--src/html/parser.nim24
-rw-r--r--src/layout/engine.nim130
-rw-r--r--src/utils/twtstr.nim23
5 files changed, 90 insertions, 101 deletions
diff --git a/src/css/parser.nim b/src/css/parser.nim
index 2fdefef2..b594abc3 100644
--- a/src/css/parser.nim
+++ b/src/css/parser.nim
@@ -286,7 +286,7 @@ proc consumeURL(state: var CSSTokenizerState): CSSToken =
 
 proc consumeIdentLikeToken(state: var CSSTokenizerState): CSSToken =
   let s = state.consumeName()
-  if s.toAsciiLower() == "url" and state.has() and state.curr() == Rune('('):
+  if s.equalsIgnoreCase("url") and state.has() and state.curr() == Rune('('):
     discard state.consume()
     while state.has(1) and state.curr().isWhitespace() and state.peek(1).isWhitespace():
       discard state.consume()
@@ -516,7 +516,7 @@ proc consumeDeclaration(state: var CSSParseState): Option[CSSDeclaration] =
     if decl.value[i] != CSS_WHITESPACE_TOKEN:
       dec j
       if decl.value[i] == CSS_IDENT_TOKEN and k == 0:
-        if CSSToken(decl.value[i]).value.toAsciiLower() == "important":
+        if CSSToken(decl.value[i]).value.equalsIgnoreCase("important"):
           inc k
           l = i
       elif k == 1 and decl.value[i] == CSS_DELIM_TOKEN:
diff --git a/src/css/values.nim b/src/css/values.nim
index 8a66b863..df80e60d 100644
--- a/src/css/values.nim
+++ b/src/css/values.nim
@@ -529,15 +529,15 @@ func cssDisplay(d: CSSDeclaration): CSSDisplay =
       of "block": return DISPLAY_BLOCK
       of "inline": return DISPLAY_INLINE
       of "list-item": return DISPLAY_LIST_ITEM
-      # of "inline-block": return DISPLAY_INLINE_BLOCK
-      # of "table": return DISPLAY_TABLE
+      of "table": return DISPLAY_TABLE
+      of "inline-block": return DISPLAY_INLINE_BLOCK
+      of "table-row": return DISPLAY_TABLE_ROW
+      of "table-cell": return DISPLAY_TABLE_CELL
+      # of "table-column": return DISPLAY_TABLE_COLUMN
       # of "table-row-group": return DISPLAY_TABLE_ROW_GROUP
       # of "table-header-group": return DISPLAY_TABLE_HEADER_GROUP
       # of "table-footer-group": return DISPLAY_TABLE_FOOTER_GROUP
       # of "table-column-group": return DISPLAY_TABLE_COLUMN_GROUP
-      # of "table-row": return DISPLAY_TABLE_ROW
-      # of "table-column": return DISPLAY_TABLE_COLUMN
-      # of "table-cell": return DISPLAY_TABLE_CELL
       of "none": return DISPLAY_NONE
       else: return DISPLAY_INLINE
   raise newException(CSSValueError, "Invalid display")
diff --git a/src/html/parser.nim b/src/html/parser.nim
index 0e0fbaa0..74ec68b7 100644
--- a/src/html/parser.nim
+++ b/src/html/parser.nim
@@ -127,11 +127,15 @@ proc parse_tag(buf: string, at: var int): DOMParsedTag =
     var value = ""
     var attrname = ""
     while at < buf.len and buf[at] != '=' and not buf[at].isWhitespace() and buf[at] != '>':
-      attrname &= buf[at].tolower()
-      at += buf.runeLenAt(at)
+      var r: Rune
+      fastRuneAt(buf, at, r)
+      if r.isAscii():
+        attrname &= char(r).tolower()
+      else:
+        attrname &= r
 
     at = skipBlanks(buf, at)
-    if buf[at] == '=':
+    if at < buf.len and buf[at] == '=':
       inc at
       at = skipBlanks(buf, at)
       if at < buf.len and (buf[at] == '"' or buf[at] == '\''):
@@ -142,9 +146,8 @@ proc parse_tag(buf: string, at: var int): DOMParsedTag =
             inc at
             value &= getescapecmd(buf, at)
           else:
-            var r: Rune
-            fastRuneAt(buf, at, r)
-            value &= r
+            value &= buf[at]
+            inc at
         if at < buf.len:
           inc at
       elif at < buf.len:
@@ -416,15 +419,14 @@ proc processDocumentPart(state: var HTMLParseState, buf: string) =
         state.commentNode.data &= buf[at]
         inc at
     else:
-      var r: Rune
-      fastRuneAt(buf, at, r)
       if state.in_comment:
-        state.commentNode.data &= $r
+        state.commentNode.data &= buf[at]
       else:
-        if not (state.skip_lf and r == Rune('\n')):
+        if not (state.skip_lf and buf[at] == '\n'):
           processDocumentText(state)
-          state.textNode.data &= $r
+          state.textNode.data &= buf[at]
         state.skip_lf = false
+      inc at
 
 proc parseHtml*(inputStream: Stream): Document =
   let document = newDocument()
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 523b7bff..b2dfe8dd 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -301,23 +301,22 @@ proc add(state: var LayoutState, parent: CSSBox, box: CSSBox) =
 
   parent.children.add(box)
 
-func isBlock(node: Node): bool =
-  if node.nodeType != ELEMENT_NODE:
-    return false
-  let elem = Element(node)
-  return elem.cssvalues[PROPERTY_DISPLAY].display == DISPLAY_BLOCK or
-          elem.cssvalues[PROPERTY_DISPLAY].display == DISPLAY_LIST_ITEM
-
 proc processComputedValueBox(state: var LayoutState, parent: CSSBox, values: CSSComputedValues): CSSBox =
   case values[PROPERTY_DISPLAY].display
   of DISPLAY_BLOCK:
-    #eprint "START", elem.tagType, parent.icontext.fromy
     result = state.newBlockBox(parent, values)
-    #CSSBlockBox(result).tag = $elem.tagType
+  of DISPLAY_INLINE_BLOCK:
+    result = state.newInlineBox(parent, values)
   of DISPLAY_INLINE:
     result = state.newInlineBox(parent, values)
   of DISPLAY_LIST_ITEM:
     result = state.newBlockBox(parent, values)
+  of DISPLAY_TABLE:
+    result = state.newBlockBox(parent, values)
+  of DISPLAY_TABLE_ROW:
+    result = state.newBlockBox(parent, values)
+  of DISPLAY_TABLE_CELL:
+    result = state.newInlineBox(parent, values)
   of DISPLAY_NONE:
     return nil
   else:
@@ -343,16 +342,17 @@ proc processElemBox(state: var LayoutState, parent: CSSBox, elem: Element): CSSB
   if result != nil:
     result.node = elem
 
-proc processNodes(state: var LayoutState, parent: CSSBox, node: Node)
+proc processElemChildren(state: var LayoutState, parent: CSSBox, elem: Element)
 
 proc processNode(state: var LayoutState, parent: CSSBox, node: Node): CSSBox =
   case node.nodeType
   of ELEMENT_NODE:
+    let elem = Element(node)
     result = state.processElemBox(parent, Element(node))
     if result == nil:
       return
 
-    state.processNodes(result, node)
+    state.processElemChildren(result, elem)
   of TEXT_NODE:
     let text = Text(node)
     result = state.processInlineBox(parent, text.data)
@@ -360,75 +360,59 @@ proc processNode(state: var LayoutState, parent: CSSBox, node: Node): CSSBox =
       result.node = node
   else: discard
 
-# ugh this is ugly, but it works...
-# basically this
-# * checks if there's a ::before pseudo element
-# * checks if we need to wrap things in anonymous block boxes
-# * in case we do, it adds the text to the anonymous box
-# * in case we don't, it tries to add the text to a new parent box
-# * but only if a new parent box is needed.
-proc processBeforePseudoElem(state: var LayoutState, parent: CSSBox, node: Node) =
-  if node.nodeType == ELEMENT_NODE:
-    let elem = Element(node)
-
-    if elem.cssvalues_before != nil:
-      var box: CSSBox
-      box = state.processComputedValueBox(parent, elem.cssvalues_before)
-      if box != nil:
-        box.node = node
+proc processBeforePseudoElem(state: var LayoutState, parent: CSSBox, elem: Element) =
+  if elem.cssvalues_before != nil:
+    var box: CSSBox
+    box = state.processComputedValueBox(parent, elem.cssvalues_before)
+    if box != nil:
+      box.node = elem
 
-      let text = elem.cssvalues_before[PROPERTY_CONTENT].content
-      var inline = state.processInlineBox(box, $text)
-      if inline != nil:
-        inline.node = node
-        state.add(box, inline)
+    let text = elem.cssvalues_before[PROPERTY_CONTENT].content
+    var inline = state.processInlineBox(box, $text)
+    if inline != nil:
+      inline.node = elem
+      state.add(box, inline)
 
-      state.add(parent, box)
-
-# same as before except it's after
-proc processAfterPseudoElem(state: var LayoutState, parent: CSSBox, node: Node) =
-  if node.nodeType == ELEMENT_NODE:
-    let elem = Element(node)
-
-    if elem.cssvalues_after != nil:
-      let box = state.processComputedValueBox(parent, elem.cssvalues_after)
-      if box != nil:
-        box.node = node
-
-      let text = elem.cssvalues_after[PROPERTY_CONTENT].content
-      var inline = state.processInlineBox(box, $text)
-      if inline != nil:
-        inline.node = node
-        state.add(box, inline)
-
-      state.add(parent, box)
-
-proc processMarker(state: var LayoutState, parent: CSSBox, node: Node) =
-  if node.nodeType == ELEMENT_NODE:
-    let elem = Element(node)
-    if elem.cssvalues[PROPERTY_DISPLAY].display == DISPLAY_LIST_ITEM:
-      var ordinalvalue = 1
-      if elem.tagType == TAG_LI:
-        ordinalvalue = HTMLLIElement(elem).ordinalvalue
-
-      let text = elem.cssvalues[PROPERTY_LIST_STYLE_TYPE].liststyletype.listMarker(ordinalvalue)
-      let tlen = text.width()
-      parent.icontext.fromx -= tlen
-      let marker = state.processInlineBox(parent, text)
-      state.add(parent, marker)
+    state.add(parent, box)
 
-proc processNodes(state: var LayoutState, parent: CSSBox, node: Node) =
-  state.nodes.add(node)
+proc processAfterPseudoElem(state: var LayoutState, parent: CSSBox, elem: Element) =
+  if elem.cssvalues_after != nil:
+    let box = state.processComputedValueBox(parent, elem.cssvalues_after)
+    if box != nil:
+      box.node = elem
 
-  state.processBeforePseudoElem(parent, node)
+    let text = elem.cssvalues_after[PROPERTY_CONTENT].content
+    var inline = state.processInlineBox(box, $text)
+    if inline != nil:
+      inline.node = elem
+      state.add(box, inline)
 
-  state.processMarker(parent, node)
+    state.add(parent, box)
 
-  for c in node.childNodes:
-    let box = state.processNode(parent, c)
+proc processMarker(state: var LayoutState, parent: CSSBox, elem: Element) =
+  if elem.cssvalues[PROPERTY_DISPLAY].display == DISPLAY_LIST_ITEM:
+    var ordinalvalue = 1
+    if elem.tagType == TAG_LI:
+      ordinalvalue = HTMLLIElement(elem).ordinalvalue
+
+    let text = elem.cssvalues[PROPERTY_LIST_STYLE_TYPE].liststyletype.listMarker(ordinalvalue)
+    let tlen = text.width()
+    parent.icontext.fromx -= tlen
+    let marker = state.processInlineBox(parent, text)
+    state.add(parent, marker)
+
+proc processNodes(state: var LayoutState, parent: CSSBox, nodes: seq[Node]) =
+  for node in nodes:
+    let box = state.processNode(parent, node)
     state.add(parent, box)
 
-  state.processAfterPseudoElem(parent, node)
+proc processElemChildren(state: var LayoutState, parent: CSSBox, elem: Element) =
+  state.nodes.add(elem)
+
+  state.processBeforePseudoElem(parent, elem)
+  state.processMarker(parent, elem)
+  state.processNodes(parent, elem.childNodes)
+  state.processAfterPseudoElem(parent, elem)
 
   discard state.nodes.pop()
 
@@ -441,5 +425,5 @@ proc alignBoxes*(document: Document, term: TermAttributes): CSSBox =
   rootbox.bcontext = newBlockContext()
   rootbox.bcontext.width = term.width
   state.nodes.add(document.root)
-  state.processNodes(rootbox, document.root)
+  state.processElemChildren(rootbox, document.root)
   return rootbox
diff --git a/src/utils/twtstr.nim b/src/utils/twtstr.nim
index f20b0bbe..ef81edc4 100644
--- a/src/utils/twtstr.nim
+++ b/src/utils/twtstr.nim
@@ -139,31 +139,34 @@ func decValue*(c: char): int =
   return decCharMap[int(c)]
 
 func isAscii*(r: Rune): bool =
-  return int(r) <= int(high(char))
+  return int(r) < 128
 
 func hexValue*(r: Rune): int =
-  if isAscii(r):
+  if int(r) < 256:
     return hexValue(char(r))
   return -1
 
 func decValue*(r: Rune): int =
-  if isAscii(r):
+  if int(r) < 256:
     return decValue(char(r))
   return -1
 
-func toAsciiLower*(s: seq[Rune]): string =
-  for r in s:
-    if isAscii(r):
-      result &= lowerChars[int(r)]
+func equalsIgnoreCase*(s1: seq[Rune], s2: string): bool =
+  var i = 0
+  while i < min(s1.len, s2.len):
+    if not s1[i].isAscii() or cast[char](s1[i]).tolower() != s2[i]:
+      return false
+    inc i
+  return true
 
 func breaksWord*(r: Rune): bool =
   return r in breakWord
 
 func isAlphaAscii*(r: Rune): bool =
-  return isAscii(r) and isAlphaAscii(char(r))
+  return int(r) < 256 and isAlphaAscii(char(r))
 
 func isDigitAscii*(r: Rune): bool =
-  return isAscii(r) and isDigit(char(r))
+  return int(r) < 256 and isDigit(char(r))
 
 func substr*(s: seq[Rune], i: int, j: int): seq[Rune] =
   if s.len == 0:
@@ -214,7 +217,7 @@ func japaneseNumber*(i: int): string =
     return "〇"
   var n = i
   if i < 0:
-    result &= "ス"
+    result &= "マイナス"
     n *= -1
 
   let o = n