|
|
|
@ -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 |
|
|
|
|
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,100 +445,133 @@ 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 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var buf bytes.Buffer |
|
|
|
|
var m byte |
|
|
|
|
for { |
|
|
|
|
c, err := er.ReadByte() |
|
|
|
|
er = bytes.NewReader(w.rest.Bytes()[2:]) |
|
|
|
|
err := doTitleSequence(er) |
|
|
|
|
if err != nil { |
|
|
|
|
w.lastbuf.WriteByte(c1) |
|
|
|
|
w.lastbuf.WriteByte(c2) |
|
|
|
|
w.lastbuf.Write(buf.Bytes()) |
|
|
|
|
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 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': |
|
|
|
|
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(), ";") |
|
|
|
|
if len(token) != 2 { |
|
|
|
|
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 |
|
|
|
@ -489,51 +582,65 @@ loop: |
|
|
|
|
} |
|
|
|
|
csbi.cursorPosition.x = short(n2 - 1) |
|
|
|
|
csbi.cursorPosition.y = short(n1 - 1) |
|
|
|
|
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
csbi.cursorPosition.y = 0 |
|
|
|
|
} |
|
|
|
|
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) |
|
|
|
|
case 'J': |
|
|
|
|
n, err := strconv.Atoi(buf.String()) |
|
|
|
|
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()) |
|
|
|
|
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': |
|
|
|
|
cs := buf.String() |
|
|
|
|
if cs == "?25" { |
|
|
|
|
var ci consoleCursorInfo |
|
|
|
|
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) |
|
|
|
|
cs := buf.String() |
|
|
|
|
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': |
|
|
|
|
cs := buf.String() |
|
|
|
|
if cs == "?25" { |
|
|
|
|
var ci consoleCursorInfo |
|
|
|
|
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) |
|
|
|
|
cs := buf.String() |
|
|
|
|
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 { |
|
|
|
|