about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-09-28 17:29:12 +0200
committerbptato <nincsnevem662@gmail.com>2024-09-28 17:54:08 +0200
commit9c257361388f5007871a36eea3abc815a8740d66 (patch)
tree3c9494ecfa6467438043402594bb2d2b7bd262eb
parent1bbad9a452390ebc09d038e25ed0307f3fdcd312 (diff)
downloadchawan-9c257361388f5007871a36eea3abc815a8740d66.tar.gz
container: fix control char display
Also, kill twidth and its friends; we haven't been using it for a
while now. (In the future, a solution with PUA chars might be worth
exploring.)
-rw-r--r--src/layout/renderdocument.nim8
-rw-r--r--src/local/container.nim35
-rw-r--r--src/local/lineedit.nim10
-rw-r--r--src/local/pager.nim2
-rw-r--r--src/local/select.nim4
-rw-r--r--src/server/buffer.nim2
-rw-r--r--src/utils/strwidth.nim21
7 files changed, 29 insertions, 53 deletions
diff --git a/src/layout/renderdocument.nim b/src/layout/renderdocument.nim
index 5c8ac4a7..7a4797ac 100644
--- a/src/layout/renderdocument.nim
+++ b/src/layout/renderdocument.nim
@@ -77,7 +77,7 @@ proc findFirstX(line: var FlexibleLine; x: int; outi: var int): int =
   while cx < x and i < line.str.len:
     let pi = i
     let u = line.str.nextUTF8(i)
-    let w = u.twidth(cx)
+    let w = u.width()
     # we must ensure x is max(cx, x), otherwise our assumption of cx <= x
     # breaks down
     if cx + w > x:
@@ -194,13 +194,13 @@ proc setTextFormat(line: var FlexibleLine; x, cx, nx: int; ostr: string;
 proc setText(line: var FlexibleLine; linestr: string; x: int; format: Format;
     node: StyledNode) =
   assert x >= 0 and linestr.len != 0
-  var targetX = x + linestr.twidth(x)
+  var targetX = x + linestr.width()
   var i = 0
   var cx = line.findFirstX(x, i) # first x of new string (before padding)
   var j = i
   var nx = x # last x of new string
   while nx < targetX and j < line.str.len:
-    nx += line.str.nextUTF8(j).twidth(nx)
+    nx += line.str.nextUTF8(j).width()
   let ostr = line.str.substr(j)
   line.setTextStr(linestr, ostr, i, x, cx, nx, targetX)
   line.setTextFormat(x, cx, nx, ostr, format, node)
@@ -210,7 +210,7 @@ proc setText(grid: var FlexibleGrid; linestr: string; x, y: int; format: Format;
   var x = x
   var i = 0
   while x < 0 and i < linestr.len:
-    x += linestr.nextUTF8(i).twidth(x)
+    x += linestr.nextUTF8(i).width()
   if x < 0:
     # highest x is outside the canvas, no need to draw
     return
diff --git a/src/local/container.nim b/src/local/container.nim
index 61db75ec..bbd90f1e 100644
--- a/src/local/container.nim
+++ b/src/local/container.nim
@@ -308,7 +308,7 @@ func findColBytes(s: string; endx: int; startx = 0; starti = 0): int =
   var i = starti
   while i < s.len and w < endx:
     let u = s.nextUTF8(i)
-    w += u.twidth(w)
+    w += u.width()
   return i
 
 func cursorBytes(container: Container; y: int; cc = container.cursorx): int =
@@ -327,7 +327,7 @@ func cursorFirstX(container: Container): int =
   let cc = container.cursorx
   while i < line.len:
     let u = line.nextUTF8(i)
-    let tw = u.twidth(w)
+    let tw = u.width()
     if w + tw > cc:
       return w
     w += tw
@@ -343,7 +343,7 @@ func cursorLastX(container: Container): int =
   let cc = container.cursorx
   while i < line.len and w <= cc:
     let u = line.nextUTF8(i)
-    w += u.twidth(w)
+    w += u.width()
   return max(w - 1, 0)
 
 # Last cell for tab, first cell for everything else (e.g. double width.)
@@ -361,7 +361,7 @@ func cursorDispX(container: Container): int =
   while i < line.len and w <= cc:
     u = line.nextUTF8(i)
     pw = w
-    w += u.twidth(w)
+    w += u.width()
   if u == uint32('\t'):
     return max(w - 1, 0)
   return pw
@@ -640,7 +640,7 @@ proc cursorLineTextStart(container: Container) {.jsfunc.} =
   for u in container.currentLine.points:
     if not container.luctx.isWhiteSpaceLU(u):
       break
-    x += u.twidth(x)
+    x += u.width()
   if x == 0:
     dec x
   container.setCursorX(x)
@@ -745,7 +745,7 @@ proc skipCat(container: Container; b, x: var int; breakFunc: BreakFunc;
     if container.luctx.breakFunc(u) != cat:
       b = pb
       break
-    x += u.twidth(x)
+    x += u.width()
 
 proc skipSpace(container: Container; b, x: var int; breakFunc: BreakFunc) =
   container.skipCat(b, x, breakFunc, bcSpace)
@@ -858,7 +858,7 @@ proc cursorWordEnd(container: Container; breakFunc: BreakFunc) =
       b = pb
     else:
       px = x
-      x += u.twidth(x)
+      x += u.width()
   container.skipSpace(b, x, breakFunc)
   # move to the last char in the current category
   let ob = b
@@ -873,7 +873,7 @@ proc cursorWordEnd(container: Container; breakFunc: BreakFunc) =
         b = pb
         break
       px = x
-      x += u.twidth(x)
+      x += u.width()
     x = px
   if b < container.currentLine.len or ob != b:
     container.setCursorX(x)
@@ -1255,7 +1255,7 @@ proc onMatch(container: Container; res: BufferMatch; refresh: bool) =
     container.setCursorXYCenter(res.x, res.y, refresh)
     if container.hlon:
       container.clearSearchHighlights()
-      let ex = res.x + res.str.twidth(res.x) - 1
+      let ex = res.x + res.str.width() - 1
       let hl = Highlight(
         t: hltSearch,
         x1: res.x,
@@ -1723,7 +1723,7 @@ proc drawLines*(container: Container; display: var FixedGrid; hlcolor: CellColor
     # Skip cells till fromx.
     while w < container.fromx and i < line.str.len:
       let u = line.str.nextUTF8(i)
-      w += u.twidth(w)
+      w += u.width()
     let dls = by * display.width # starting position of row in display
     # Fill in the gap in case we skipped more cells than fromx mandates (i.e.
     # we encountered a double-width character.)
@@ -1740,25 +1740,20 @@ proc drawLines*(container: Container; display: var FixedGrid; hlcolor: CellColor
       let pw = w
       let pi = i
       let u = line.str.nextUTF8(i)
-      let uw = u.twidth(w)
+      let uw = u.width()
       w += uw
       if w > container.fromx + display.width:
         break # die on exceeding the width limit
       if nf.pos != -1 and nf.pos <= pw:
         cf = nf
         nf = line.findNextFormat(pw)
-      if u == uint32('\t'):
-        # Needs to be replaced with spaces, otherwise bgcolor isn't displayed.
-        let tk = k + uw
-        while k < tk:
-          display[dls + k].str &= ' '
-          set_fmt display[dls + k], cf
-          inc k
+      if u <= 0xFF and char(u) in Controls:
+        display[dls + k].str &= '^' & char(u).getControlLetter()
       else:
         for j in pi ..< i:
           display[dls + k].str &= line.str[j]
-        set_fmt display[dls + k], cf
-        k += uw
+      set_fmt display[dls + k], cf
+      k += uw
     if bgcolor != defaultColor:
       # Fill the screen if bgcolor is not default.
       while k < display.width:
diff --git a/src/local/lineedit.nim b/src/local/lineedit.nim
index 2f998b84..f64c37fd 100644
--- a/src/local/lineedit.nim
+++ b/src/local/lineedit.nim
@@ -26,9 +26,9 @@ type
     promptw: int
     state*: LineEditState
     escNext*: bool
-    cursorx: int # 0 ..< news.notwidth
+    cursorx: int # 0 ..< news.width
     cursori: int # 0 ..< news.len
-    shiftx: int # 0 ..< news.notwidth
+    shiftx: int # 0 ..< news.width
     shifti: int # 0 ..< news.len
     padding: int # 0 or 1
     maxwidth: int
@@ -127,7 +127,7 @@ proc insertCharseq(edit: LineEdit; s: string) =
     return
   edit.news.insert(s, edit.cursori)
   edit.cursori += s.len
-  edit.cursorx += s.notwidth()
+  edit.cursorx += s.width()
   edit.redraw = true
 
 proc cancel(edit: LineEdit) {.jsfunc.} =
@@ -270,7 +270,7 @@ proc begin(edit: LineEdit) {.jsfunc.} =
 proc `end`(edit: LineEdit) {.jsfunc.} =
   if edit.cursori < edit.news.len:
     edit.cursori = edit.news.len
-    edit.cursorx = edit.news.notwidth()
+    edit.cursorx = edit.news.width()
     if edit.cursorx >= edit.shiftx + edit.maxwidth:
       edit.redraw = true
 
@@ -315,7 +315,7 @@ proc readLine*(prompt, current: string; termwidth: int; disallowed: set[char];
     hide: hide,
     redraw: true,
     cursori: current.len,
-    cursorx: current.notwidth(),
+    cursorx: current.width(),
     # - 1, so that the cursor always has place
     maxwidth: termwidth - promptw - 1,
     hist: hist,
diff --git a/src/local/pager.nim b/src/local/pager.nim
index 2d0b12f4..f623bf06 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -449,7 +449,7 @@ proc refreshStatusMsg*(pager: Pager) =
       " (" & $container.atPercentOf() & "%)" &
       " <" & container.getTitle()
     let hover = container.getHoverText()
-    let sl = hover.notwidth()
+    let sl = hover.width()
     var l = 0
     var i = 0
     var maxw = pager.status.grid.width - 1 # -1 for '>'
diff --git a/src/local/select.nim b/src/local/select.nim
index 70726e7c..766abd1e 100644
--- a/src/local/select.nim
+++ b/src/local/select.nim
@@ -183,7 +183,7 @@ proc drawBorders(display: var FixedGrid; sx, ex, sy, ey: int;
         display[y * display.width + x].str = " "
         inc x
       else:
-        #x = display[y * display.width + x].str.twidth(x)
+        #x = display[y * display.width + x].str.width()
         inc x
   # Draw corners.
   let tl = if upmore: VerticalBar else: CornerTopLeft
@@ -261,7 +261,7 @@ proc drawSelect*(select: Select; display: var FixedGrid) =
     while j < select.options[i].len:
       let pj = j
       let u = select.options[i].nextUTF8(j)
-      let nx = x + u.twidth(x)
+      let nx = x + u.width()
       if nx > ex:
         break
       display[dls + x].str = select.options[i].substr(pj, j - 1)
diff --git a/src/server/buffer.nim b/src/server/buffer.nim
index 8a124b2f..858a737c 100644
--- a/src/server/buffer.nim
+++ b/src/server/buffer.nim
@@ -420,7 +420,7 @@ func cursorBytes(buffer: Buffer; y, cc: int): int =
   var i = 0
   while i < line.len and w < cc:
     let u = line.nextUTF8(i)
-    w += u.twidth(w)
+    w += u.width()
   return i
 
 proc navigate(buffer: Buffer; url: URL) =
diff --git a/src/utils/strwidth.nim b/src/utils/strwidth.nim
index 4ce9aa12..df84dbad 100644
--- a/src/utils/strwidth.nim
+++ b/src/utils/strwidth.nim
@@ -27,17 +27,10 @@ func width*(u: uint32): int =
         return 2
   return 1
 
-# Width, but also works with tabs.
-# Needs the column width of the text so far.
-func twidth*(u: uint32; w: int): int =
-  if u != uint32('\t'):
-    return u.width()
-  return ((w div 8) + 1) * 8 - w
-
 func width*(s: openArray[char]): int =
   var w = 0
   for u in s.points:
-    w += u.twidth(w)
+    w += u.width()
   return w
 
 func width*(s: string; start, len: int): int =
@@ -48,21 +41,9 @@ func width*(s: string; start, len: int): int =
     m = s.len
   while i < m:
     let u = s.nextUTF8(i)
-    w += u.twidth(w)
-  return w
-
-func notwidth*(s: openArray[char]): int =
-  var w = 0
-  for u in s.points:
     w += u.width()
   return w
 
-func twidth*(s: string; w: int): int =
-  var i = w
-  for u in s.points:
-    i += u.twidth(w)
-  return i - w
-
 func padToWidth*(s: string; size: int; schar = '$'): string =
   result = newStringOfCap(s.len)
   var w = 0