|
|
@@ -1,3 +1,6 @@
|
|
|
+// +build windows
|
|
|
+// +build !appengine
|
|
|
+
|
|
|
package colorable
|
|
|
|
|
|
import (
|
|
|
@@ -26,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
|
|
|
@@ -65,14 +77,18 @@ var (
|
|
|
procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
|
|
|
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
|
|
|
- lastbuf bytes.Buffer
|
|
|
- oldattr word
|
|
|
- oldpos coord
|
|
|
+ out io.Writer
|
|
|
+ handle syscall.Handle
|
|
|
+ althandle syscall.Handle
|
|
|
+ oldattr word
|
|
|
+ oldpos coord
|
|
|
+ rest bytes.Buffer
|
|
|
}
|
|
|
|
|
|
// NewColorable return new instance of Writer which handle escape sequence from File.
|
|
|
@@ -86,9 +102,8 @@ func NewColorable(file *os.File) io.Writer {
|
|
|
handle := syscall.Handle(file.Fd())
|
|
|
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
return &Writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}}
|
|
|
- } else {
|
|
|
- return file
|
|
|
}
|
|
|
+ return file
|
|
|
}
|
|
|
|
|
|
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
|
|
|
@@ -360,20 +375,65 @@ var color256 = map[int]int{
|
|
|
255: 0xeeeeee,
|
|
|
}
|
|
|
|
|
|
+// `\033]0;TITLESTR\007`
|
|
|
+func doTitleSequence(er *bytes.Reader) error {
|
|
|
+ var c byte
|
|
|
+ var err error
|
|
|
+
|
|
|
+ c, err = er.ReadByte()
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if c != '0' && c != '2' {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ c, err = er.ReadByte()
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if c != ';' {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ title := make([]byte, 0, 80)
|
|
|
+ for {
|
|
|
+ c, err = er.ReadByte()
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if c == 0x07 || c == '\n' {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ title = append(title, c)
|
|
|
+ }
|
|
|
+ if len(title) > 0 {
|
|
|
+ title8, err := syscall.UTF16PtrFromString(string(title))
|
|
|
+ if err == nil {
|
|
|
+ procSetConsoleTitle.Call(uintptr(unsafe.Pointer(title8)))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
// Write write data on console
|
|
|
func (w *Writer) Write(data []byte) (n int, err error) {
|
|
|
var csbi consoleScreenBufferInfo
|
|
|
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
|
|
|
- er := bytes.NewReader(data)
|
|
|
+ handle := w.handle
|
|
|
+
|
|
|
+ var er *bytes.Reader
|
|
|
+ if w.rest.Len() > 0 {
|
|
|
+ var rest bytes.Buffer
|
|
|
+ w.rest.WriteTo(&rest)
|
|
|
+ w.rest.Reset()
|
|
|
+ rest.Write(data)
|
|
|
+ er = bytes.NewReader(rest.Bytes())
|
|
|
+ } else {
|
|
|
+ er = bytes.NewReader(data)
|
|
|
+ }
|
|
|
var bw [1]byte
|
|
|
loop:
|
|
|
for {
|
|
|
- r1, _, err := procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
- if r1 == 0 {
|
|
|
- break loop
|
|
|
- }
|
|
|
-
|
|
|
c1, err := er.ReadByte()
|
|
|
if err != nil {
|
|
|
break loop
|
|
|
@@ -385,155 +445,202 @@ loop:
|
|
|
}
|
|
|
c2, err := er.ReadByte()
|
|
|
if err != nil {
|
|
|
- w.lastbuf.WriteByte(c1)
|
|
|
break loop
|
|
|
}
|
|
|
- if c2 != 0x5b {
|
|
|
- w.lastbuf.WriteByte(c1)
|
|
|
- w.lastbuf.WriteByte(c2)
|
|
|
+
|
|
|
+ switch c2 {
|
|
|
+ case '>':
|
|
|
+ continue
|
|
|
+ case ']':
|
|
|
+ w.rest.WriteByte(c1)
|
|
|
+ w.rest.WriteByte(c2)
|
|
|
+ er.WriteTo(&w.rest)
|
|
|
+ if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 {
|
|
|
+ break loop
|
|
|
+ }
|
|
|
+ er = bytes.NewReader(w.rest.Bytes()[2:])
|
|
|
+ err := doTitleSequence(er)
|
|
|
+ if err != nil {
|
|
|
+ break loop
|
|
|
+ }
|
|
|
+ w.rest.Reset()
|
|
|
+ continue
|
|
|
+ // https://github.com/mattn/go-colorable/issues/27
|
|
|
+ case '7':
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ w.oldpos = csbi.cursorPosition
|
|
|
+ continue
|
|
|
+ case '8':
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
|
|
|
+ continue
|
|
|
+ case 0x5b:
|
|
|
+ // execute part after switch
|
|
|
+ default:
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
+ w.rest.WriteByte(c1)
|
|
|
+ w.rest.WriteByte(c2)
|
|
|
+ er.WriteTo(&w.rest)
|
|
|
+
|
|
|
var buf bytes.Buffer
|
|
|
var m byte
|
|
|
- for {
|
|
|
- c, err := er.ReadByte()
|
|
|
- if err != nil {
|
|
|
- w.lastbuf.WriteByte(c1)
|
|
|
- w.lastbuf.WriteByte(c2)
|
|
|
- w.lastbuf.Write(buf.Bytes())
|
|
|
- break loop
|
|
|
- }
|
|
|
+ for i, c := range w.rest.Bytes()[2:] {
|
|
|
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
|
|
|
m = c
|
|
|
+ er = bytes.NewReader(w.rest.Bytes()[2+i+1:])
|
|
|
+ w.rest.Reset()
|
|
|
break
|
|
|
}
|
|
|
buf.Write([]byte(string(c)))
|
|
|
}
|
|
|
+ if m == 0 {
|
|
|
+ break loop
|
|
|
+ }
|
|
|
|
|
|
- var csbi consoleScreenBufferInfo
|
|
|
switch m {
|
|
|
case 'A':
|
|
|
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 '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)))
|
|
|
- csbi.cursorPosition.x -= short(n)
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ csbi.cursorPosition.x += short(n)
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
case 'D':
|
|
|
n, err = strconv.Atoi(buf.String())
|
|
|
if err != nil {
|
|
|
continue
|
|
|
}
|
|
|
- if n, err = strconv.Atoi(buf.String()); err == nil {
|
|
|
- var csbi consoleScreenBufferInfo
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
- csbi.cursorPosition.x += short(n)
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ csbi.cursorPosition.x -= short(n)
|
|
|
+ if csbi.cursorPosition.x < 0 {
|
|
|
+ csbi.cursorPosition.x = 0
|
|
|
}
|
|
|
+ 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)))
|
|
|
- case 'H':
|
|
|
- token := strings.Split(buf.String(), ";")
|
|
|
- if len(token) != 2 {
|
|
|
- continue
|
|
|
- }
|
|
|
- n1, err := strconv.Atoi(token[0])
|
|
|
- if err != nil {
|
|
|
- continue
|
|
|
- }
|
|
|
- n2, err := strconv.Atoi(token[1])
|
|
|
- if err != nil {
|
|
|
- continue
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ case 'H', 'f':
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ if buf.Len() > 0 {
|
|
|
+ token := strings.Split(buf.String(), ";")
|
|
|
+ switch len(token) {
|
|
|
+ case 1:
|
|
|
+ n1, err := strconv.Atoi(token[0])
|
|
|
+ if err != nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ csbi.cursorPosition.y = short(n1 - 1)
|
|
|
+ case 2:
|
|
|
+ n1, err := strconv.Atoi(token[0])
|
|
|
+ if err != nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ n2, err := strconv.Atoi(token[1])
|
|
|
+ if err != nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ csbi.cursorPosition.x = short(n2 - 1)
|
|
|
+ csbi.cursorPosition.y = short(n1 - 1)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ csbi.cursorPosition.y = 0
|
|
|
}
|
|
|
- csbi.cursorPosition.x = short(n2 - 1)
|
|
|
- csbi.cursorPosition.y = short(n1 - 1)
|
|
|
- procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
+ procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
|
|
|
case 'J':
|
|
|
- n, err := strconv.Atoi(buf.String())
|
|
|
- if err != nil {
|
|
|
- continue
|
|
|
+ n := 0
|
|
|
+ if buf.Len() > 0 {
|
|
|
+ n, err = strconv.Atoi(buf.String())
|
|
|
+ if err != nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
}
|
|
|
- procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
+ var count, written dword
|
|
|
var cursor coord
|
|
|
+ procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
|
|
|
switch n {
|
|
|
case 0:
|
|
|
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
|
|
+ count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
|
|
|
case 1:
|
|
|
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
|
|
+ count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.window.top-csbi.cursorPosition.y)*dword(csbi.size.x)
|
|
|
case 2:
|
|
|
cursor = coord{x: csbi.window.left, y: csbi.window.top}
|
|
|
+ count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
|
|
|
}
|
|
|
- var count, written dword
|
|
|
- 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, err := strconv.Atoi(buf.String())
|
|
|
- if err != nil {
|
|
|
- continue
|
|
|
+ n := 0
|
|
|
+ if buf.Len() > 0 {
|
|
|
+ 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)))
|
|
|
var cursor coord
|
|
|
+ var count, written dword
|
|
|
switch n {
|
|
|
case 0:
|
|
|
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
|
|
|
+ count = dword(csbi.size.x - csbi.cursorPosition.x)
|
|
|
case 1:
|
|
|
- cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
|
|
|
+ cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
|
|
|
+ count = dword(csbi.size.x - csbi.cursorPosition.x)
|
|
|
case 2:
|
|
|
- cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
|
|
|
+ cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
|
|
|
+ count = dword(csbi.size.x)
|
|
|
}
|
|
|
- var count, written dword
|
|
|
- count = dword(csbi.size.x - csbi.cursorPosition.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, ";")
|
|
|
@@ -547,7 +654,7 @@ loop:
|
|
|
attr |= foregroundIntensity
|
|
|
case n == 7:
|
|
|
attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
|
|
|
- case 22 == n || n == 25 || n == 25:
|
|
|
+ case n == 22 || n == 25:
|
|
|
attr |= foregroundIntensity
|
|
|
case n == 27:
|
|
|
attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
|
|
|
@@ -572,6 +679,21 @@ loop:
|
|
|
attr |= n256foreAttr[n256]
|
|
|
i += 2
|
|
|
}
|
|
|
+ } else if len(token) == 5 && token[i+1] == "2" {
|
|
|
+ var r, g, b int
|
|
|
+ r, _ = strconv.Atoi(token[i+2])
|
|
|
+ g, _ = strconv.Atoi(token[i+3])
|
|
|
+ b, _ = strconv.Atoi(token[i+4])
|
|
|
+ i += 4
|
|
|
+ if r > 127 {
|
|
|
+ attr |= foregroundRed
|
|
|
+ }
|
|
|
+ if g > 127 {
|
|
|
+ attr |= foregroundGreen
|
|
|
+ }
|
|
|
+ if b > 127 {
|
|
|
+ attr |= foregroundBlue
|
|
|
+ }
|
|
|
} else {
|
|
|
attr = attr & (w.oldattr & backgroundMask)
|
|
|
}
|
|
|
@@ -599,6 +721,21 @@ loop:
|
|
|
attr |= n256backAttr[n256]
|
|
|
i += 2
|
|
|
}
|
|
|
+ } else if len(token) == 5 && token[i+1] == "2" {
|
|
|
+ var r, g, b int
|
|
|
+ r, _ = strconv.Atoi(token[i+2])
|
|
|
+ g, _ = strconv.Atoi(token[i+3])
|
|
|
+ b, _ = strconv.Atoi(token[i+4])
|
|
|
+ i += 4
|
|
|
+ if r > 127 {
|
|
|
+ attr |= backgroundRed
|
|
|
+ }
|
|
|
+ if g > 127 {
|
|
|
+ attr |= backgroundGreen
|
|
|
+ }
|
|
|
+ if b > 127 {
|
|
|
+ attr |= backgroundBlue
|
|
|
+ }
|
|
|
} else {
|
|
|
attr = attr & (w.oldattr & foregroundMask)
|
|
|
}
|
|
|
@@ -630,33 +767,56 @@ 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 == "?25" {
|
|
|
- var ci consoleCursorInfo
|
|
|
- procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ if cs == "5>" {
|
|
|
+ procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ ci.visible = 0
|
|
|
+ procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ } else if cs == "?25" {
|
|
|
+ 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 == "?25" {
|
|
|
- var ci consoleCursorInfo
|
|
|
- procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ if cs == "5>" {
|
|
|
+ procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ ci.visible = 1
|
|
|
+ procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
|
|
|
+ } else if cs == "?25" {
|
|
|
+ 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)))
|
|
|
}
|
|
|
}
|
|
|
- return len(data) - w.lastbuf.Len(), nil
|
|
|
+
|
|
|
+ return len(data), nil
|
|
|
}
|
|
|
|
|
|
type consoleColor struct {
|
|
|
@@ -700,22 +860,22 @@ func (c consoleColor) backgroundAttr() (attr word) {
|
|
|
}
|
|
|
|
|
|
var color16 = []consoleColor{
|
|
|
- consoleColor{0x000000, false, false, false, false},
|
|
|
- consoleColor{0x000080, false, false, true, false},
|
|
|
- consoleColor{0x008000, false, true, false, false},
|
|
|
- consoleColor{0x008080, false, true, true, false},
|
|
|
- consoleColor{0x800000, true, false, false, false},
|
|
|
- consoleColor{0x800080, true, false, true, false},
|
|
|
- consoleColor{0x808000, true, true, false, false},
|
|
|
- consoleColor{0xc0c0c0, true, true, true, false},
|
|
|
- consoleColor{0x808080, false, false, false, true},
|
|
|
- consoleColor{0x0000ff, false, false, true, true},
|
|
|
- consoleColor{0x00ff00, false, true, false, true},
|
|
|
- consoleColor{0x00ffff, false, true, true, true},
|
|
|
- consoleColor{0xff0000, true, false, false, true},
|
|
|
- consoleColor{0xff00ff, true, false, true, true},
|
|
|
- consoleColor{0xffff00, true, true, false, true},
|
|
|
- consoleColor{0xffffff, true, true, true, true},
|
|
|
+ {0x000000, false, false, false, false},
|
|
|
+ {0x000080, false, false, true, false},
|
|
|
+ {0x008000, false, true, false, false},
|
|
|
+ {0x008080, false, true, true, false},
|
|
|
+ {0x800000, true, false, false, false},
|
|
|
+ {0x800080, true, false, true, false},
|
|
|
+ {0x808000, true, true, false, false},
|
|
|
+ {0xc0c0c0, true, true, true, false},
|
|
|
+ {0x808080, false, false, false, true},
|
|
|
+ {0x0000ff, false, false, true, true},
|
|
|
+ {0x00ff00, false, true, false, true},
|
|
|
+ {0x00ffff, false, true, true, true},
|
|
|
+ {0xff0000, true, false, false, true},
|
|
|
+ {0xff00ff, true, false, true, true},
|
|
|
+ {0xffff00, true, true, false, true},
|
|
|
+ {0xffffff, true, true, true, true},
|
|
|
}
|
|
|
|
|
|
type hsv struct {
|