about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-12-07 19:02:56 +0100
committerbptato <nincsnevem662@gmail.com>2022-12-07 19:02:56 +0100
commit31162225df672187e4b73423ac2f4bc25937fd3f (patch)
tree7c52d54677897b4eaa258592bfa96d3b7b303505
parenteb61a176754a565a5c53562993897388fa2d260c (diff)
downloadchawan-31162225df672187e4b73423ac2f4bc25937fd3f.tar.gz
Add multiple text-decoration, overline emulation
-rw-r--r--res/config.toml2
-rw-r--r--src/config/config.nim29
-rw-r--r--src/css/values.nim24
-rw-r--r--src/display/term.nim22
-rw-r--r--src/layout/box.nim2
-rw-r--r--src/render/renderdocument.nim9
6 files changed, 58 insertions, 30 deletions
diff --git a/res/config.toml b/res/config.toml
index 6115303b..fa641f25 100644
--- a/res/config.toml
+++ b/res/config.toml
@@ -5,6 +5,8 @@ editor = "vi %s +%d"
 [display]
 color-mode = "auto"
 format-mode = "auto"
+no-format-mode = ["overline"]
+emulate-overline = true
 alt-screen = "auto"
 highlight-color = "cyan"
 double-width-ambiguous = false
diff --git a/src/config/config.nim b/src/config/config.nim
index 941f8c54..19cf9a8a 100644
--- a/src/config/config.nim
+++ b/src/config/config.nim
@@ -37,12 +37,14 @@ type
     headless*: bool
     colormode*: Option[ColorMode]
     formatmode*: Option[FormatMode]
+    noformatmode*: FormatMode
     altscreen*: Option[bool]
     mincontrast*: float
     editor*: string
     tmpdir*: string
     siteconf: seq[StaticSiteConfig]
     forceclear*: bool
+    emulateoverline*: bool
 
   BufferConfig* = object
     userstyle*: string
@@ -170,6 +172,18 @@ proc parseConfig(config: Config, dir: string, t: TomlValue) =
         of "inline":
           config.stylesheet &= v.s
     of "display":
+      template get_format_mode(v: TomlValue): FormatMode =
+        var mode: FormatMode
+        for vv in v.a:
+          case vv.s
+          of "bold": mode.incl(FLAG_BOLD)
+          of "italic": mode.incl(FLAG_ITALIC)
+          of "underline": mode.incl(FLAG_UNDERLINE)
+          of "reverse": mode.incl(FLAG_REVERSE)
+          of "strike": mode.incl(FLAG_STRIKE)
+          of "overline": mode.incl(FLAG_OVERLINE)
+          of "blink": mode.incl(FLAG_BLINK)
+        mode
       for k, v in v:
         case k
         of "alt-screen":
@@ -188,17 +202,9 @@ proc parseConfig(config: Config, dir: string, t: TomlValue) =
           if v.vt == VALUE_STRING and v.s == "auto":
             config.formatmode = none(FormatMode)
           elif v.vt == VALUE_ARRAY:
-            var mode: FormatMode
-            for v in v.a:
-              case v.s
-              of "bold": mode.incl(FLAG_BOLD)
-              of "italic": mode.incl(FLAG_ITALIC)
-              of "underline": mode.incl(FLAG_UNDERLINE)
-              of "reverse": mode.incl(FLAG_REVERSE)
-              of "strike": mode.incl(FLAG_STRIKE)
-              of "overline": mode.incl(FLAG_OVERLINE)
-              of "blink": mode.incl(FLAG_BLINK)
-            config.formatmode = some(mode)
+            config.formatmode = some(get_format_mode v)
+        of "no-format-mode":
+          config.noformatmode = get_format_mode v
         of "highlight-color":
           config.hlcolor = parseRGBAColor(v.s).get
         of "double-width-ambiguous":
@@ -209,6 +215,7 @@ proc parseConfig(config: Config, dir: string, t: TomlValue) =
           else:
             config.mincontrast = float(v.f)
         of "force-clear": config.forceclear = v.b
+        of "emulate-overline": config.emulateoverline = v.b
     of "external":
       for k, v in v:
         case k
diff --git a/src/css/values.nim b/src/css/values.nim
index 848bd7d0..304eada5 100644
--- a/src/css/values.nim
+++ b/src/css/values.nim
@@ -121,7 +121,7 @@ type
     of VALUE_INTEGER:
       integer*: int
     of VALUE_TEXT_DECORATION:
-      textdecoration*: CSSTextDecoration
+      textdecoration*: set[CSSTextDecoration]
     of VALUE_WORD_BREAK:
       wordbreak*: CSSWordBreak
     of VALUE_LIST_STYLE_TYPE:
@@ -538,17 +538,17 @@ func cssFontWeight(d: CSSDeclaration): int =
 
   raise newException(CSSValueError, "Invalid font weight")
 
-func cssTextDecoration(d: CSSDeclaration): CSSTextDecoration =
-  if isToken(d):
-    let tok = getToken(d)
-    if tok.tokenType == CSS_IDENT_TOKEN:
-      case tok.value
-      of "none": return TEXT_DECORATION_NONE
-      of "underline": return TEXT_DECORATION_UNDERLINE
-      of "overline": return TEXT_DECORATION_OVERLINE
-      of "line-through": return TEXT_DECORATION_LINE_THROUGH
-      of "blink": return TEXT_DECORATION_BLINK
-  raise newException(CSSValueError, "Invalid text decoration")
+func cssTextDecoration(d: CSSDeclaration): set[CSSTextDecoration] =
+  for tok in d.value:
+    if tok of CSSToken:
+      let tok = CSSToken(tok)
+      if tok.tokenType == CSS_IDENT_TOKEN:
+        case tok.value
+        of "none": result.incl(TEXT_DECORATION_NONE)
+        of "underline": result.incl(TEXT_DECORATION_UNDERLINE)
+        of "overline": result.incl(TEXT_DECORATION_OVERLINE)
+        of "line-through": result.incl(TEXT_DECORATION_LINE_THROUGH)
+        of "blink": result.incl(TEXT_DECORATION_BLINK)
 
 func cssWordBreak(d: CSSDeclaration): CSSWordBreak =
   if isToken(d):
diff --git a/src/display/term.nim b/src/display/term.nim
index eb061d99..beb84a4c 100644
--- a/src/display/term.nim
+++ b/src/display/term.nim
@@ -332,10 +332,27 @@ proc hideCursor*(term: Terminal) =
 proc showCursor*(term: Terminal) =
   term.outfile.showCursor()
 
+func emulateOverline(term: Terminal): bool =
+  term.config.emulateoverline and FLAG_OVERLINE notin term.formatmode and
+  FLAG_UNDERLINE in term.formatmode
+
 proc writeGrid*(term: Terminal, grid: FixedGrid, x = 0, y = 0) =
   for ly in y ..< y + grid.height:
     for lx in x ..< x + grid.width:
-      term.canvas[ly * term.canvas.width + lx] = grid[(ly - y) * grid.width + (lx - x)]
+      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 w = grid[(ly - y) * grid.width + (lx - x)].width()
+        let s = i - term.canvas.width
+        var j = s
+        while j < term.canvas.len and j < s + w:
+          let cell = addr term.canvas[j]
+          cell.format.flags.incl(FLAG_UNDERLINE)
+          if cell.str == "":
+            cell.str = " "
+          if cell.str == " ":
+            cell.format.fgcolor = grid[(ly - y) * grid.width + (lx - x)].format.fgcolor
+          j += cell[].width()
 
 proc outputGrid*(term: Terminal) =
   term.outfile.write(term.resetFormat())
@@ -449,6 +466,9 @@ proc detectTermAttributes(term: Terminal) =
     of "24bit", "truecolor": term.colormode = TRUE_COLOR
   if term.config.formatmode.isSome:
     term.formatmode = term.config.formatmode.get
+  for fm in FormatFlags:
+    if fm in term.config.noformatmode:
+      term.formatmode.excl(fm)
   if term.config.altscreen.isSome:
     term.smcup = term.config.altscreen.get
   term.mincontrast = term.config.mincontrast
diff --git a/src/layout/box.nim b/src/layout/box.nim
index 3a8dc41c..4a0b0fcd 100644
--- a/src/layout/box.nim
+++ b/src/layout/box.nim
@@ -74,7 +74,7 @@ type
   ComputedFormat* = ref object
     fontstyle*: CSSFontStyle
     fontweight*: int
-    textdecoration*: CSSTextDecoration
+    textdecoration*: set[CSSTextDecoration]
     color*: RGBAColor
     node*: StyledNode
 
diff --git a/src/render/renderdocument.nim b/src/render/renderdocument.nim
index 0315f6b7..2a938acc 100644
--- a/src/render/renderdocument.nim
+++ b/src/render/renderdocument.nim
@@ -19,14 +19,13 @@ func formatFromWord(computed: ComputedFormat): Format =
     result.italic = true
   if computed.fontweight > 500:
     result.bold = true
-  case computed.textdecoration
-  of TEXT_DECORATION_UNDERLINE:
+  if TEXT_DECORATION_UNDERLINE in computed.textdecoration:
     result.underline = true
-  of TEXT_DECORATION_OVERLINE:
+  if TEXT_DECORATION_OVERLINE in computed.textdecoration:
     result.overline = true
-  of TEXT_DECORATION_LINE_THROUGH:
+  if TEXT_DECORATION_LINE_THROUGH in computed.textdecoration:
     result.strike = true
-  of TEXT_DECORATION_BLINK:
+  if TEXT_DECORATION_BLINK in computed.textdecoration:
     result.blink = true
   else: discard