application/octet-stream
•
5.06 KB
•
154 lines
(defclass TextBuffer
"A buffer for text editors"
:export
(defn new (self filename)
(def lines [(buffer/allocate 16)])
{ :lines lines
:lines-clean []
:filename filename
:changed #f
:pos-x 0
:pos-y 0
:scroll-x 0
:scroll-y 0
:prototype* self })
(defn get-line (self line-y)
(def lines (ref self :lines))
(if (or (< line-y 0)
(>= line-y (:length lines)))
#nil
(ref lines line-y)))
(defn line-length (self pos-y)
(def line (:get-line self pos-y))
(when-not line (return 0))
(dotimes (i (:length line) (:length line))
(when (zero? (ref line i))
(return i))))
(defn backward-delete-line (self)
(def lines (ref self :lines))
(def ll (- (:length lines) 1))
(def pos-y (ref self :pos-y))
(when (zero? pos-y) (return))
(while (< pos-y ll)
(set! lines pos-y (inc pos-y))
(inc! pos-y))
(:length! lines (max 0 ll))
(set! self :pos-y (- (ref self :pos-y) 1))
(:line-clean! self (ref self :pos-y) #f)
(set! self :pos-x (inc (:line-length self (ref self :pos-y)))))
(defn backward-char (self)
(def pos-x (ref self :pos-x))
(when (< pos-x 1)
(def pos-y (ref self :pos-y))
(when (< pos-y 1)
(return))
(set! self :pos-y (dec pos-y))
(:line-clean! self (ref self :pos-y) #f)
(set! self :pos-x (:line-length self (dec pos-y)))
(return))
(set! self :pos-x (dec pos-x)))
(defn previous-line (self)
(def pos-x (ref self :pos-x))
(def pos-y (ref self :pos-y))
(when (< pos-y 1)
(return))
(set! self :pos-y (dec pos-y))
(:line-clean! self (ref self :pos-y) #f)
(set! self :pos-x (min pos-x (:line-length self (dec pos-y)))))
(defn next-line (self)
(def pos-x (ref self :pos-x))
(def pos-y (ref self :pos-y))
(def lines (ref self :lines))
(def ll (- (:length lines) 1))
(when (>= pos-y ll)
(return))
(set! self :pos-y (inc pos-y))
(:line-clean! self (ref self :pos-y) #f)
(set! self :pos-x (min pos-x (:line-length self (inc pos-y)))))
(defn forward-char (self)
(def pos-x (ref self :pos-x))
(def pos-y (ref self :pos-y))
(def ll (:line-length self pos-y))
(when (>= pos-x ll)
(when (>= (inc pos-y) (:length (ref self :lines)))
(return))
(set! self :pos-x 0)
(set! self :pos-y (inc pos-y))
(:line-clean! self (ref self :pos-y) #f)
(return))
(set! self :pos-x (inc pos-x)))
(defn delete-forward-char (self)
(def line (:get-line self (ref self :pos-y)))
(when-not line (return))
(def pos-x (ref self :pos-x))
(def bl (- (:length line) 2))
(while (<= pos-x bl)
(set! line pos-x (ref line (inc pos-x)))
(inc! pos-x))
(set! line (- (:length line) 1) 0))
(defn backward-delete-char (self)
(def line (:get-line self (ref self :pos-y)))
(when-not line (return))
(def pos-x (ref self :pos-x))
(when (< pos-x 1)
(return (:backward-delete-line self)))
(def bl (- (:length line) 1))
(while (<= pos-x bl)
(set! line (- pos-x 1) (ref line pos-x))
(inc! pos-x))
(set! line bl 0)
(set! self :pos-x (- (ref self :pos-x) 1)))
(defn insert-char (self c)
:export
(def line (:get-line self (ref self :pos-y)))
(when-not line
; ToDo: add line?
(return))
(def pos-x (ref self :pos-x))
(def i (- (:length line) 1))
(when-not (zero? (ref line i))
(:length! line (+ (:length line) 16))
(def i (- (:length line) 1)))
(while (> i pos-x)
(set! line i (ref line (dec i)))
(dec! i))
(set! line pos-x c)
(set! self :pos-x (inc pos-x)))
(defn insert-newline (self)
:export
(def lines (ref self :lines))
(def lines-clean (ref self :lines-clean))
(:length! lines (inc (:length lines)))
(:length! lines-clean (:length lines))
(set! lines (- (:length lines) 1) (buffer/allocate 16))
(set! self :pos-x 0)
(set! self :pos-y (inc (ref self :pos-y)))
(:line-clean! self (ref self :pos-y) #f))
(defn get-buf-name (self buf)
(def filename (ref self :filename))
(def saved (if (ref self :changed) "*" ""))
(fmt "{filename}{saved}"))
(defn line-clean? (self line)
(def lines-clean (ref self :lines-clean))
(when (>= line (:length lines-clean)) (return #f))
(or (ref lines-clean line) #f))
(defn line-clean! (self line clean)
(def lines-clean (ref self :lines-clean))
(when (>= line (:length lines-clean))
(:length! lines-clean (inc line)))
(set! lines-clean line clean)))