Signed-off-by: Sachin Joshi <sachin_jayant_joshi@hotmail.com>
| ... | ... |
@@ -26,15 +26,15 @@ const ( |
| 26 | 26 |
) |
| 27 | 27 |
|
| 28 | 28 |
func main() {
|
| 29 |
+ if reexec.Init() {
|
|
| 30 |
+ return |
|
| 31 |
+ } |
|
| 32 |
+ |
|
| 29 | 33 |
// Set terminal emulation based on platform as required. |
| 30 | 34 |
stdout, stderr, stdin := term.StdStreams() |
| 31 | 35 |
|
| 32 | 36 |
initLogging(stderr) |
| 33 | 37 |
|
| 34 |
- if reexec.Init() {
|
|
| 35 |
- return |
|
| 36 |
- } |
|
| 37 |
- |
|
| 38 | 38 |
flag.Parse() |
| 39 | 39 |
// FIXME: validate daemon flags here |
| 40 | 40 |
|
| ... | ... |
@@ -83,6 +83,7 @@ const ( |
| 83 | 83 |
|
| 84 | 84 |
ANSI_MAX_CMD_LENGTH = 256 |
| 85 | 85 |
|
| 86 |
+ MAX_INPUT_EVENTS = 128 |
|
| 86 | 87 |
MAX_INPUT_BUFFER = 1024 |
| 87 | 88 |
DEFAULT_WIDTH = 80 |
| 88 | 89 |
DEFAULT_HEIGHT = 24 |
| ... | ... |
@@ -195,15 +196,18 @@ type ( |
| 195 | 195 |
type WindowsTerminal struct {
|
| 196 | 196 |
outMutex sync.Mutex |
| 197 | 197 |
inMutex sync.Mutex |
| 198 |
- inputBuffer chan byte |
|
| 198 |
+ inputBuffer []byte |
|
| 199 |
+ inputSize int |
|
| 200 |
+ inputEvents []INPUT_RECORD |
|
| 199 | 201 |
screenBufferInfo *CONSOLE_SCREEN_BUFFER_INFO |
| 200 | 202 |
inputEscapeSequence []byte |
| 201 | 203 |
} |
| 202 | 204 |
|
| 203 | 205 |
func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
|
| 204 | 206 |
handler := &WindowsTerminal{
|
| 205 |
- inputBuffer: make(chan byte, MAX_INPUT_BUFFER), |
|
| 207 |
+ inputBuffer: make([]byte, MAX_INPUT_BUFFER), |
|
| 206 | 208 |
inputEscapeSequence: []byte(KEY_ESC_CSI), |
| 209 |
+ inputEvents: make([]INPUT_RECORD, MAX_INPUT_EVENTS), |
|
| 207 | 210 |
} |
| 208 | 211 |
|
| 209 | 212 |
// Save current screen buffer info |
| ... | ... |
@@ -218,6 +222,8 @@ func StdStreams() (stdOut io.Writer, stdErr io.Writer, stdIn io.ReadCloser) {
|
| 218 | 218 |
|
| 219 | 219 |
// Set the window size |
| 220 | 220 |
SetWindowSize(uintptr(handle), DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_HEIGHT) |
| 221 |
+ buffer = make([]CHAR_INFO, screenBufferInfo.MaximumWindowSize.X*screenBufferInfo.MaximumWindowSize.Y) |
|
| 222 |
+ |
|
| 221 | 223 |
if IsTerminal(os.Stdout.Fd()) {
|
| 222 | 224 |
stdOut = &terminalWriter{
|
| 223 | 225 |
wrappedWriter: os.Stdout, |
| ... | ... |
@@ -427,6 +433,8 @@ func getNumberOfChars(fromCoord COORD, toCoord COORD, screenSize COORD) uint32 {
|
| 427 | 427 |
return 0 |
| 428 | 428 |
} |
| 429 | 429 |
|
| 430 |
+var buffer []CHAR_INFO |
|
| 431 |
+ |
|
| 430 | 432 |
func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoord COORD, toCoord COORD, windowSize COORD) (bool, uint32, error) {
|
| 431 | 433 |
var writeRegion SMALL_RECT |
| 432 | 434 |
writeRegion.Top = fromCoord.Y |
| ... | ... |
@@ -439,14 +447,13 @@ func clearDisplayRect(fileDesc uintptr, fillChar rune, attributes WORD, fromCoor |
| 439 | 439 |
height := toCoord.Y - fromCoord.Y + 1 |
| 440 | 440 |
size := width * height |
| 441 | 441 |
if size > 0 {
|
| 442 |
- buffer := make([]CHAR_INFO, size) |
|
| 443 |
- for i := 0; i < len(buffer); i++ {
|
|
| 442 |
+ for i := 0; i < int(size); i++ {
|
|
| 444 | 443 |
buffer[i].UnicodeChar = WCHAR(fillChar) |
| 445 | 444 |
buffer[i].Attributes = attributes |
| 446 | 445 |
} |
| 447 | 446 |
|
| 448 | 447 |
// Write to buffer |
| 449 |
- r, err := writeConsoleOutput(fileDesc, buffer, windowSize, COORD{X: 0, Y: 0}, &writeRegion)
|
|
| 448 |
+ r, err := writeConsoleOutput(fileDesc, buffer[:size], windowSize, COORD{X: 0, Y: 0}, &writeRegion)
|
|
| 450 | 449 |
if !r {
|
| 451 | 450 |
if err != nil {
|
| 452 | 451 |
return false, 0, err |
| ... | ... |
@@ -914,6 +921,9 @@ func (term *WindowsTerminal) HandleOutputCommand(fd uintptr, command []byte) (n |
| 914 | 914 |
|
| 915 | 915 |
// WriteChars writes the bytes to given writer. |
| 916 | 916 |
func (term *WindowsTerminal) WriteChars(fd uintptr, w io.Writer, p []byte) (n int, err error) {
|
| 917 |
+ if len(p) == 0 {
|
|
| 918 |
+ return 0, nil |
|
| 919 |
+ } |
|
| 917 | 920 |
return w.Write(p) |
| 918 | 921 |
} |
| 919 | 922 |
|
| ... | ... |
@@ -1049,24 +1059,19 @@ func mapKeystokeToTerminalString(keyEvent *KEY_EVENT_RECORD, escapeSequence []by |
| 1049 | 1049 |
|
| 1050 | 1050 |
// getAvailableInputEvents polls the console for availble events |
| 1051 | 1051 |
// The function does not return until at least one input record has been read. |
| 1052 |
-func getAvailableInputEvents(fd uintptr) (inputEvents []INPUT_RECORD, err error) {
|
|
| 1052 |
+func getAvailableInputEvents(fd uintptr, inputEvents []INPUT_RECORD) (n int, err error) {
|
|
| 1053 | 1053 |
handle := syscall.Handle(fd) |
| 1054 | 1054 |
if nil != err {
|
| 1055 |
- return nil, err |
|
| 1055 |
+ return 0, err |
|
| 1056 | 1056 |
} |
| 1057 | 1057 |
for {
|
| 1058 | 1058 |
// Read number of console events available |
| 1059 |
- tempBuffer := make([]INPUT_RECORD, MAX_INPUT_BUFFER) |
|
| 1060 |
- nr, err := readConsoleInputKey(uintptr(handle), tempBuffer) |
|
| 1059 |
+ nr, err := readConsoleInputKey(uintptr(handle), inputEvents) |
|
| 1061 | 1060 |
if nr == 0 {
|
| 1062 |
- return nil, err |
|
| 1061 |
+ return 0, err |
|
| 1063 | 1062 |
} |
| 1064 | 1063 |
if 0 < nr {
|
| 1065 |
- retValue := make([]INPUT_RECORD, nr) |
|
| 1066 |
- for i := 0; i < nr; i++ {
|
|
| 1067 |
- retValue[i] = tempBuffer[i] |
|
| 1068 |
- } |
|
| 1069 |
- return retValue, nil |
|
| 1064 |
+ return nr, nil |
|
| 1070 | 1065 |
} |
| 1071 | 1066 |
} |
| 1072 | 1067 |
} |
| ... | ... |
@@ -1086,32 +1091,19 @@ func getTranslatedKeyCodes(inputEvents []INPUT_RECORD, escapeSequence []byte) st |
| 1086 | 1086 |
} |
| 1087 | 1087 |
|
| 1088 | 1088 |
// ReadChars reads the characters from the given reader |
| 1089 |
-func (term *WindowsTerminal) ReadChars(fd uintptr, w io.Reader, p []byte) (n int, err error) {
|
|
| 1090 |
- n = 0 |
|
| 1091 |
- for n < len(p) {
|
|
| 1092 |
- select {
|
|
| 1093 |
- case b := <-term.inputBuffer: |
|
| 1094 |
- p[n] = b |
|
| 1095 |
- n++ |
|
| 1096 |
- default: |
|
| 1097 |
- // Read at least one byte read |
|
| 1098 |
- if n > 0 {
|
|
| 1099 |
- return n, nil |
|
| 1100 |
- } |
|
| 1101 |
- inputEvents, _ := getAvailableInputEvents(fd) |
|
| 1102 |
- if inputEvents != nil {
|
|
| 1103 |
- if len(inputEvents) == 0 && nil != err {
|
|
| 1104 |
- return n, err |
|
| 1105 |
- } |
|
| 1106 |
- if len(inputEvents) != 0 {
|
|
| 1107 |
- keyCodes := getTranslatedKeyCodes(inputEvents, term.inputEscapeSequence) |
|
| 1108 |
- for _, b := range []byte(keyCodes) {
|
|
| 1109 |
- term.inputBuffer <- b |
|
| 1110 |
- } |
|
| 1111 |
- } |
|
| 1112 |
- } |
|
| 1089 |
+func (term *WindowsTerminal) ReadChars(fd uintptr, r io.Reader, p []byte) (n int, err error) {
|
|
| 1090 |
+ for term.inputSize == 0 {
|
|
| 1091 |
+ nr, err := getAvailableInputEvents(fd, term.inputEvents) |
|
| 1092 |
+ if nr == 0 && nil != err {
|
|
| 1093 |
+ return n, err |
|
| 1094 |
+ } |
|
| 1095 |
+ if nr > 0 {
|
|
| 1096 |
+ keyCodes := getTranslatedKeyCodes(term.inputEvents[:nr], term.inputEscapeSequence) |
|
| 1097 |
+ term.inputSize = copy(term.inputBuffer, keyCodes) |
|
| 1113 | 1098 |
} |
| 1114 | 1099 |
} |
| 1100 |
+ n = copy(p, term.inputBuffer[:term.inputSize]) |
|
| 1101 |
+ term.inputSize -= n |
|
| 1115 | 1102 |
return n, nil |
| 1116 | 1103 |
} |
| 1117 | 1104 |
|