start scrolling

This commit is contained in:
Liam Galvin 2018-09-02 20:59:35 +01:00
parent ada4e924f9
commit 8e5a9fb26d
5 changed files with 209 additions and 98 deletions

View File

@ -46,7 +46,7 @@ func (buffer *Buffer) SetReplaceMode() {
buffer.replaceMode = true
}
func (buffer *Buffer) SetMargins(top uint, bottom uint) {
func (buffer *Buffer) SetVerticalMargins(top uint, bottom uint) {
buffer.topMargin = top
buffer.bottomMargin = bottom
}
@ -57,11 +57,36 @@ func (buffer *Buffer) GetScrollOffset() uint {
func (buffer *Buffer) ScrollDown(lines uint16) {
defer buffer.emitDisplayChange()
// scrollable region is enabled
if buffer.topMargin > 0 || buffer.bottomMargin < uint(buffer.ViewHeight())-1 {
for c := 0; c < int(lines); c++ {
for i := buffer.topMargin; i < buffer.bottomMargin; i++ {
above := buffer.getViewLine(uint16(i))
below := buffer.getViewLine(uint16(i + 1))
above.cells = below.cells
}
final := buffer.getViewLine(uint16(buffer.bottomMargin))
lineIndex := buffer.convertViewLineToRawLine(uint16(buffer.bottomMargin + 1))
if lineIndex < uint64(len(buffer.lines)) {
*final = buffer.lines[lineIndex]
} else {
*final = newLine()
}
}
return
}
if buffer.Height() < int(buffer.ViewHeight()) {
return
}
defer buffer.emitDisplayChange()
if uint(lines) > buffer.scrollLinesFromBottom {
lines = uint16(buffer.scrollLinesFromBottom)
}
@ -70,11 +95,36 @@ func (buffer *Buffer) ScrollDown(lines uint16) {
func (buffer *Buffer) ScrollUp(lines uint16) {
if buffer.Height() < int(buffer.ViewHeight()) {
defer buffer.emitDisplayChange()
// scrollable region is enabled
if buffer.topMargin > 0 || buffer.bottomMargin < uint(buffer.ViewHeight())-1 {
for c := 0; c < int(lines); c++ {
for i := buffer.bottomMargin; i > buffer.topMargin+1; i-- {
below := buffer.getViewLine(uint16(i))
above := buffer.getViewLine(uint16(i - 1))
below.cells = above.cells
}
final := buffer.getViewLine(uint16(buffer.topMargin))
lineIndex := buffer.convertViewLineToRawLine(uint16(buffer.topMargin - 1))
if lineIndex >= 0 && lineIndex < uint64(len(buffer.lines)) {
*final = buffer.lines[lineIndex]
} else {
panic("hmm!?")
*final = newLine()
}
}
return
}
defer buffer.emitDisplayChange()
if buffer.Height() < int(buffer.ViewHeight()) {
return
}
if uint(lines)+buffer.scrollLinesFromBottom >= (uint(buffer.Height()) - uint(buffer.ViewHeight())) {
buffer.scrollLinesFromBottom = uint(buffer.Height()) - uint(buffer.ViewHeight())
@ -279,12 +329,26 @@ func (buffer *Buffer) CarriageReturn() {
func (buffer *Buffer) NewLine() {
defer buffer.emitDisplayChange()
buffer.cursorX = 0
if (buffer.topMargin > 0 || buffer.bottomMargin < uint(buffer.ViewHeight())-1) && uint(buffer.cursorY) == buffer.bottomMargin {
// scrollable region is enabled
for i := buffer.topMargin; i < buffer.bottomMargin; i++ {
above := buffer.getViewLine(uint16(i))
below := buffer.getViewLine(uint16(i + 1))
above.cells = below.cells
}
final := buffer.getViewLine(uint16(buffer.bottomMargin))
*final = newLine()
return
}
if buffer.cursorY >= buffer.ViewHeight()-1 {
buffer.lines = append(buffer.lines, newLine())
} else {
buffer.cursorY++
}
buffer.cursorX = 0
}
func (buffer *Buffer) MovePosition(x int16, y int16) {
@ -344,23 +408,27 @@ func (buffer *Buffer) Clear() {
// creates if necessary
func (buffer *Buffer) getCurrentLine() *Line {
return buffer.getViewLine(buffer.cursorY)
}
if buffer.cursorY >= buffer.ViewHeight() { // @todo is this okay?
func (buffer *Buffer) getViewLine(index uint16) *Line {
if index >= buffer.ViewHeight() { // @todo is this okay?
return &buffer.lines[len(buffer.lines)-1]
}
if len(buffer.lines) < int(buffer.ViewHeight()) {
for int(buffer.cursorY) >= len(buffer.lines) {
for int(index) >= len(buffer.lines) {
buffer.lines = append(buffer.lines, newLine())
}
return &buffer.lines[int(buffer.cursorY)]
return &buffer.lines[int(index)]
}
if int(buffer.RawLine()) < len(buffer.lines) {
return &buffer.lines[buffer.RawLine()]
if int(buffer.convertViewLineToRawLine(index)) < len(buffer.lines) {
return &buffer.lines[buffer.convertViewLineToRawLine(index)]
}
panic(fmt.Sprintf("Failed to retrieve line for %d %d", buffer.cursorX, buffer.cursorY))
panic(fmt.Sprintf("Failed to retrieve line for %d", index))
}
func (buffer *Buffer) EraseLine() {
@ -547,5 +615,5 @@ func (buffer *Buffer) ResizeView(width uint16, height uint16) {
line = buffer.getCurrentLine()
buffer.cursorX = uint16((len(line.cells) - cXFromEndOfLine) - 1)
buffer.SetMargins(0, uint(buffer.viewHeight-1))
buffer.SetVerticalMargins(0, uint(buffer.viewHeight-1))
}

View File

@ -15,12 +15,14 @@ var csiSequenceMap = map[rune]csiSequenceHandler{
't': csiWindowManipulation,
'J': csiEraseInDisplayHandler,
'K': csiEraseInLineHandler,
'L': csiInsertLinesHandler,
'P': csiDeleteHandler,
'T': csiScrollHandler,
'S': csiScrollUpHandler,
'T': csiScrollDownHandler,
'X': csiEraseCharactersHandler,
}
func csiScrollHandler(params []string, intermediate string, terminal *Terminal) error {
func csiScrollUpHandler(params []string, intermediate string, terminal *Terminal) error {
distance := 1
if len(params) > 1 {
return fmt.Errorf("Not supported")
@ -32,6 +34,41 @@ func csiScrollHandler(params []string, intermediate string, terminal *Terminal)
distance = 1
}
}
terminal.logger.Debugf("Scrolling up %d", distance)
terminal.ScrollUp(uint16(distance))
return nil
}
func csiInsertLinesHandler(params []string, intermediate string, terminal *Terminal) error {
count := 1
if len(params) > 1 {
return fmt.Errorf("Not supported")
}
if len(params) == 1 {
var err error
count, err = strconv.Atoi(params[0])
if err != nil {
count = 1
}
}
terminal.logger.Debugf("Inserting %d lines", count)
panic("Not supported")
return nil
}
func csiScrollDownHandler(params []string, intermediate string, terminal *Terminal) error {
distance := 1
if len(params) > 1 {
return fmt.Errorf("Not supported")
}
if len(params) == 1 {
var err error
distance, err = strconv.Atoi(params[0])
if err != nil {
distance = 1
}
}
terminal.logger.Debugf("Scrolling down %d", distance)
terminal.ScrollDown(uint16(distance))
return nil
}
@ -61,90 +98,9 @@ func csiSetMarginsHandler(params []string, intermediate string, terminal *Termin
top--
bottom--
terminal.logger.Warnf("Request to set margins from line %d to %d", top, bottom)
terminal.ActiveBuffer().SetVerticalMargins(uint(top), uint(bottom))
terminal.ActiveBuffer().SetPosition(0, 0)
return fmt.Errorf("Not supported")
}
func csiSetMode(modeStr string, enabled bool, terminal *Terminal) error {
/*
Mouse support
#define SET_X10_MOUSE 9
#define SET_VT200_MOUSE 1000
#define SET_VT200_HIGHLIGHT_MOUSE 1001
#define SET_BTN_EVENT_MOUSE 1002
#define SET_ANY_EVENT_MOUSE 1003
#define SET_FOCUS_EVENT_MOUSE 1004
#define SET_EXT_MODE_MOUSE 1005
#define SET_SGR_EXT_MODE_MOUSE 1006
#define SET_URXVT_EXT_MODE_MOUSE 1015
#define SET_ALTERNATE_SCROLL 1007
*/
switch modeStr {
case "4":
if enabled { // @todo support replace mode
terminal.ActiveBuffer().SetInsertMode()
} else {
terminal.ActiveBuffer().SetReplaceMode()
}
case "?1":
terminal.modes.ApplicationCursorKeys = enabled
case "?7":
// auto-wrap mode
//DECAWM
terminal.ActiveBuffer().SetAutoWrap(enabled)
case "?9":
if enabled {
terminal.logger.Infof("Turning on X10 mouse mode")
terminal.SetMouseMode(MouseModeX10)
} else {
terminal.logger.Infof("Turning off X10 mouse mode")
terminal.SetMouseMode(MouseModeNone)
}
case "?12", "?13":
terminal.modes.BlinkingCursor = enabled
case "?25":
terminal.modes.ShowCursor = enabled
case "?47", "?1047":
if enabled {
terminal.UseAltBuffer()
} else {
terminal.UseMainBuffer()
}
case "?1000", "?1006;1000", "?10061000": // ?10061000 seen from htop
// enable mouse tracking
// 1000 refers to ext mode for extended mouse click area - otherwise only x <= 255-31
if enabled {
terminal.logger.Infof("Turning on VT200 mouse mode")
terminal.SetMouseMode(MouseModeVT200)
} else {
terminal.logger.Infof("Turning off VT200 mouse mode")
terminal.SetMouseMode(MouseModeNone)
}
case "?1048":
if enabled {
terminal.ActiveBuffer().SaveCursor()
} else {
terminal.ActiveBuffer().RestoreCursor()
}
case "?1049":
if enabled {
terminal.UseAltBuffer()
} else {
terminal.UseMainBuffer()
}
default:
return fmt.Errorf("Unsupported CSI %sl code", modeStr)
}
return nil
}
@ -334,7 +290,7 @@ CSI:
err = fmt.Errorf("Unknown CSI control sequence: 0x%02X (ESC[%s%s%s)", final, param, intermediate, string(final))
}
}
terminal.logger.Debugf("Received CSI control sequence: 0x%02X (ESC[%s%s%s)", final, param, intermediate, string(final))
fmt.Printf("CSI 0x%02X (ESC[%s%s%s)\n", final, param, intermediate, string(final))
return err
}

83
terminal/modes.go Normal file
View File

@ -0,0 +1,83 @@
package terminal
import "fmt"
func csiSetMode(modeStr string, enabled bool, terminal *Terminal) error {
/*
Mouse support
#define SET_X10_MOUSE 9
#define SET_VT200_MOUSE 1000
#define SET_VT200_HIGHLIGHT_MOUSE 1001
#define SET_BTN_EVENT_MOUSE 1002
#define SET_ANY_EVENT_MOUSE 1003
#define SET_FOCUS_EVENT_MOUSE 1004
#define SET_EXT_MODE_MOUSE 1005
#define SET_SGR_EXT_MODE_MOUSE 1006
#define SET_URXVT_EXT_MODE_MOUSE 1015
#define SET_ALTERNATE_SCROLL 1007
*/
switch modeStr {
case "4":
if enabled { // @todo support replace mode
terminal.ActiveBuffer().SetInsertMode()
} else {
terminal.ActiveBuffer().SetReplaceMode()
}
case "?1":
terminal.modes.ApplicationCursorKeys = enabled
case "?7":
// auto-wrap mode
//DECAWM
terminal.ActiveBuffer().SetAutoWrap(enabled)
case "?9":
if enabled {
terminal.logger.Infof("Turning on X10 mouse mode")
terminal.SetMouseMode(MouseModeX10)
} else {
terminal.logger.Infof("Turning off X10 mouse mode")
terminal.SetMouseMode(MouseModeNone)
}
case "?12", "?13":
terminal.modes.BlinkingCursor = enabled
case "?25":
terminal.modes.ShowCursor = enabled
case "?47", "?1047":
if enabled {
terminal.UseAltBuffer()
} else {
terminal.UseMainBuffer()
}
case "?1000", "?1006;1000", "?10061000": // ?10061000 seen from htop
// enable mouse tracking
// 1000 refers to ext mode for extended mouse click area - otherwise only x <= 255-31
if enabled {
terminal.logger.Infof("Turning on VT200 mouse mode")
terminal.SetMouseMode(MouseModeVT200)
} else {
terminal.logger.Infof("Turning off VT200 mouse mode")
terminal.SetMouseMode(MouseModeNone)
}
case "?1048":
if enabled {
terminal.ActiveBuffer().SaveCursor()
} else {
terminal.ActiveBuffer().RestoreCursor()
}
case "?1049":
if enabled {
terminal.UseAltBuffer()
} else {
terminal.UseMainBuffer()
}
default:
return fmt.Errorf("Unsupported CSI %sl code", modeStr)
}
return nil
}

View File

@ -26,6 +26,7 @@ var escapeSequenceMap = map[rune]escapeSequenceHandler{
}
func newLineSequenceHandler(pty chan rune, terminal *Terminal) error {
terminal.logger.Debugf("New line!")
terminal.ActiveBuffer().NewLine()
return nil
}
@ -94,7 +95,7 @@ func (terminal *Terminal) processInput(ctx context.Context, pty chan rune) {
terminal.logger.Errorf("Error handling escape sequence: %s", err)
}
} else {
terminal.logger.Debugf("Received character 0x%X: %q", b, string(b))
//terminal.logger.Debugf("Received character 0x%X: %q", b, string(b))
if b >= 0x20 {
terminal.ActiveBuffer().Write(b)
} else {

View File

@ -133,10 +133,13 @@ func (terminal *Terminal) GetScrollOffset() uint {
}
func (terminal *Terminal) ScrollDown(lines uint16) {
terminal.logger.Infof("Scrolling down %d", lines)
terminal.ActiveBuffer().ScrollDown(lines)
}
func (terminal *Terminal) ScrollUp(lines uint16) {
terminal.logger.Infof("Scrolling up %d", lines)
terminal.ActiveBuffer().ScrollUp(lines)
}