mirror of https://github.com/liamg/aminal.git
start scrolling
This commit is contained in:
parent
ada4e924f9
commit
8e5a9fb26d
|
@ -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))
|
||||
}
|
||||
|
|
126
terminal/csi.go
126
terminal/csi.go
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue