From dcdd3e749a4f0a4f1e3608379c6bcf35dfc311ce Mon Sep 17 00:00:00 2001 From: Dmytro Maluka Date: Wed, 13 Mar 2024 21:11:04 +0100 Subject: [PATCH] Fix ruler overwriting neighboring split pane + fix crash #3052 (#3069) * Fix gutter overwriting other split pane When we resize a split pane to a very small width, so that the gutter does not fit in the pane, it overwrites the sibling split pane. To fix it, clean up the calculation of gutter width, buffer width and scrollbar width, so that they add up exactly to the window width, and ensure that we don't draw the gutter beyond this calculated gutter width (gutterOffset). As a bonus, this also fixes the crash #3052 (observed when resizing a split pane to a very small width, if wordwrap is enabled), by ensuring that bufWidth is never negative. [*] By the gutter we mean of course gutter + diffgutter + ruler. * Don't display line numbers if buffer width is 0 and softwrap is on If softwrap is enabled, the line numbers displayed in the ruler depend on the heights of the displayed softwrapped lines, which depend on the width of the displayed buffer. If this width is 0 (e.g. after resizing buffer pane to a very small width), there is no displayed text at all, so line numbers don't make sense. So don't display line numbers in this case. * Fix buffer text overwriting scrollbar when window width is 1 char --- internal/display/bufwindow.go | 45 ++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/internal/display/bufwindow.go b/internal/display/bufwindow.go index bca6bf8e..6e67f845 100644 --- a/internal/display/bufwindow.go +++ b/internal/display/bufwindow.go @@ -129,6 +129,11 @@ func (w *BufWindow) updateDisplayInfo() { w.bufHeight-- } + scrollbarWidth := 0 + if w.Buf.Settings["scrollbar"].(bool) && w.Buf.LinesNum() > w.Height && w.Width > 0 { + scrollbarWidth = 1 + } + w.hasMessage = len(b.Messages) > 0 // We need to know the string length of the largest line number @@ -146,13 +151,13 @@ func (w *BufWindow) updateDisplayInfo() { w.gutterOffset += w.maxLineNumLength + 1 } - prevBufWidth := w.bufWidth - - w.bufWidth = w.Width - w.gutterOffset - if w.Buf.Settings["scrollbar"].(bool) && w.Buf.LinesNum() > w.Height { - w.bufWidth-- + if w.gutterOffset > w.Width-scrollbarWidth { + w.gutterOffset = w.Width - scrollbarWidth } + prevBufWidth := w.bufWidth + w.bufWidth = w.Width - w.gutterOffset - scrollbarWidth + if w.bufWidth != prevBufWidth && w.Buf.Settings["softwrap"].(bool) { for _, c := range w.Buf.GetCursors() { c.LastVisualX = c.GetVisualX() @@ -277,13 +282,17 @@ func (w *BufWindow) drawGutter(vloc *buffer.Loc, bloc *buffer.Loc) { break } } - screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, char, nil, s) - vloc.X++ - screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, char, nil, s) - vloc.X++ + for i := 0; i < 2 && vloc.X < w.gutterOffset; i++ { + screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, char, nil, s) + vloc.X++ + } } func (w *BufWindow) drawDiffGutter(backgroundStyle tcell.Style, softwrapped bool, vloc *buffer.Loc, bloc *buffer.Loc) { + if vloc.X >= w.gutterOffset { + return + } + symbol := ' ' styleName := "" @@ -319,26 +328,28 @@ func (w *BufWindow) drawLineNum(lineNumStyle tcell.Style, softwrapped bool, vloc } else { lineInt = bloc.Y - cursorLine } - lineNum := strconv.Itoa(util.Abs(lineInt)) + lineNum := []rune(strconv.Itoa(util.Abs(lineInt))) // Write the spaces before the line number if necessary - for i := 0; i < w.maxLineNumLength-len(lineNum); i++ { + for i := 0; i < w.maxLineNumLength-len(lineNum) && vloc.X < w.gutterOffset; i++ { screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, ' ', nil, lineNumStyle) vloc.X++ } // Write the actual line number - for _, ch := range lineNum { - if softwrapped { + for i := 0; i < len(lineNum) && vloc.X < w.gutterOffset; i++ { + if softwrapped || (w.bufWidth == 0 && w.Buf.Settings["softwrap"] == true) { screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, ' ', nil, lineNumStyle) } else { - screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, ch, nil, lineNumStyle) + screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, lineNum[i], nil, lineNumStyle) } vloc.X++ } // Write the extra space - screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, ' ', nil, lineNumStyle) - vloc.X++ + if vloc.X < w.gutterOffset { + screen.SetContent(w.X+vloc.X, w.Y+vloc.Y, ' ', nil, lineNumStyle) + vloc.X++ + } } // getStyle returns the highlight style for the given character position @@ -619,7 +630,7 @@ func (w *BufWindow) displayBuffer() { wordwidth := 0 totalwidth := w.StartCol - nColsBeforeStart - for len(line) > 0 { + for len(line) > 0 && vloc.X < maxWidth { r, combc, size := util.DecodeCharacter(line) line = line[size:]