|
|
@@ -29,6 +29,15 @@ const (
|
|
|
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
|
|
|
)
|
|
|
|
|
|
+const (
|
|
|
+ genericRead = 0x80000000
|
|
|
+ genericWrite = 0x40000000
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
+ consoleTextmodeBuffer = 0x1
|
|
|
+)
|
|
|
+
|
|
|
type wchar uint16
|
|
|
type short int16
|
|
|
type dword uint32
|
|
|
@@ -69,14 +78,16 @@ var (
|
|
|
procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo")
|
|
|
procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo")
|
|
|
procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW")
|
|
|
+ procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer")
|
|
|
)
|
|
|
|
|
|
// Writer provide colorable Writer to the console
|
|
|
type Writer struct {
|
|
|
- out io.Writer
|
|
|
- handle syscall.Handle
|
|
|
- oldattr word
|
|
|
- oldpos coord
|
|
|
+ out io.Writer
|
|
|
+ handle syscall.Handle
|
|
|
+ althandle syscall.Handle
|
|
|
+ oldattr word
|
|
|
+ oldpos coord
|
|
|
}
|
|
|
|
|
|
// NewColorable return new instance of Writer which handle escape sequence from File.
|
|
|
@@ -407,6 +418,7 @@ func (w *Writer) Write(data []byte) (n int, err error) {
|
|
|
var csbi consoleScreenBufferInfo
|
|
|
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
|
|
|
+ handle := w.handle
|
|
|
er := bytes.NewReader(data)
|
|
|
var bw [1]byte
|
|
|
loop:
|
|
|
@@ -455,61 +467,61 @@ loop:
|
|
|
if err != nil {
|
|
|
continue
|
|
|
}
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
csbi.cursorPosition.y -= short(n)
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
case 'B':
|
|
|
n, err = strconv.Atoi(buf.String())
|
|
|
if err != nil {
|
|
|
continue
|
|
|
}
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
csbi.cursorPosition.y += short(n)
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
case 'C':
|
|
|
n, err = strconv.Atoi(buf.String())
|
|
|
if err != nil {
|
|
|
continue
|
|
|
}
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
csbi.cursorPosition.x += short(n)
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
case 'D':
|
|
|
n, err = strconv.Atoi(buf.String())
|
|
|
if err != nil {
|
|
|
continue
|
|
|
}
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
csbi.cursorPosition.x -= short(n)
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
case 'E':
|
|
|
n, err = strconv.Atoi(buf.String())
|
|
|
if err != nil {
|
|
|
continue
|
|
|
}
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
csbi.cursorPosition.x = 0
|
|
|
csbi.cursorPosition.y += short(n)
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
case 'F':
|
|
|
n, err = strconv.Atoi(buf.String())
|
|
|
if err != nil {
|
|
|
continue
|
|
|
}
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
csbi.cursorPosition.x = 0
|
|
|
csbi.cursorPosition.y -= short(n)
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
case 'G':
|
|
|
n, err = strconv.Atoi(buf.String())
|
|
|
if err != nil {
|
|
|
continue
|
|
|
}
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
csbi.cursorPosition.x = short(n - 1)
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
case 'H', 'f':
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
if buf.Len() > 0 {
|
|
|
token := strings.Split(buf.String(), ";")
|
|
|
switch len(token) {
|
|
|
@@ -534,7 +546,7 @@ loop:
|
|
|
} else {
|
|
|
csbi.cursorPosition.y = 0
|
|
|
}
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
case 'J':
|
|
|
n := 0
|
|
|
if buf.Len() > 0 {
|
|
|
@@ -545,7 +557,7 @@ loop:
|
|
|
}
|
|
|
var count, written dword
|
|
|
var cursor coord
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
switch n {
|
|
|
case 0:
|
|
|
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
|
|
@@ -557,8 +569,8 @@ loop:
|
|
|
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
|
|
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
|
|
|
}
|
|
|
- procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
|
|
- procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
|
|
+ procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
|
|
+ procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
|
|
case 'K':
|
|
|
n := 0
|
|
|
if buf.Len() > 0 {
|
|
|
@@ -567,7 +579,7 @@ loop:
|
|
|
continue
|
|
|
}
|
|
|
}
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
var cursor coord
|
|
|
var count, written dword
|
|
|
switch n {
|
|
|
@@ -581,14 +593,14 @@ loop:
|
|
|
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
|
|
|
count = dword(csbi.size.x)
|
|
|
}
|
|
|
- procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
|
|
- procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
|
|
+ procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
|
|
+ procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
|
|
|
case 'm':
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
attr := csbi.attributes
|
|
|
cs := buf.String()
|
|
|
if cs == "" {
|
|
|
- procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr))
|
|
|
+ procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr))
|
|
|
continue
|
|
|
}
|
|
|
token := strings.Split(cs, ";")
|
|
|
@@ -715,38 +727,52 @@ loop:
|
|
|
attr |= backgroundBlue
|
|
|
}
|
|
|
}
|
|
|
- procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
|
|
|
+ procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
|
|
|
}
|
|
|
}
|
|
|
case 'h':
|
|
|
var ci consoleCursorInfo
|
|
|
cs := buf.String()
|
|
|
if cs == "5>" {
|
|
|
- procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
ci.visible = 0
|
|
|
- procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
} else if cs == "?25" {
|
|
|
- procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
ci.visible = 1
|
|
|
- procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ } else if cs == "?1049" {
|
|
|
+ if w.althandle == 0 {
|
|
|
+ h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0)
|
|
|
+ w.althandle = syscall.Handle(h)
|
|
|
+ if w.althandle != 0 {
|
|
|
+ handle = w.althandle
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
case 'l':
|
|
|
var ci consoleCursorInfo
|
|
|
cs := buf.String()
|
|
|
if cs == "5>" {
|
|
|
- procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
ci.visible = 1
|
|
|
- procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
} else if cs == "?25" {
|
|
|
- procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
ci.visible = 0
|
|
|
- procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ } else if cs == "?1049" {
|
|
|
+ if w.althandle != 0 {
|
|
|
+ syscall.CloseHandle(w.althandle)
|
|
|
+ w.althandle = 0
|
|
|
+ handle = w.handle
|
|
|
+ }
|
|
|
}
|
|
|
case 's':
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
w.oldpos = csbi.cursorPosition
|
|
|
case 'u':
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
|
|
|
}
|
|
|
}
|
|
|
|