| // +build windows |
| |
| package winterm |
| |
| // effectiveSr gets the current effective scroll region in buffer coordinates |
| func (h *windowsAnsiEventHandler) effectiveSr(window SMALL_RECT) scrollRegion { |
| top := addInRange(window.Top, h.sr.top, window.Top, window.Bottom) |
| bottom := addInRange(window.Top, h.sr.bottom, window.Top, window.Bottom) |
| if top >= bottom { |
| top = window.Top |
| bottom = window.Bottom |
| } |
| return scrollRegion{top: top, bottom: bottom} |
| } |
| |
| func (h *windowsAnsiEventHandler) scrollUp(param int) error { |
| info, err := GetConsoleScreenBufferInfo(h.fd) |
| if err != nil { |
| return err |
| } |
| |
| sr := h.effectiveSr(info.Window) |
| return h.scroll(param, sr, info) |
| } |
| |
| func (h *windowsAnsiEventHandler) scrollDown(param int) error { |
| return h.scrollUp(-param) |
| } |
| |
| func (h *windowsAnsiEventHandler) deleteLines(param int) error { |
| info, err := GetConsoleScreenBufferInfo(h.fd) |
| if err != nil { |
| return err |
| } |
| |
| start := info.CursorPosition.Y |
| sr := h.effectiveSr(info.Window) |
| // Lines cannot be inserted or deleted outside the scrolling region. |
| if start >= sr.top && start <= sr.bottom { |
| sr.top = start |
| return h.scroll(param, sr, info) |
| } else { |
| return nil |
| } |
| } |
| |
| func (h *windowsAnsiEventHandler) insertLines(param int) error { |
| return h.deleteLines(-param) |
| } |
| |
| // scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates. |
| func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error { |
| h.logf("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom) |
| h.logf("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom) |
| |
| // Copy from and clip to the scroll region (full buffer width) |
| scrollRect := SMALL_RECT{ |
| Top: sr.top, |
| Bottom: sr.bottom, |
| Left: 0, |
| Right: info.Size.X - 1, |
| } |
| |
| // Origin to which area should be copied |
| destOrigin := COORD{ |
| X: 0, |
| Y: sr.top - int16(param), |
| } |
| |
| char := CHAR_INFO{ |
| UnicodeChar: ' ', |
| Attributes: h.attributes, |
| } |
| |
| if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { |
| return err |
| } |
| return nil |
| } |
| |
| func (h *windowsAnsiEventHandler) deleteCharacters(param int) error { |
| info, err := GetConsoleScreenBufferInfo(h.fd) |
| if err != nil { |
| return err |
| } |
| return h.scrollLine(param, info.CursorPosition, info) |
| } |
| |
| func (h *windowsAnsiEventHandler) insertCharacters(param int) error { |
| return h.deleteCharacters(-param) |
| } |
| |
| // scrollLine scrolls a line horizontally starting at the provided position by a number of columns. |
| func (h *windowsAnsiEventHandler) scrollLine(columns int, position COORD, info *CONSOLE_SCREEN_BUFFER_INFO) error { |
| // Copy from and clip to the scroll region (full buffer width) |
| scrollRect := SMALL_RECT{ |
| Top: position.Y, |
| Bottom: position.Y, |
| Left: position.X, |
| Right: info.Size.X - 1, |
| } |
| |
| // Origin to which area should be copied |
| destOrigin := COORD{ |
| X: position.X - int16(columns), |
| Y: position.Y, |
| } |
| |
| char := CHAR_INFO{ |
| UnicodeChar: ' ', |
| Attributes: h.attributes, |
| } |
| |
| if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { |
| return err |
| } |
| return nil |
| } |