forked from ebhomengo/niki
119 lines
3.1 KiB
Go
119 lines
3.1 KiB
Go
|
// +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
|
||
|
}
|