mirror of
https://github.com/bloeys/nterm.git
synced 2025-12-29 06:28:20 +00:00
Alhamdullah working scrolling that respects wrapped text
This commit is contained in:
154
main.go
154
main.go
@ -105,7 +105,7 @@ const (
|
|||||||
hinting = font.HintingNone
|
hinting = font.HintingNone
|
||||||
|
|
||||||
defaultCmdBufSize = 4 * 1024
|
defaultCmdBufSize = 4 * 1024
|
||||||
defaultParaBufSize = 10 * 1024
|
defaultParaBufSize = 5 * 1024 * 1024
|
||||||
defaultTextBufSize = 4 * 1024 * 1024
|
defaultTextBufSize = 4 * 1024 * 1024
|
||||||
|
|
||||||
defaultScrollSpd = 1
|
defaultScrollSpd = 1
|
||||||
@ -636,8 +636,8 @@ func (p *program) WritePara(para *Para) {
|
|||||||
p.Paras.Write(*para)
|
p.Paras.Write(*para)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsParaValid(textBuf *ring.Buffer[byte], l *Para) bool {
|
func IsParaValid(textBuf *ring.Buffer[byte], p *Para) bool {
|
||||||
isValid := textBuf.WrittenElements-l.StartIndex_WriteCount < uint64(textBuf.Cap)
|
isValid := textBuf.WrittenElements-p.StartIndex_WriteCount < uint64(textBuf.Cap)
|
||||||
return isValid
|
return isValid
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -943,11 +943,17 @@ func FindNLinesIndexIterator(it ring.Iterator[byte], paraIt ring.Iterator[Para],
|
|||||||
bytesSeen += int64(size)
|
bytesSeen += int64(size)
|
||||||
|
|
||||||
// If this is true we covered one line
|
// If this is true we covered one line
|
||||||
if charsSeenThisLine == charsPerLine || r == '\n' {
|
if charsSeenThisLine > charsPerLine || r == '\n' {
|
||||||
|
|
||||||
charsSeenThisLine = 0
|
|
||||||
newIndex = startIndex + bytesSeen
|
newIndex = startIndex + bytesSeen
|
||||||
|
|
||||||
|
// Don't stop at newlines, but the char right after
|
||||||
|
if charsSeenThisLine > charsPerLine {
|
||||||
|
charsSeenThisLine = 0
|
||||||
|
} else {
|
||||||
|
charsSeenThisLine = 0
|
||||||
|
}
|
||||||
|
|
||||||
n--
|
n--
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
break
|
break
|
||||||
@ -957,29 +963,22 @@ func FindNLinesIndexIterator(it ring.Iterator[byte], paraIt ring.Iterator[Para],
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
extraIt := it.Buf.Iterator()
|
// If on the empty line between paragraphs we want to know where the last char of the previous
|
||||||
|
// para is so we can take into account position differences with wrapping
|
||||||
if it.Buf.Get(uint64(startIndex)) == '\n' && it.Buf.Get(uint64(startIndex-1)) == '\n' {
|
if it.Buf.Get(uint64(startIndex)) == '\n' && it.Buf.Get(uint64(startIndex-1)) == '\n' {
|
||||||
|
|
||||||
charsIntoLine := getWrappedLineLen(extraIt, paraIt, startIndex-1, charsPerLine)
|
charsIntoLine := getCharGridPosX(it.Buf.Iterator(), paraIt, startIndex-2, charsPerLine)
|
||||||
if charsIntoLine > 0 {
|
if charsIntoLine > 0 {
|
||||||
n++
|
charsSeenThisLine = charsPerLine - charsIntoLine
|
||||||
it.Prev()
|
|
||||||
it.Prev()
|
|
||||||
bytesSeen += 2
|
|
||||||
charsSeenThisLine = charsPerLine - int64(charsIntoLine)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
charsIntoLine := getWrappedLineLen(extraIt, paraIt, startIndex, charsPerLine)
|
|
||||||
if charsIntoLine > 0 {
|
|
||||||
charsSeenThisLine = charsPerLine - int64(charsIntoLine) - 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip the extra new line so the decoder starts with normal characters instead of seeing a newline
|
||||||
|
// and immediately quitting
|
||||||
|
it.Prev()
|
||||||
|
} else if it.Buf.Get(uint64(startIndex-1)) == '\n' {
|
||||||
|
it.Prev()
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Todo this has wrong behavior when dealing with wrapped lines because we don't know what X position to be in
|
|
||||||
// after going up a line. Are we in the middle of the line? The only way to know is to draw from the start of this paragraph
|
|
||||||
// till the start index, which will allows us to get accurate information on wrapping.
|
|
||||||
//
|
|
||||||
// But this is bad if the paragraph is too big, so we should break paragraphs after a certain size
|
|
||||||
for !done || bytesToKeep > 0 {
|
for !done || bytesToKeep > 0 {
|
||||||
|
|
||||||
read, done = it.PrevN(buf[bytesToKeep:], 4)
|
read, done = it.PrevN(buf[bytesToKeep:], 4)
|
||||||
@ -992,30 +991,16 @@ func FindNLinesIndexIterator(it ring.Iterator[byte], paraIt ring.Iterator[Para],
|
|||||||
bytesSeen += int64(size)
|
bytesSeen += int64(size)
|
||||||
|
|
||||||
// If this is true we covered one line
|
// If this is true we covered one line
|
||||||
if charsSeenThisLine == charsPerLine || r == '\n' {
|
if charsSeenThisLine > charsPerLine || r == '\n' {
|
||||||
|
|
||||||
newIndex = startIndex - bytesSeen + int64(size)
|
newIndex = startIndex - bytesSeen
|
||||||
|
|
||||||
n++
|
n++
|
||||||
if n >= 0 {
|
if n >= 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
charsSeenThisLine = 0
|
charsSeenThisLine = 1
|
||||||
if r == '\n' {
|
|
||||||
|
|
||||||
// var charsIntoLine int64
|
|
||||||
// if it.Buf.Get(uint64(newIndex)) == '\n' && it.Buf.Get(uint64(newIndex-1)) == '\n' {
|
|
||||||
// charsIntoLine = getWrappedLineLen(extraIt, paraIt, newIndex-1, charsPerLine)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if charsIntoLine > 0 {
|
|
||||||
// charsSeenThisLine = charsPerLine - int64(charsIntoLine) - 1
|
|
||||||
// } else {
|
|
||||||
// charsSeenThisLine = 0
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1023,35 +1008,26 @@ func FindNLinesIndexIterator(it ring.Iterator[byte], paraIt ring.Iterator[Para],
|
|||||||
if startIndex-bytesSeen == 0 {
|
if startIndex-bytesSeen == 0 {
|
||||||
newIndex = 0
|
newIndex = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Stopped at:", it.Buf.Get(uint64(newIndex)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newIndex
|
return newIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWrappedLineLen(it ring.Iterator[byte], paraIt ring.Iterator[Para], startIndexRel, charsPerLine int64) int64 {
|
func getCharGridPosX(it ring.Iterator[byte], paraIt ring.Iterator[Para], textBufStartIndexRel, charsPerLine int64) int64 {
|
||||||
|
|
||||||
done := false
|
// @PERF We need a faster way of finding the current paragraph
|
||||||
read := 0
|
|
||||||
bytesToKeep := 0
|
|
||||||
buf := make([]byte, 4)
|
|
||||||
bytesSeen := int64(0)
|
|
||||||
|
|
||||||
paraIt.GotoStart()
|
|
||||||
it.GotoIndex(startIndexRel)
|
|
||||||
|
|
||||||
// @PERF We need a faster way of doing this
|
|
||||||
// Find para that contains the start index
|
// Find para that contains the start index
|
||||||
var para *Para
|
var para *Para
|
||||||
|
paraIt.GotoStart()
|
||||||
for p, done := paraIt.NextPtr(); !done; p, done = paraIt.NextPtr() {
|
for p, done := paraIt.NextPtr(); !done; p, done = paraIt.NextPtr() {
|
||||||
|
|
||||||
if !IsParaValid(it.Buf, p) {
|
if !IsParaValid(it.Buf, p) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
x := it.Buf.RelIndexFromWriteCount(p.EndIndex_WriteCount)
|
startIndexRel := it.Buf.RelIndexFromWriteCount(p.StartIndex_WriteCount)
|
||||||
if startIndexRel > int64(x) {
|
endIndexRel := it.Buf.RelIndexFromWriteCount(p.EndIndex_WriteCount)
|
||||||
|
if textBufStartIndexRel < int64(startIndexRel) || textBufStartIndexRel > int64(endIndexRel) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1070,64 +1046,24 @@ func getWrappedLineLen(it ring.Iterator[byte], paraIt ring.Iterator[Para], start
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find how far into the line the selected char is
|
// println("-----------------------------------", it.Buf.RelIndexFromWriteCount(para.StartIndex_WriteCount), it.Buf.Get(uint64(textBufStartIndexRel)))
|
||||||
charsIntoLine := int64(0)
|
// PrintPara(it.Buf, para)
|
||||||
if startIndexRel != int64(it.Buf.RelIndexFromWriteCount(para.StartIndex_WriteCount+1)) {
|
// println("-----------------------------------", it.Buf.RelIndexFromWriteCount(para.EndIndex_WriteCount), "\n")
|
||||||
|
|
||||||
hasWrap := false
|
// This doesn't consider non-printing chars for wrapping, but should be good enough
|
||||||
// Start at paragraph beginning till startIndex character
|
v1, v2 := it.Buf.ViewsFromToRelIndex(it.Buf.RelIndexFromWriteCount(para.StartIndex_WriteCount+1), uint64(textBufStartIndexRel))
|
||||||
it.GotoIndex(int64(it.Buf.RelIndexFromWriteCount(para.StartIndex_WriteCount + 1)))
|
runeCount := utf8.RuneCount(v1)
|
||||||
for int64(it.CurrToRelIndex()) < startIndexRel && !done {
|
runeCount += utf8.RuneCount(v2)
|
||||||
|
lastCharGridPosX := runeCount % int(charsPerLine+1)
|
||||||
|
return int64(lastCharGridPosX)
|
||||||
|
}
|
||||||
|
|
||||||
read, done = it.NextN(buf[bytesToKeep:], 4)
|
func PrintPara(textBuf *ring.Buffer[byte], p *Para) {
|
||||||
|
|
||||||
r, size := utf8.DecodeRune(buf[:bytesToKeep+read])
|
if !IsParaValid(textBuf, p) {
|
||||||
bytesToKeep += read - size
|
return
|
||||||
copy(buf, buf[size:size+bytesToKeep])
|
|
||||||
|
|
||||||
charsIntoLine++
|
|
||||||
bytesSeen += int64(size)
|
|
||||||
|
|
||||||
if r == '\n' {
|
|
||||||
panic("bruh")
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is true we covered one line
|
|
||||||
if charsIntoLine == charsPerLine {
|
|
||||||
hasWrap = true
|
|
||||||
charsIntoLine = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Previous loop potentially jumps 4 bytes a tick which means we can break out of it
|
|
||||||
// by moving 4 bytes and reaching startIndex, but then charsIntoLine doesn't process the remaining
|
|
||||||
// bytes to see how many bytes they make, so these left overs we cover here
|
|
||||||
it.GotoIndex(int64(it.Buf.RelIndexFromWriteCount(para.StartIndex_WriteCount + 1)))
|
|
||||||
paraStartIndexRel := int64(it.CurrToRelIndex())
|
|
||||||
for bytesToKeep > 0 && paraStartIndexRel+bytesSeen < startIndexRel {
|
|
||||||
|
|
||||||
r, size := utf8.DecodeRune(buf[:bytesToKeep])
|
|
||||||
bytesToKeep -= size
|
|
||||||
copy(buf, buf[size:size+bytesToKeep])
|
|
||||||
|
|
||||||
charsIntoLine++
|
|
||||||
bytesSeen += int64(size)
|
|
||||||
|
|
||||||
if r == '\n' {
|
|
||||||
panic("bruh")
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is true we covered one line
|
|
||||||
if charsIntoLine == charsPerLine {
|
|
||||||
hasWrap = true
|
|
||||||
charsIntoLine = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hasWrap {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return charsIntoLine
|
v1, v2 := textBuf.ViewsFromToWriteCount(p.StartIndex_WriteCount, p.EndIndex_WriteCount)
|
||||||
|
fmt.Println(string(v1) + string(v2))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,6 @@ out vec4 v2fColor;
|
|||||||
out vec3 v2fFragPos;
|
out vec3 v2fFragPos;
|
||||||
|
|
||||||
uniform mat4 projViewMat;
|
uniform mat4 projViewMat;
|
||||||
uniform vec2 modelSize;
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user