about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-04-27 16:49:42 +0200
committerbptato <nincsnevem662@gmail.com>2024-04-27 16:49:42 +0200
commitdfc0b6c73f263876c10e56aee18e8ecabd1465c3 (patch)
tree854c2ecd99b7c7823ecba6f913088f7d0f3d8588
parent911c2dd13051b5c195c60264d07ff7ff6cccc664 (diff)
downloadchawan-dfc0b6c73f263876c10e56aee18e8ecabd1465c3.tar.gz
term: query sixel color register number
-rw-r--r--src/local/term.nim83
1 files changed, 51 insertions, 32 deletions
diff --git a/src/local/term.nim b/src/local/term.nim
index 98c7fd91..85347f49 100644
--- a/src/local/term.nim
+++ b/src/local/term.nim
@@ -78,6 +78,7 @@ type
     defaultForeground: RGBColor
     ibuf*: string # buffer for chars when we can't process them
     hasSixel: bool
+    sixelRegisterNum: int
 
 # control sequence introducer
 template CSI(s: varargs[string, `$`]): string =
@@ -99,6 +100,10 @@ const GEOMCELL = CSI(18, "t")
 # allow shift-key to override mouse protocol
 const XTSHIFTESCAPE = CSI(">0s")
 
+# query sixel register number
+template XTSMGRAPHICS(pi, pa, pv: untyped): string =
+  CSI("?" & $pi, $pa, $pv & "S")
+
 # device control string
 const DCSSTART = "\eP"
 
@@ -180,7 +185,7 @@ proc readChar*(term: Terminal): char =
 template SGR*(s: varargs[string, `$`]): string =
   CSI(s) & "m"
 
-#TODO a) this should be customizable b) these defaults suck
+#TODO a) this should be customizable
 const ANSIColorMap = [
   rgb(0, 0, 0),
   rgb(205, 0, 0),
@@ -674,7 +679,8 @@ proc outputSixelImage(term: Terminal; x, y, offx, offy, dispw, disph: int;
     let rgb = EightBitColor(b).toRGB()
     let rgbq = RGBColor(uint32(rgb).fastmul(100))
     # 2 is RGB
-    outs &= '#' & $b & ";2;" & $rgbq.r & ';' & $rgbq.g & ';' & $rgbq.b
+    let n = b - 15
+    outs &= '#' & $n & ";2;" & $rgbq.r & ';' & $rgbq.g & ';' & $rgbq.b
   let W = int(dispw) - offx
   var n = offy * int(bmp.width)
   let L = disph * int(bmp.width)
@@ -696,7 +702,8 @@ proc outputSixelImage(term: Terminal; x, y, offx, offy, dispw, disph: int;
     outs = ""
     for i, line in bands:
       let t = if i != bands.high: '$' else: '-'
-      outs &= '#' & $uint8(line.c) & line.data.compressSixel() & t
+      let n = uint8(line.c) - 15
+      outs &= '#' & $n & line.data.compressSixel() & t
   if outs.len > 0 and outs[^1] == '-':
     outs.setLen(outs.len - 1)
   outs &= ST
@@ -825,6 +832,7 @@ type
     heightPx: int
     width: int
     height: int
+    registers: int
 
 proc queryAttrs(term: Terminal; windowOnly: bool): QueryResult =
   const tcapRGB = 0x524742 # RGB supported?
@@ -835,6 +843,7 @@ proc queryAttrs(term: Terminal; windowOnly: bool): QueryResult =
       KITTYQUERY &
       GEOMPIXEL &
       GEOMCELL &
+      XTSMGRAPHICS(1, 1, 0) & # color registers
       XTGETTCAP("524742") &
       DA1
     term.outfile.write(outs)
@@ -858,47 +867,56 @@ proc queryAttrs(term: Terminal; windowOnly: bool): QueryResult =
     template skip_until(term: Terminal; c: char) =
       while (let cc = term.consume; cc != c):
         discard
+    template consume_int_till(term: Terminal; sentinel: char): int =
+      var n = 0
+      while (let c = term.consume; c != sentinel):
+        if (let x = decValue(c); x != -1):
+          n *= 10
+          n += x
+        else:
+          fail
+      n
+    template consume_int_greedy(term: Terminal; lastc: var char): int =
+      var n = 0
+      while true:
+        let c = term.consume
+        if (let x = decValue(c); x != -1):
+          n *= 10
+          n += x
+        else:
+          lastc = c
+          break
+      n
     term.expect '\e'
     case term.consume
     of '[':
       # CSI
       case (let c = term.consume; c)
-      of '?': # DA1
-        var n = 0
+      of '?': # DA1, XTSMGRAPHICS
+        var lastc: char
+        var params = newSeq[int]()
         while true:
-          let c = term.consume
-          let x = decValue(c)
-          if x == -1:
+          let n = term.consume_int_greedy lastc
+          params.add(n)
+          if lastc in {'c', 'S'}:
+            break
+          if lastc != ';':
+            fail
+        if lastc == 'c':
+          for n in params:
             case n
             of 4: result.attrs.incl(qaSixel)
             of 22: result.attrs.incl(qaAnsiColor)
             else: discard
-            n = 0
-            if c == 'c':
-              break
-            if c != ';':
-              fail
-          else:
-            n *= 10
-            n += x
-        result.success = true
-        break # DA1 returned; done
+          result.success = true
+          break # DA1 returned; done
+        else: # 'S'
+          if params.len >= 3 and params[0] == 1 and params[1] == 0:
+            result.registers = params[2]
       of '4', '8': # GEOMPIXEL, GEOMCELL
         term.expect ';'
-        var height = 0
-        var width = 0
-        while (let c = term.consume; c != ';'):
-          if (let x = decValue(c); x != -1):
-            height *= 10
-            height += x
-          else:
-            fail
-        while (let c = term.consume; c != 't'):
-          if (let x = decValue(c); x != -1):
-            width *= 10
-            width += x
-          else:
-            fail
+        let height = term.consume_int_till ';'
+        let width = term.consume_int_till 't'
         if c == '4': # GEOMSIZE
           result.widthPx = width
           result.heightPx = height
@@ -1010,6 +1028,7 @@ proc detectTermAttributes(term: Terminal; windowOnly: bool): TermStartResult =
         term.colorMode = cmTrueColor
       if qaSixel in r.attrs:
         term.imageMode = imSixel
+        term.sixelRegisterNum = clamp(r.registers, 16, 1024)
       if qaKittyImage in r.attrs:
         term.imageMode = imKitty
       # just assume the terminal doesn't choke on these.