about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--README.md13
-rw-r--r--doc/config.md12
-rw-r--r--res/config.toml2
-rw-r--r--src/config/config.nim11
-rw-r--r--src/display/term.nim77
-rw-r--r--todo6
6 files changed, 82 insertions, 39 deletions
diff --git a/README.md b/README.md
index 130fa10b..0b2b6a01 100644
--- a/README.md
+++ b/README.md
@@ -66,6 +66,19 @@ want to try more established ones:
 
 ## FAQ
 
+### Why does Chawan use strange/incorrect/ugly colors?
+
+Chawan assumes the terminal's default background/foreground colors are
+black and white. If this is not true for your terminal, make sure to set
+the display.default-background-color and display.default-foreground-color
+properties in your Chawan configuration file.
+
+Also, by default, Chawan uses the eight ANSI colors to display colored
+text. To use true colors, either export COLORTERM=truecolor or set the
+display.color-mode to "24bit". To use 256 colors, set display.color-mode to
+"8bit" instead. (You can also turn off colors and/or styling altogether in
+the configuration; please consult [doc/config.md](doc/config.md) for details.)
+
 ### Why write another web browser?
 
 I've found other text-based web browsers insufficient for my needs, so
diff --git a/doc/config.md b/doc/config.md
index ca62dd88..fabe9820 100644
--- a/doc/config.md
+++ b/doc/config.md
@@ -282,6 +282,18 @@ black background, etc).</td>
 <td>Set the terminal emulator's window title to that of the current page.</td>
 </tr>
 
+<tr>
+<td>default-background-color</td>
+<td>color</td>
+<td>Sets the assumed background color of the terminal.</td>
+</tr>
+
+<tr>
+<td>default-foreground-color</td>
+<td>color</td>
+<td>Sets the assumed foreground color of the terminal.</td>
+</tr>
+
 </table>
 
 ## Omnirule
diff --git a/res/config.toml b/res/config.toml
index 4e319652..c12c10ff 100644
--- a/res/config.toml
+++ b/res/config.toml
@@ -30,6 +30,8 @@ double-width-ambiguous = false
 minimum-contrast = 100
 force-clear = false
 set-title = true
+default-background-color = "#000000"
+default-foreground-color = "#FFFFFF"
 
 [[omnirule]]
 match = '^ddg:'
diff --git a/src/config/config.nim b/src/config/config.nim
index dfcb63c4..f379cb3b 100644
--- a/src/config/config.nim
+++ b/src/config/config.nim
@@ -96,6 +96,8 @@ type
     minimum_contrast*: int32
     force_clear*: bool
     set_title*: bool
+    default_background_color*: RGBColor
+    default_foreground_color*: RGBColor
 
   #TODO: add JS wrappers for objects
   Config* = ref ConfigObj
@@ -321,6 +323,7 @@ proc parseConfigValue(x: var Opt[ColorMode], v: TomlValue, k: string)
 proc parseConfigValue(x: var Opt[FormatMode], v: TomlValue, k: string)
 proc parseConfigValue(x: var FormatMode, v: TomlValue, k: string)
 proc parseConfigValue(x: var RGBAColor, v: TomlValue, k: string)
+proc parseConfigValue(x: var RGBColor, v: TomlValue, k: string)
 proc parseConfigValue[T](x: var Opt[T], v: TomlValue, k: string)
 proc parseConfigValue(x: var ActionMap, v: TomlValue, k: string)
 proc parseConfigValue(x: var CSSConfig, v: TomlValue, k: string)
@@ -429,6 +432,14 @@ proc parseConfigValue(x: var RGBAColor, v: TomlValue, k: string) =
         "' for key " & k)
   x = c.get
 
+proc parseConfigValue(x: var RGBColor, v: TomlValue, k: string) =
+  typeCheck(v, VALUE_STRING, k)
+  let c = parseLegacyColor(v.s)
+  if c.isNone:
+      raise newException(ValueError, "invalid color '" & v.s &
+        "' for key " & k)
+  x = c.get
+
 proc parseConfigValue[T](x: var Opt[T], v: TomlValue, k: string) =
   if v.vt == VALUE_STRING and v.s == "auto":
     x.err()
diff --git a/src/display/term.nim b/src/display/term.nim
index 0aa7daa9..a2112ee5 100644
--- a/src/display/term.nim
+++ b/src/display/term.nim
@@ -51,7 +51,6 @@ type
     canvas*: FixedGrid
     pcanvas: FixedGrid
     attrs*: WindowAttributes
-    mincontrast: int
     colormode: ColorMode
     formatmode: FormatMode
     smcup: bool
@@ -201,26 +200,33 @@ proc disableAltScreen(term: Terminal): string =
   else:
     return RMCUP()
 
+func defaultBackground(term: Terminal): RGBColor =
+  return term.config.display.default_background_color
+
+func defaultForeground(term: Terminal): RGBColor =
+  return term.config.display.default_foreground_color
+
+func mincontrast(term: Terminal): int32 =
+  return term.config.display.minimum_contrast
+
 proc getRGB(a: CellColor, bg: bool): RGBColor =
   if a.rgb:
     return a.rgbcolor
-  elif a == defaultColor:
-    if bg:
-      return ColorsRGB["black"]
-    else:
-      return ColorsRGB["white"]
   elif a.color >= 16:
     return eightBitToRGB(EightBitColor(a.color))
-  return ANSIColorMap[a.color mod 10]
+  return ANSIColorMap[a.color]
 
 # Use euclidian distance to quantize RGB colors.
-proc approximateANSIColor(rgb: RGBColor): ANSIColor =
+proc approximateANSIColor(rgb, termDefault: RGBColor): CellColor =
   var a = 0i32
   var n = -1
-  for i in 0 .. ANSIColorMap.high:
-    let color = ANSIColorMap[i]
+  for i in -1 .. ANSIColorMap.high:
+    let color = if i > 0:
+      ANSIColorMap[i]
+    else:
+      termDefault
     if color == rgb:
-      return ANSIColor(i)
+      return if i == -1: defaultColor else: cellColor(ANSIColor(i))
     let x = int32(color.r) - int32(rgb.r)
     let y = int32(color.g) - int32(rgb.g)
     let z = int32(color.b) - int32(rgb.b)
@@ -231,14 +237,20 @@ proc approximateANSIColor(rgb: RGBColor): ANSIColor =
     if n == -1 or b < a:
       n = i
       a = b
-  return ANSIColor(n)
+  return if n == -1: defaultColor else: cellColor(ANSIColor(n))
 
-# Return a fgcolor contrasted to the background by contrast.
-proc correctContrast(bgcolor, fgcolor: CellColor, contrast: int,
-    colormode: ColorMode): CellColor =
+# Return a fgcolor contrasted to the background by term.mincontrast.
+proc correctContrast(term: Terminal, bgcolor, fgcolor: CellColor): CellColor =
+  let contrast = term.mincontrast
   let cfgcolor = fgcolor
-  let bgcolor = getRGB(bgcolor, true)
-  let fgcolor = getRGB(fgcolor, false)
+  let bgcolor = if bgcolor == defaultColor:
+    term.defaultBackground
+  else:
+    getRGB(bgcolor, true)
+  let fgcolor = if fgcolor == defaultColor:
+    term.defaultForeground
+  else:
+    getRGB(fgcolor, false)
   let bgY = int(bgcolor.Y)
   var fgY = int(fgcolor.Y)
   let diff = abs(bgY - fgY)
@@ -256,11 +268,11 @@ proc correctContrast(bgcolor, fgcolor: CellColor, contrast: int,
         if fgY < 0:
           fgY = 255
     let newrgb = YUV(cast[uint8](fgY), fgcolor.U, fgcolor.V)
-    case colormode
+    case term.colormode
     of TRUECOLOR:
       return cellColor(newrgb)
     of ANSI:
-      return cellColor(approximateANSIColor(newrgb))
+      return approximateANSIColor(newrgb, term.defaultForeground)
     of EIGHT_BIT:
       return cellColor(rgbToEightBit(newrgb))
     of MONOCHROME:
@@ -283,25 +295,16 @@ proc processFormat*(term: Terminal, format: var Format, cellf: Format): string =
       let color = cellf.fgcolor.eightbit
       cellf.fgcolor = cellColor(eightBitToRGB(color))
     if cellf.bgcolor.rgb:
-      let color = approximateANSIColor(cellf.bgcolor.rgbcolor)
-      if color == ANSI_BLACK:
-        cellf.bgcolor = defaultColor
-      else:
-        cellf.bgcolor = cellColor(color)
+      cellf.bgcolor = approximateANSIColor(cellf.bgcolor.rgbcolor,
+        term.defaultBackground)
     if cellf.fgcolor.rgb:
       if cellf.bgcolor == defaultColor:
-        var color = approximateANSIColor(cellf.fgcolor.rgbcolor)
-        if color == ANSI_BLACK:
-          color = ANSI_WHITE
-        if color == ANSI_WHITE:
-          cellf.fgcolor = defaultColor
-        else:
-          cellf.fgcolor = cellColor(color)
+        cellf.fgcolor = approximateANSIColor(cellf.fgcolor.rgbcolor,
+          term.defaultForeground)
       else:
-        cellf.fgcolor = if cellf.bgcolor.color < 4:
-          defaultColor
-        else:
-          cellColor(ANSI_WHITE) # white
+        # ANSI non-default fgcolor AND bgcolor at the same time is assumed
+        # to be broken.
+        cellf.fgcolor = defaultColor
   of EIGHT_BIT:
     if cellf.bgcolor.rgb:
       cellf.bgcolor = cellColor(rgbToEightBit(cellf.bgcolor.rgbcolor))
@@ -313,8 +316,7 @@ proc processFormat*(term: Terminal, format: var Format, cellf: Format): string =
   of TRUE_COLOR: discard
 
   if term.colormode != MONOCHROME:
-    cellf.fgcolor = correctContrast(cellf.bgcolor, cellf.fgcolor,
-      term.mincontrast, term.colormode)
+    cellf.fgcolor = term.correctContrast(cellf.bgcolor, cellf.fgcolor)
   if cellf.fgcolor != format.fgcolor and cellf.fgcolor == defaultColor or
       cellf.bgcolor != format.bgcolor and cellf.bgcolor == defaultColor:
     result &= term.resetFormat()
@@ -520,7 +522,6 @@ proc applyConfig(term: Terminal) =
     if term.config.display.alt_screen.isSome:
       term.smcup = term.config.display.alt_screen.get
     term.set_title = term.config.display.set_title
-  term.mincontrast = term.config.display.minimum_contrast
   if term.config.encoding.display_charset.isSome:
     term.cs = term.config.encoding.display_charset.get
   else:
diff --git a/todo b/todo
index c4e6e260..79e5fb2e 100644
--- a/todo
+++ b/todo
@@ -14,8 +14,12 @@ display:
 - important: buffer list
 	* either a buffer list buffer, or a buffer list popup menu. ideally
 	  both.
-- configurable default background color
 - dark mode (basically max Y)
+- do not assume default background color
+	* instead, add an "override-default-color" option that is set to
+	  true by default and replaces default bgcolor/fgcolor with
+	  default-background/foreground-color
+- allow overriding ansi colors
 config:
 - important: config editor
 - working js interface