barometer: update DMA's vendoring packages
[barometer.git] / src / dma / vendor / github.com / mattn / go-colorable / colorable_windows.go
index e17a547..404e10c 100644 (file)
@@ -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,17 @@ 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
+       rest      bytes.Buffer
 }
 
 // NewColorable return new instance of Writer which handle escape sequence from File.
@@ -407,7 +419,18 @@ 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 {
@@ -425,29 +448,55 @@ loop:
                        break loop
                }
 
-               if c2 == ']' {
-                       if err := doTitleSequence(er); err != nil {
+               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
-               }
-               if c2 != 0x5b {
+               // 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 {
-                               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
+               }
 
                switch m {
                case 'A':
@@ -455,61 +504,64 @@ 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)))
+                       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)))
+                       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 +586,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,20 +597,20 @@ 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}
-                               count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
+                               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 - csbi.cursorPosition.x + (csbi.window.top-csbi.cursorPosition.y)*csbi.size.x)
+                               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 - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
+                               count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*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 'K':
                        n := 0
                        if buf.Len() > 0 {
@@ -567,28 +619,28 @@ 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 {
                        case 0:
-                               cursor = coord{x: csbi.cursorPosition.x + 1, y: csbi.cursorPosition.y}
-                               count = dword(csbi.size.x - csbi.cursorPosition.x - 1)
+                               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)
                        }
-                       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, ";")
@@ -627,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)
                                                }
@@ -654,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)
                                                }
@@ -685,38 +767,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)))
                }
        }