Merge branch 'master' into vttest

This commit is contained in:
rrrooommmaaa 2019-01-10 20:30:06 +00:00 committed by GitHub
commit dcf91a03cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 231 additions and 25 deletions

View File

@ -837,7 +837,7 @@ func (buffer *Buffer) EraseLineToCursor() {
line := buffer.getCurrentLine()
for i := 0; i <= int(buffer.cursorX); i++ {
if i < len(line.cells) {
line.cells[i].erase()
line.cells[i].erase(buffer.defaultCell.attr.BgColour)
}
}
}
@ -898,7 +898,7 @@ func (buffer *Buffer) EraseCharacters(n int) {
}
for i := int(buffer.cursorX); i < max; i++ {
line.cells[i].erase()
line.cells[i].erase(buffer.defaultCell.attr.BgColour)
}
}
@ -928,7 +928,7 @@ func (buffer *Buffer) EraseDisplayToCursor() {
if i >= len(line.cells) {
break
}
line.cells[i].erase()
line.cells[i].erase(buffer.defaultCell.attr.BgColour)
}
for i := uint16(0); i < buffer.cursorY; i++ {
rawLine := buffer.convertViewLineToRawLine(i)

View File

@ -53,8 +53,9 @@ func (cell *Cell) Bg() [3]float32 {
return cell.attr.BgColour
}
func (cell *Cell) erase() {
func (cell *Cell) erase(bgColour [3]float32) {
cell.setRune(0)
cell.attr.BgColour = bgColour
}
func (cell *Cell) setRune(r rune) {

View File

@ -36,6 +36,8 @@ type GUI struct {
showDebugInfo bool
keyboardShortcuts map[config.UserAction]*config.KeyCombination
resizeLock *sync.Mutex
handCursor *glfw.Cursor
arrowCursor *glfw.Cursor
}
func Min(x, y int) int {

View File

@ -17,6 +17,22 @@ func (gui *GUI) glfwScrollCallback(w *glfw.Window, xoff float64, yoff float64) {
}
}
func (gui *GUI) getHandCursor() *glfw.Cursor {
if gui.handCursor == nil {
gui.handCursor = glfw.CreateStandardCursor(glfw.HandCursor)
}
return gui.handCursor
}
func (gui *GUI) getArrowCursor() *glfw.Cursor {
if gui.arrowCursor == nil {
gui.arrowCursor = glfw.CreateStandardCursor(glfw.ArrowCursor)
}
return gui.arrowCursor
}
func (gui *GUI) mouseMoveCallback(w *glfw.Window, px float64, py float64) {
scale := gui.scale()
@ -40,9 +56,9 @@ func (gui *GUI) mouseMoveCallback(w *glfw.Window, px float64, py float64) {
}
if url := gui.terminal.ActiveBuffer().GetURLAtPosition(x, y); url != "" {
w.SetCursor(glfw.CreateStandardCursor(glfw.HandCursor))
w.SetCursor(gui.getHandCursor())
} else {
w.SetCursor(glfw.CreateStandardCursor(glfw.ArrowCursor))
w.SetCursor(gui.getArrowCursor())
}
}

69
matrix/automatrix.go Normal file
View File

@ -0,0 +1,69 @@
package matrix
// AutoMatrix -- automatically growing matrix
type AutoMatrix struct {
lines [][]rune
}
// NewAutoMatrix creates a new auto-matrix
func NewAutoMatrix() *AutoMatrix {
m := &AutoMatrix{
lines: make([][]rune, 0),
}
return m
}
// ExtractFrom extracts from (x1, y1) until the end
func (matrix *AutoMatrix) ExtractFrom(x1, y1 int) []rune {
result := make([]rune, 0)
y := y1
for y < len(matrix.lines) {
if matrix.lines[y] != nil {
xMin := 0
if y == y1 {
xMin = x1
}
result = append(result, matrix.lines[y][xMin:]...)
}
y++
}
return result
}
// Extract from (x1, y1) until (x2, y2)
func (matrix *AutoMatrix) Extract(x1, y1, x2, y2 int) []rune {
result := make([]rune, 0)
y := y1
for y <= y2 && y < len(matrix.lines) {
xMin := 0
if y == y1 {
xMin = x1
}
if matrix.lines[y] != nil {
xMax := x2
if y != y2 {
xMax = len(matrix.lines[y]) - 1
}
result = append(result, matrix.lines[y][xMin:xMax]...)
}
y++
}
return result
}
func (matrix *AutoMatrix) setAtLine(value rune, x int, line []rune) []rune {
if x >= len(line) {
line = append(line, make([]rune, x-len(line)+1)...)
}
line[x] = value
return line
}
// SetAt sets a value at (x, y) growing the matrix as necessary
func (matrix *AutoMatrix) SetAt(value rune, x int, y int) {
if y >= len(matrix.lines) {
matrix.lines = append(matrix.lines, make([][]rune, y-len(matrix.lines)+1)...)
}
matrix.lines[y] = matrix.setAtLine(value, x, matrix.lines[y])
}

View File

@ -49,11 +49,17 @@ var csiSequences = []csiMapping{
{id: '@', handler: csiInsertBlankCharactersHandler, description: "Insert Ps (Blank) Character(s) (default = 1) (ICH)"},
}
func csiHandler(pty chan rune, terminal *Terminal) error {
var final rune
type runeRange struct {
min rune
max rune
}
var csiTerminators = runeRange{0x40, 0x7e}
func loadCSI(pty chan rune) (final rune, param string, intermediate string) {
var b rune
param := ""
intermediate := ""
param = ""
intermediate = ""
CSI:
for {
b = <-pty
@ -63,16 +69,27 @@ CSI:
case b >= 0x20 && b <= 0x2F:
//intermediate? useful?
intermediate += string(b)
case b >= 0x40 && b <= 0x7e:
case b >= csiTerminators.min && b <= csiTerminators.max:
final = b
break CSI
}
}
params := strings.Split(param, ";")
if param == "" {
return final, param, intermediate
}
func splitParams(paramString string) []string {
params := strings.Split(paramString, ";")
if paramString == "" {
params = []string{}
}
return params
}
func csiHandler(pty chan rune, terminal *Terminal) error {
final, param, intermediate := loadCSI(pty)
params := splitParams(param)
for _, sequence := range csiSequences {
if sequence.id == final {
@ -237,8 +254,8 @@ func csiCursorCharacterAbsoluteHandler(params []string, intermediate string, ter
return nil
}
func csiCursorPositionHandler(params []string, intermediate string, terminal *Terminal) error {
x, y := 1, 1
func parseCursorPosition(params []string) (x, y int) {
x, y = 1, 1
if len(params) == 2 {
var err error
if params[0] != "" {
@ -254,6 +271,11 @@ func csiCursorPositionHandler(params []string, intermediate string, terminal *Te
}
}
}
return x, y
}
func csiCursorPositionHandler(params []string, intermediate string, terminal *Terminal) error {
x, y := parseCursorPosition(params)
terminal.ActiveBuffer().SetPosition(uint16(x-1), uint16(y-1))
return nil

View File

@ -7,32 +7,130 @@ import (
"math"
"strings"
"github.com/liamg/aminal/matrix"
"github.com/liamg/aminal/sixel"
)
func sixelHandler(pty chan rune, terminal *Terminal) error {
data := []rune{}
type boolFormRuneFunc func(rune) bool
func swallowByFunction(pty chan rune, isTerminator boolFormRuneFunc) {
for {
b := <-pty
if b == 0x1b { // terminated by ESC bell or ESC \
if isTerminator(b) {
break
}
}
}
func filter(src []rune) []rune {
result := make([]rune, 0, len(src))
for _, v := range src {
if v >= 33 {
result = append(result, v)
}
}
return result
}
func sixelHandler(pty chan rune, terminal *Terminal) error {
debug := ""
// data := []rune{}
// track for Windows formatting workaround
scrollOffset := uint16(terminal.GetScrollOffset())
x := terminal.ActiveBuffer().CursorColumn() + 2 // reserve two bytes for Sixel prefix (ESC P)
y := terminal.ActiveBuffer().CursorLine()
scrollingLine := terminal.ActiveBuffer().ViewHeight() - 1
xStart := x
yStartWithOffset := y + scrollOffset
matrix := matrix.NewAutoMatrix() // a simplified version of Buffer
for {
b := <-pty
if b == 0x1b {
t := <-pty
if t == '[' { // Windows injected a CSI sequence
final, param, _ := loadCSI(pty)
if final == 'H' {
// position cursor
params := splitParams(param)
{
xT, yT := parseCursorPosition(params) // 1 based
x = uint16(xT - 1) // 0 based
y = uint16(yT - 1) // 0 based
}
}
debug += "[CSI " + param + string(final) + "]"
continue
}
if t == ']' { // Windows injected an OSC sequence
// TODO: pass through as if it came via normal stream
swallowByFunction(pty, terminal.IsOSCTerminator)
debug += "[OSC]"
continue
}
// if re-drawing a region beforethe start of sixel sequencce,
// ignore all possible ESC pairs (including ESC P)
if y+scrollOffset < yStartWithOffset || (y+scrollOffset == yStartWithOffset && x < xStart) {
x += 2
continue
}
if t != 0x07 && t != 0x5c {
return fmt.Errorf("Incorrect terminator in sixel sequence: 0x%02X [%c]", t, t)
}
break
break // terminated by ESC bell or ESC \
}
if b >= 33 {
data = append(data, b)
if b == 0x0d {
// skip
} else if b == 0x0a {
terminal.logger.Debugf("Sixel line: %s", debug)
debug = ""
if y == scrollingLine {
scrollOffset++
} else {
y++
}
x = 0
} else if y+scrollOffset < yStartWithOffset || (y+scrollOffset == yStartWithOffset && x < xStart) {
x++
} else if b < 32 {
x++ // always?
} else {
debug += string(b)
matrix.SetAt(b, int(x), int(y+scrollOffset-yStartWithOffset))
x++
}
/*
if b >= 33 {
data = append(data, b)
}
*/
}
six, err := sixel.ParseString(string(data))
if debug != "" {
terminal.logger.Debugf("Sixel last line: %s", debug)
}
newData := matrix.ExtractFrom(int(xStart), 0) // , int(x), int(y+scrollOffset))
terminal.logger.Debugf("Sixel data: %s", string(newData))
filteredData := filter(newData)
six, err := sixel.ParseString(string(filteredData))
if err != nil {
return fmt.Errorf("Failed to parse sixel data: %s", err)
}
drawSixel(six, terminal)
return nil
}
func drawSixel(six *sixel.Sixel, terminal *Terminal) {
originalImage := six.RGBA()
w := originalImage.Bounds().Size().X
@ -70,6 +168,4 @@ func sixelHandler(pty chan rune, terminal *Terminal) error {
cell.SetImage(rgba)
}
}
return nil
}