Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1922)

Delta Between Two Patch Sets: src/pkg/os/file_windows.go

Issue 95780046: code review 95780046: os,syscall: On Windows, recognize Control-Z for console...
Left Patch Set: Created 9 years, 11 months ago
Right Patch Set: diff -r 22dd1c22fd76 https://code.google.com/p/go/ Created 9 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | src/pkg/syscall/syscall_windows.go » ('j') | src/pkg/syscall/syscall_windows.go » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package os 5 package os
6 6
7 import ( 7 import (
8 "io" 8 "io"
9 "runtime" 9 "runtime"
10 "sync" 10 "sync"
(...skipping 14 matching lines...) Expand all
25 // to close the wrong file descriptor. 25 // to close the wrong file descriptor.
26 type file struct { 26 type file struct {
27 fd syscall.Handle 27 fd syscall.Handle
28 name string 28 name string
29 dirinfo *dirInfo // nil unless directory being read 29 dirinfo *dirInfo // nil unless directory being read
30 l sync.Mutex // used to implement windows pread/pwrite 30 l sync.Mutex // used to implement windows pread/pwrite
31 31
32 // only for console io 32 // only for console io
33 isConsole bool 33 isConsole bool
34 lastbits []byte // first few bytes of the last incomplete rune in last write 34 lastbits []byte // first few bytes of the last incomplete rune in last write
35 » readbuf []rune // input console buffer 35 » conInLine string // console input line buffer
minux1 2014/04/27 20:13:59 why use string as buffer? it will very inefficient
36 } 36 }
37 37
38 // Fd returns the Windows handle referencing the open file. 38 // Fd returns the Windows handle referencing the open file.
39 func (file *File) Fd() uintptr { 39 func (file *File) Fd() uintptr {
40 if file == nil { 40 if file == nil {
41 return uintptr(syscall.InvalidHandle) 41 return uintptr(syscall.InvalidHandle)
42 } 42 }
43 return uintptr(file.fd) 43 return uintptr(file.fd)
44 } 44 }
45 45
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 } 238 }
239 n-- 239 n--
240 fi = append(fi, f) 240 fi = append(fi, f)
241 } 241 }
242 if !wantAll && len(fi) == 0 { 242 if !wantAll && len(fi) == 0 {
243 return fi, io.EOF 243 return fi, io.EOF
244 } 244 }
245 return fi, nil 245 return fi, nil
246 } 246 }
247 247
248 const conEOT = 0x1A // For a Windows console, Control-Z is EOT
249
250 // readConsoleLine reads a line of character input from the Windows console inpu t buffer.
251 // Control-Z interrupts and Enter interrupts and ends input for a line.
252 // Enter ("\r\n") is returned as "\n".
253 func (f *File) readConsoleLine() (err error) {
254 if f == nil {
255 return ErrInvalid
256 }
257 f.conInLine = ""
258
259 var mode uint32
260 err = syscall.GetConsoleMode(f.fd, &mode)
261 if err != nil {
262 return err
263 }
264 const plMode = syscall.ENABLE_PROCESSED_INPUT | syscall.ENABLE_LINE_INPU T
265 if mode&plMode != plMode {
266 defer func(mode uint32) {
267 e := syscall.SetConsoleMode(f.fd, mode)
268 if e != nil {
269 err = e
270 f.conInLine = ""
271 }
272 }(mode)
273 err = syscall.SetConsoleMode(f.fd, mode|plMode)
274 if err != nil {
275 return err
276 }
277 }
278
279 var rLine []rune
280 const bufLen = 256 - 1
281 buf := make([]uint16, bufLen, bufLen+1)
282 var nr uint32
283 // Note: CONSOLE_READCONSOLE_CONTROL structure
284 // Minimum support: Windows Vista or Windows Server 2008 [desktop apps o nly].
285 // If not available, Control-Z is buffered until Enter is pressed.
286 crc := syscall.ConsoleReadconsoleControl{
287 Length: 4 * 4,
288 CtrlWakeupMask: 1 << conEOT,
289 }
290 for {
291 // Unicode: ReadConsoleW
292 err := syscall.ReadConsole(f.fd, &buf[0], uint32(bufLen), &nr, & crc)
293 if err != nil {
294 return err
295 }
296 rBuf := utf16.Decode(buf[:nr])
297 if len(rLine) == 0 {
298 rLine = rBuf
299 } else {
300 rLine = append(rLine, rBuf...)
301 }
302 if len(rLine) > 0 {
303 end := len(rLine) - 1
304 if rLine[end] == conEOT {
305 break
306 }
307 if rLine[end] == '\n' {
308 if len(rLine) > 1 {
309 if rLine[end-1] == '\r' {
310 rLine[end-1] = rLine[end]
311 rLine = rLine[:end]
312 }
313 }
314 break
315 }
316 }
317 }
318 f.conInLine = string(rLine)
319 return nil
320 }
321
248 // readConsole reads utf16 characters from console File, 322 // readConsole reads utf16 characters from console File,
249 // encodes them into utf8 and stores them in buffer b. 323 // encodes them into utf8 and stores them in buffer b.
250 // It returns the number of utf8 bytes read and an error, if any. 324 // It returns the number of utf8 bytes read and an error, if any.
325 // For os package portability, the buffer contents match those returned under Li nux,
326 // except for OS dependent control characters and keys.
327 // Control-Z on Windows is the equivalent to Control-D on Linux.
328 // Enter ("\r\n") is returned as "\n".
251 func (f *File) readConsole(b []byte) (n int, err error) { 329 func (f *File) readConsole(b []byte) (n int, err error) {
252 » if len(b) == 0 { 330 » if f == nil {
253 » » return 0, nil 331 » » return 0, ErrInvalid
254 » } 332 » }
255 » if len(f.readbuf) == 0 { 333 » b = b[:0:len(b)]
256 » » // syscall.ReadConsole seems to fail, if given large buffer. 334
257 » » // So limit the buffer to 16000 characters. 335 » if len(f.conInLine) == 0 {
258 » » numBytes := len(b) 336 » » err = f.readConsoleLine()
259 » » if numBytes > 16000 {
260 » » » numBytes = 16000
261 » » }
262 » » // get more input data from os
263 » » wchars := make([]uint16, numBytes)
264 » » var p *uint16
265 » » if len(b) > 0 {
266 » » » p = &wchars[0]
267 » » }
268 » » var nw uint32
269 » » err := syscall.ReadConsole(f.fd, p, uint32(len(wchars)), &nw, ni l)
270 if err != nil { 337 if err != nil {
338 f.conInLine = ""
271 return 0, err 339 return 0, err
272 } 340 }
273 » » f.readbuf = utf16.Decode(wchars[:nw]) 341 » }
274 » } 342
275 » for i, r := range f.readbuf { 343 » i := 0
276 » » if utf8.RuneLen(r) > len(b) { 344 » for i < len(f.conInLine) {
277 » » » f.readbuf = f.readbuf[i:] 345 » » if f.conInLine[i] == conEOT {
278 » » » return n, nil 346 » » » if i == 0 {
279 » » } 347 » » » » f.conInLine = ""
280 » » nr := utf8.EncodeRune(b, r) 348 » » » » return 0, nil // io.EOF
281 » » b = b[nr:] 349 » » » }
282 » » n += nr 350 » » » i++
283 » } 351 » » » if i < len(f.conInLine) && f.conInLine[i] == '\n' {
284 » f.readbuf = nil 352 » » » » i++
285 » return n, nil 353 » » » }
354 » » » break
355 » » }
356 » » if len(b)+1 > cap(b) {
357 » » » break
358 » » }
359 » » b = b[:len(b)+1]
360 » » b[len(b)-1] = f.conInLine[i]
361 » » i++
362 » }
363 » f.conInLine = f.conInLine[i:]
364 » return len(b), nil
286 } 365 }
287 366
288 // read reads up to len(b) bytes from the File. 367 // read reads up to len(b) bytes from the File.
289 // It returns the number of bytes read and an error, if any. 368 // It returns the number of bytes read and an error, if any.
290 func (f *File) read(b []byte) (n int, err error) { 369 func (f *File) read(b []byte) (n int, err error) {
291 f.l.Lock() 370 f.l.Lock()
292 defer f.l.Unlock() 371 defer f.l.Unlock()
293 if f.isConsole { 372 if f.isConsole {
294 return f.readConsole(b) 373 return f.readConsole(b)
295 } 374 }
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0]) 565 n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
487 if n > uint32(len(dirw)) { 566 if n > uint32(len(dirw)) {
488 n = 0 567 n = 0
489 } 568 }
490 } 569 }
491 if n > 0 && dirw[n-1] == pathSep { 570 if n > 0 && dirw[n-1] == pathSep {
492 n-- 571 n--
493 } 572 }
494 return string(utf16.Decode(dirw[0:n])) 573 return string(utf16.Decode(dirw[0:n]))
495 } 574 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b