about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-07-31 15:44:54 +0200
committerbptato <nincsnevem662@gmail.com>2022-08-01 18:21:54 +0200
commit8f7eb1f7d0ec0cac610c5dcc73188fdbe1577def (patch)
tree937f23221209b443e8827af610a4d91e943f6b0f
parentb1c8e5edc277c84962955f1edbd8237adb2f5bc8 (diff)
downloadchawan-8f7eb1f7d0ec0cac610c5dcc73188fdbe1577def.tar.gz
Make marks a property of buffer
So that re-rendering the buffer doesn't destroy all marks.
-rw-r--r--src/client.nim16
-rw-r--r--src/io/buffer.nim26
-rw-r--r--src/io/cell.nim2
3 files changed, 28 insertions, 16 deletions
diff --git a/src/client.nim b/src/client.nim
index 8cda16ec..4d7fc2f4 100644
--- a/src/client.nim
+++ b/src/client.nim
@@ -340,10 +340,9 @@ proc isearch(client: Client) =
   var iput: string
   let cpos = client.buffer.cpos
   var mark: Mark
-  var my: int
   template del_mark() =
     if mark != nil:
-      client.buffer.removeMark(my, mark)
+      client.buffer.removeMark(mark)
 
   let status = readLine("/", iput, client.buffer.width, {}, false, (proc(state: var LineState): bool =
     del_mark
@@ -353,13 +352,16 @@ proc isearch(client: Client) =
       let match = client.buffer.cursorNextMatch(regex.get)
       if match.success:
         mark = client.buffer.addMark(match.x, match.y, match.str.width())
-        my = match.y
         client.buffer.redraw = true
         client.buffer.refreshBuffer(true)
         print(HVP(client.buffer.height + 1, 2))
         print(SGR())
       else:
         del_mark
+        client.buffer.redraw = true
+        client.buffer.refreshBuffer(true)
+        print(HVP(client.buffer.height + 1, 2))
+        print(SGR())
       return true
     false
   ))
@@ -377,10 +379,9 @@ proc isearchBack(client: Client) =
   var iput: string
   let cpos = client.buffer.cpos
   var mark: Mark
-  var my: int
   template del_mark() =
     if mark != nil:
-      client.buffer.removeMark(my, mark)
+      client.buffer.removeMark(mark)
   let status = readLine("?", iput, client.buffer.width, {}, false, (proc(state: var LineState): bool =
     del_mark
     let regex = compileSearchRegex($state.news)
@@ -389,13 +390,16 @@ proc isearchBack(client: Client) =
       let match = client.buffer.cursorPrevMatch(regex.get)
       if match.success:
         mark = client.buffer.addMark(match.x, match.y, match.str.width())
-        my = match.y
         client.buffer.redraw = true
         client.buffer.refreshBuffer(true)
         print(HVP(client.buffer.height + 1, 2))
         print(SGR())
       else:
         del_mark
+        client.buffer.redraw = true
+        client.buffer.refreshBuffer(true)
+        print(HVP(client.buffer.height + 1, 2))
+        print(SGR())
       return true
     false
   ))
diff --git a/src/io/buffer.nim b/src/io/buffer.nim
index f627ba42..4f434e5d 100644
--- a/src/io/buffer.nim
+++ b/src/io/buffer.nim
@@ -1,3 +1,4 @@
+import algorithm
 import httpclient
 import options
 import os
@@ -67,6 +68,7 @@ type
     userstyle*: CSSStylesheet
     loader*: FileLoader
     markcolor*: CellColor
+    marks*: seq[Mark]
 
 proc newBuffer*(): Buffer =
   new(result)
@@ -314,11 +316,11 @@ proc clearDisplay(buffer: Buffer) =
 
 proc refreshDisplay(buffer: Buffer) =
   var r: Rune
-  var y = 0
+  var y = 0 # y position on screen
   buffer.clearDisplay()
 
-  for line in buffer.lines[buffer.fromy..
-                           buffer.lastVisibleLine - 1]:
+  for by in buffer.fromy..buffer.lastVisibleLine - 1:
+    let line = buffer.lines[by] # by: y position in lines
     var w = 0 # width of the row so far
     var i = 0 # byte in line.str
 
@@ -362,8 +364,13 @@ proc refreshDisplay(buffer: Buffer) =
 
     # Then, for each cell that has a mark, override its formatting with that
     # specified by the mark.
+    var l = 0
+    while l < buffer.marks.len and buffer.marks[l].y < by:
+      inc l # linear search to find the first applicable mark
     let aw = buffer.width - (startw - buffer.fromx) # actual width
-    for mark in line.marks:
+    while l < buffer.marks.len and buffer.marks[l].y == by:
+      let mark = buffer.marks[l]
+      inc l
       if mark.x >= startw + aw or mark.x + mark.width < startw: continue
       for i in max(mark.x, startw)..<min(mark.x + mark.width, startw + aw):
         buffer.display[dls + i].format = mark.format
@@ -706,13 +713,14 @@ proc addMark*(buffer: Buffer, x, y, width: int): Mark =
   assert y < buffer.lines.len
   var format = newFormat()
   format.bgcolor = buffer.markcolor
-  result = Mark(x: x, width: width, format: format)
-  buffer.lines[y].marks.add(result)
+  result = Mark(x: x, y: y, width: width, format: format)
+  let previ = upperBound(buffer.marks, y, (proc(a: Mark, b: int): int = cmp(a.y, b)))
+  buffer.marks.insert(result, previ)
 
-proc removeMark*(buffer: Buffer, y: int, mark: Mark) =
-  let i = buffer.lines[y].marks.find(mark)
+proc removeMark*(buffer: Buffer, mark: Mark) =
+  let i = buffer.marks.find(mark)
   if i != -1:
-    buffer.lines[y].marks.delete(i)
+    buffer.marks.delete(i)
 
 proc cursorNextMatch(buffer: Buffer, regex: Regex, sy, ey: int, wrap = false): BufferMatch =
   for y in sy..ey:
diff --git a/src/io/cell.nim b/src/io/cell.nim
index 80ada720..d8f3d23b 100644
--- a/src/io/cell.nim
+++ b/src/io/cell.nim
@@ -35,10 +35,10 @@ type
   FlexibleLine* = object
     str*: string
     formats*: seq[FormatCell]
-    marks*: seq[Mark]
 
   Mark* = ref object
     x*: int
+    y*: int
     width*: int
     format*: Format