Skip to content

Commit ecf528f

Browse files
rootjstarks
authored andcommitted
Update vendored go-ansiterm for Windows console
This update fixes Windows client console bugs and increases VT100 compatibility. With this change, nano and emacs become usable, and bash works better. Signed-off-by: John Starks <jostarks@microsoft.com>
1 parent b909463 commit ecf528f

File tree

11 files changed

+609
-179
lines changed

11 files changed

+609
-179
lines changed

hack/vendor.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ rm -rf vendor/
66
source 'hack/.vendor-helpers.sh'
77

88
# the following lines are in sorted order, FYI
9-
clone git github.com/Azure/go-ansiterm 0a9ca7117fc3e5629da85238ede560cb5e749783
9+
clone git github.com/Azure/go-ansiterm 70b2c90b260171e829f1ebd7c17f600c11858dbe
1010
clone git github.com/Sirupsen/logrus v0.8.2 # logrus is a common dependency among multiple deps
1111
clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
1212
clone git github.com/go-check/check 64131543e7896d5bcc6bd5a76287eb75ea96c673

vendor/src/github.com/Azure/go-ansiterm/constants.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,11 @@ const (
7777
DEFAULT_HEIGHT = 24
7878

7979
ANSI_BEL = 0x07
80+
ANSI_BACKSPACE = 0x08
81+
ANSI_TAB = 0x09
8082
ANSI_LINE_FEED = 0x0A
83+
ANSI_VERTICAL_TAB = 0x0B
84+
ANSI_FORM_FEED = 0x0C
8185
ANSI_CARRIAGE_RETURN = 0x0D
8286
ANSI_ESCAPE_PRIMARY = 0x1B
8387
ANSI_ESCAPE_SECONDARY = 0x5B

vendor/src/github.com/Azure/go-ansiterm/event_handler.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ type AnsiEventHandler interface {
2828
// Cursor Horizontal position Absolute
2929
CHA(int) error
3030

31+
// Vertical line Position Absolute
32+
VPA(int) error
33+
3134
// CUrsor Position
3235
CUP(int, int) error
3336

@@ -37,6 +40,12 @@ type AnsiEventHandler interface {
3740
// Text Cursor Enable Mode
3841
DECTCEM(bool) error
3942

43+
// Origin Mode
44+
DECOM(bool) error
45+
46+
// 132 Column Mode
47+
DECCOLM(bool) error
48+
4049
// Erase in Display
4150
ED(int) error
4251

@@ -49,6 +58,12 @@ type AnsiEventHandler interface {
4958
// Delete Line
5059
DL(int) error
5160

61+
// Insert Character
62+
ICH(int) error
63+
64+
// Delete Character
65+
DCH(int) error
66+
5267
// Set Graphics Rendition
5368
SGR([]int) error
5469

@@ -64,6 +79,9 @@ type AnsiEventHandler interface {
6479
// Set Top and Bottom Margins
6580
DECSTBM(int, int) error
6681

82+
// Index
83+
IND() error
84+
6785
// Reverse Index
6886
RI() error
6987

vendor/src/github.com/Azure/go-ansiterm/parser_action_helpers.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,29 @@ func getInts(params []string, minCount int, dflt int) []int {
6565
return ints
6666
}
6767

68+
func (ap *AnsiParser) modeDispatch(param string, set bool) error {
69+
switch param {
70+
case "?3":
71+
return ap.eventHandler.DECCOLM(set)
72+
case "?6":
73+
return ap.eventHandler.DECOM(set)
74+
case "?25":
75+
return ap.eventHandler.DECTCEM(set)
76+
}
77+
return nil
78+
}
79+
6880
func (ap *AnsiParser) hDispatch(params []string) error {
69-
if len(params) == 1 && params[0] == "?25" {
70-
return ap.eventHandler.DECTCEM(true)
81+
if len(params) == 1 {
82+
return ap.modeDispatch(params[0], true)
7183
}
7284

7385
return nil
7486
}
7587

7688
func (ap *AnsiParser) lDispatch(params []string) error {
77-
if len(params) == 1 && params[0] == "?25" {
78-
return ap.eventHandler.DECTCEM(false)
89+
if len(params) == 1 {
90+
return ap.modeDispatch(params[0], false)
7991
}
8092

8193
return nil

vendor/src/github.com/Azure/go-ansiterm/parser_actions.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,15 @@ func (ap *AnsiParser) escDispatch() error {
2525
logger.Infof("escDispatch: %v(%v)", cmd, intermeds)
2626

2727
switch cmd {
28-
case "M":
28+
case "D": // IND
29+
return ap.eventHandler.IND()
30+
case "E": // NEL, equivalent to CRLF
31+
err := ap.eventHandler.Execute(ANSI_CARRIAGE_RETURN)
32+
if err == nil {
33+
err = ap.eventHandler.Execute(ANSI_LINE_FEED)
34+
}
35+
return err
36+
case "M": // RI
2937
return ap.eventHandler.RI()
3038
}
3139

@@ -39,6 +47,8 @@ func (ap *AnsiParser) csiDispatch() error {
3947
logger.Infof("csiDispatch: %v(%v)", cmd, params)
4048

4149
switch cmd {
50+
case "@":
51+
return ap.eventHandler.ICH(getInt(params, 1))
4252
case "A":
4353
return ap.eventHandler.CUU(getInt(params, 1))
4454
case "B":
@@ -67,12 +77,16 @@ func (ap *AnsiParser) csiDispatch() error {
6777
return ap.eventHandler.IL(getInt(params, 1))
6878
case "M":
6979
return ap.eventHandler.DL(getInt(params, 1))
80+
case "P":
81+
return ap.eventHandler.DCH(getInt(params, 1))
7082
case "S":
7183
return ap.eventHandler.SU(getInt(params, 1))
7284
case "T":
7385
return ap.eventHandler.SD(getInt(params, 1))
7486
case "c":
7587
return ap.eventHandler.DA(params)
88+
case "d":
89+
return ap.eventHandler.VPA(getInt(params, 1))
7690
case "f":
7791
ints := getInts(params, 2, 1)
7892
x, y := ints[0], ints[1]

vendor/src/github.com/Azure/go-ansiterm/test_event_handler.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ func (h *TestAnsiEventHandler) CHA(param int) error {
6565
return nil
6666
}
6767

68+
func (h *TestAnsiEventHandler) VPA(param int) error {
69+
h.recordCall("VPA", []string{strconv.Itoa(param)})
70+
return nil
71+
}
72+
6873
func (h *TestAnsiEventHandler) CUP(x int, y int) error {
6974
xS, yS := strconv.Itoa(x), strconv.Itoa(y)
7075
h.recordCall("CUP", []string{xS, yS})
@@ -82,6 +87,16 @@ func (h *TestAnsiEventHandler) DECTCEM(visible bool) error {
8287
return nil
8388
}
8489

90+
func (h *TestAnsiEventHandler) DECOM(visible bool) error {
91+
h.recordCall("DECOM", []string{strconv.FormatBool(visible)})
92+
return nil
93+
}
94+
95+
func (h *TestAnsiEventHandler) DECCOLM(use132 bool) error {
96+
h.recordCall("DECOLM", []string{strconv.FormatBool(use132)})
97+
return nil
98+
}
99+
85100
func (h *TestAnsiEventHandler) ED(param int) error {
86101
h.recordCall("ED", []string{strconv.Itoa(param)})
87102
return nil
@@ -102,6 +117,16 @@ func (h *TestAnsiEventHandler) DL(param int) error {
102117
return nil
103118
}
104119

120+
func (h *TestAnsiEventHandler) ICH(param int) error {
121+
h.recordCall("ICH", []string{strconv.Itoa(param)})
122+
return nil
123+
}
124+
125+
func (h *TestAnsiEventHandler) DCH(param int) error {
126+
h.recordCall("DCH", []string{strconv.Itoa(param)})
127+
return nil
128+
}
129+
105130
func (h *TestAnsiEventHandler) SGR(params []int) error {
106131
strings := []string{}
107132
for _, v := range params {
@@ -138,6 +163,11 @@ func (h *TestAnsiEventHandler) RI() error {
138163
return nil
139164
}
140165

166+
func (h *TestAnsiEventHandler) IND() error {
167+
h.recordCall("IND", nil)
168+
return nil
169+
}
170+
141171
func (h *TestAnsiEventHandler) Flush() error {
142172
return nil
143173
}

vendor/src/github.com/Azure/go-ansiterm/winterm/ansi.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"strings"
1010
"syscall"
1111

12-
. "github.com/docker/docker/vendor/src/github.com/Azure/go-ansiterm"
12+
. "github.com/Azure/go-ansiterm"
1313
)
1414

1515
// Windows keyboard constants

vendor/src/github.com/Azure/go-ansiterm/winterm/attr_translation.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const (
1313

1414
// collectAnsiIntoWindowsAttributes modifies the passed Windows text mode flags to reflect the
1515
// request represented by the passed ANSI mode.
16-
func collectAnsiIntoWindowsAttributes(windowsMode WORD, baseMode WORD, ansiMode SHORT) WORD {
16+
func collectAnsiIntoWindowsAttributes(windowsMode WORD, inverted bool, baseMode WORD, ansiMode SHORT) (WORD, bool) {
1717
switch ansiMode {
1818

1919
// Mode styles
@@ -26,9 +26,11 @@ func collectAnsiIntoWindowsAttributes(windowsMode WORD, baseMode WORD, ansiMode
2626
case ANSI_SGR_UNDERLINE:
2727
windowsMode = windowsMode | COMMON_LVB_UNDERSCORE
2828

29-
case ANSI_SGR_REVERSE, ANSI_SGR_REVERSE_OFF:
30-
// Note: Windows does not support a native reverse. Simply swap the foreground / background color / intensity.
31-
windowsMode = (COMMON_LVB_MASK & windowsMode) | ((FOREGROUND_MASK & windowsMode) << 4) | ((BACKGROUND_MASK & windowsMode) >> 4)
29+
case ANSI_SGR_REVERSE:
30+
inverted = true
31+
32+
case ANSI_SGR_REVERSE_OFF:
33+
inverted = false
3234

3335
case ANSI_SGR_UNDERLINE_OFF:
3436
windowsMode &^= COMMON_LVB_UNDERSCORE
@@ -91,5 +93,10 @@ func collectAnsiIntoWindowsAttributes(windowsMode WORD, baseMode WORD, ansiMode
9193
windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
9294
}
9395

94-
return windowsMode
96+
return windowsMode, inverted
97+
}
98+
99+
// invertAttributes inverts the foreground and background colors of a Windows attributes value
100+
func invertAttributes(windowsMode WORD) WORD {
101+
return (COMMON_LVB_MASK & windowsMode) | ((FOREGROUND_MASK & windowsMode) << 4) | ((BACKGROUND_MASK & windowsMode) >> 4)
95102
}

vendor/src/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,35 @@ const (
77
Vertical
88
)
99

10-
// setCursorPosition sets the cursor to the specified position, bounded to the buffer size
11-
func (h *WindowsAnsiEventHandler) setCursorPosition(position COORD, sizeBuffer COORD) error {
12-
position.X = ensureInRange(position.X, 0, sizeBuffer.X-1)
13-
position.Y = ensureInRange(position.Y, 0, sizeBuffer.Y-1)
14-
return SetConsoleCursorPosition(h.fd, position)
10+
func (h *WindowsAnsiEventHandler) getCursorWindow(info *CONSOLE_SCREEN_BUFFER_INFO) SMALL_RECT {
11+
if h.originMode {
12+
sr := h.effectiveSr(info.Window)
13+
return SMALL_RECT{
14+
Top: sr.top,
15+
Bottom: sr.bottom,
16+
Left: 0,
17+
Right: info.Size.X - 1,
18+
}
19+
} else {
20+
return SMALL_RECT{
21+
Top: info.Window.Top,
22+
Bottom: info.Window.Bottom,
23+
Left: 0,
24+
Right: info.Size.X - 1,
25+
}
26+
}
27+
}
28+
29+
// setCursorPosition sets the cursor to the specified position, bounded to the screen size
30+
func (h *WindowsAnsiEventHandler) setCursorPosition(position COORD, window SMALL_RECT) error {
31+
position.X = ensureInRange(position.X, window.Left, window.Right)
32+
position.Y = ensureInRange(position.Y, window.Top, window.Bottom)
33+
err := SetConsoleCursorPosition(h.fd, position)
34+
if err != nil {
35+
return err
36+
}
37+
logger.Infof("Cursor position set: (%d, %d)", position.X, position.Y)
38+
return err
1539
}
1640

1741
func (h *WindowsAnsiEventHandler) moveCursorVertical(param int) error {
@@ -31,17 +55,15 @@ func (h *WindowsAnsiEventHandler) moveCursor(moveMode int, param int) error {
3155
position := info.CursorPosition
3256
switch moveMode {
3357
case Horizontal:
34-
position.X = AddInRange(position.X, SHORT(param), info.Window.Left, info.Window.Right)
58+
position.X += SHORT(param)
3559
case Vertical:
36-
position.Y = AddInRange(position.Y, SHORT(param), info.Window.Top, info.Window.Bottom)
60+
position.Y += SHORT(param)
3761
}
3862

39-
if err = h.setCursorPosition(position, info.Size); err != nil {
63+
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
4064
return err
4165
}
4266

43-
logger.Infof("Cursor position set: (%d, %d)", position.X, position.Y)
44-
4567
return nil
4668
}
4769

@@ -53,9 +75,9 @@ func (h *WindowsAnsiEventHandler) moveCursorLine(param int) error {
5375

5476
position := info.CursorPosition
5577
position.X = 0
56-
position.Y = AddInRange(position.Y, SHORT(param), info.Window.Top, info.Window.Bottom)
78+
position.Y += SHORT(param)
5779

58-
if err = h.setCursorPosition(position, info.Size); err != nil {
80+
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
5981
return err
6082
}
6183

@@ -69,9 +91,9 @@ func (h *WindowsAnsiEventHandler) moveCursorColumn(param int) error {
6991
}
7092

7193
position := info.CursorPosition
72-
position.X = AddInRange(SHORT(param), -1, info.Window.Left, info.Window.Right)
94+
position.X = SHORT(param) - 1
7395

74-
if err = h.setCursorPosition(position, info.Size); err != nil {
96+
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
7597
return err
7698
}
7799

0 commit comments

Comments
 (0)