Skip to content

Commit

Permalink
[WIP] Grid system refactor.
Browse files Browse the repository at this point in the history
  • Loading branch information
christianparpart committed Aug 1, 2021
1 parent 31f06c9 commit 44e2297
Show file tree
Hide file tree
Showing 41 changed files with 2,079 additions and 1,911 deletions.
6 changes: 3 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Current PR (box drawings)
# Current PR

- [ ] maxHistoryLineCount cannot be "unlimited" anymore.

- [ ] `builtin_box_drawing: false` ignored? check!
- [ ] top-left and bottom-left arc show artifacts on very left side. why? most likely overflow in pixel painting.

# RELEASE CHECKLIST

Expand Down
2 changes: 1 addition & 1 deletion autogen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ exec cmake "${ROOTDIR}" \
-DCONTOUR_COVERAGE="OFF" \
-DCONTOUR_PERF_STATS="ON" \
-DCONTOUR_BLUR_PLATFORM_KWIN="ON" \
-GNinja
#-GNinja

89 changes: 89 additions & 0 deletions docs/grid-redesign.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Grid (re)design

## grid properties

- line and column positions are given in offsets (0-based indices!)
- grid cells of the full scrollback + main page area are stored in dense linear space
- `Line` is just a view into the ring buffer
- logical lines above main page area's line count cannot be edited
- scroll offset represents the *bottom* line of the viewport.
- maybe make scroll offset negative (to have all ops being additions)

## corollary

- the VT screen line/column position to offset translation (minus 1)
happens as early as possible in the `Sequencer`.
- `Line::Wrapped`-flag can be removed.
- writing an overlong line does not need to care about auto-wrapping
- because `lineLength / pageWidth == numberOfLinesWriten`
- the new cursor position can be computed analogous to the above
- because of the meaning of the scroll-offset, reflow can be O(1) implemented
with a `Line()` being arbitrary long(!) and the top screen line being
computed by subtracting `(PageLineCount - 1) * PageColumnCount)`,
then *just* lineary walking forward until the bottom right.
- this enables relative jumps (`CUU` etc) to jump up logical lines.
- we could make the cursor jump behavior configurable, via DEC mode.
- On char write overflow
- if Reflow DEC mode is enabled, then continue appending character
- else if AutoWrap DEC mode is enabled, then linefeed()
- else overwrite character on right margin
- I think with the above approach we do not need DEC mode 2027 for disabling
reflow in order to protect command prompts. as they're automatically protected
by the grid line architecture.

### Notes

Suppose only a single overly long line is written and ocupies the full screen
(many page counts).

```
bottomRightOffset = line(cursor.line + realOffset(scrollOffset_)).right_offset;
topLeftOffset = bottomRightOffset - pageSize.lines * pageSize.columns;
def renderViewport():
{
for (auto i = topLeftOffset, k = 0; i < bottomRightOffset; ++i, ++k)
{
auto rowNr = k / pageSize.columns;
auto colNr = k % pageSize.columns;
renderCell(buffer_[i], rowNr, colNr);
}
}
```

## shrink columns

page size: 6x2
lines: 2
line.1: 0..5 abcdef
line.2: 6..11 ABCDEF

shrink to pageSize: 4x2

line.1: 0..3 abcd
line.2: 4..5 ef Wrapped
line.3: 6..9 ABCD
line.4: 10..11 EF Wrapped

Shrinking does not destroy, as it always reflows.
`CUU` will move by logical line numbers.

## overlong lines

4x2


line.1 ABCDEFabcdef
line.2 ABCD

view:

history.line.-1 ABCD
history.line.0 EFAB
logical.line.1 cdef
logical.line.2 ABCD

## Rendering a wrapped line

- the scroll-offset represents the number of real lines scrolled up
-
6 changes: 3 additions & 3 deletions src/contour/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1181,10 +1181,10 @@ TerminalProfile loadTerminalProfile(UsedKeys& _usedKeys,
else
errorlog().write("Invalid render_mode \"{}\" in configuration.", renderModeStr);

auto intValue = profile.maxHistoryLineCount.value_or(std::numeric_limits<LineCount>::max());
auto intValue = profile.maxHistoryLineCount;
tryLoadChild(_usedKeys, _doc, basePath, "history.limit", intValue);
if (unbox<int>(intValue) < 0 || intValue == std::numeric_limits<LineCount>::max())
profile.maxHistoryLineCount = nullopt;
if (unbox<int>(intValue) < 0)
profile.maxHistoryLineCount = LineCount(0);
else
profile.maxHistoryLineCount = intValue;

Expand Down
2 changes: 1 addition & 1 deletion src/contour/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ struct TerminalProfile {
terminal::PageSize terminalSize = {terminal::LineCount(10), terminal::ColumnCount(40)};
terminal::VTType terminalId = terminal::VTType::VT525;

std::optional<terminal::LineCount> maxHistoryLineCount;
terminal::LineCount maxHistoryLineCount;
terminal::LineCount historyScrollMultiplier;
ScrollBarPosition scrollbarPosition = ScrollBarPosition::Right;
bool hideScrollbarInAltScreen = true;
Expand Down
2 changes: 1 addition & 1 deletion src/contour/TerminalSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ void TerminalSession::operator()(actions::FollowHyperlink)
auto const _l = scoped_lock{terminal()};
auto const currentMousePosition = terminal().currentMousePosition();
auto const currentMousePositionRel = terminal::Coordinate{
currentMousePosition.row - terminal().viewport().relativeScrollOffset().as<int>(),
currentMousePosition.row + terminal().viewport().scrollOffset().as<LineOffset>(),
currentMousePosition.column
};
if (terminal().screen().contains(currentMousePosition))
Expand Down
6 changes: 3 additions & 3 deletions src/contour/TerminalWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ void ScrollableDisplay::updateValues()
return;

scrollBar_->setMaximum(session_.terminal().screen().historyLineCount().as<int>());
if (auto const s = session_.terminal().viewport().absoluteScrollOffset(); s.has_value())
scrollBar_->setValue(s.value().as<int>());
if (auto const s = session_.terminal().viewport().scrollOffset(); s.value)
scrollBar_->setValue(s.value);
else
scrollBar_->setValue(scrollBar_->maximum());
}
Expand Down Expand Up @@ -196,7 +196,7 @@ void ScrollableDisplay::updatePosition()

void ScrollableDisplay::onValueChanged()
{
session_.terminal().viewport().scrollToAbsolute(terminal::StaticScrollbackPosition(scrollBar_->value()));
session_.terminal().viewport().scrollTo(terminal::ScrollOffset::cast_from(scrollBar_->value()));
session_.scheduleRedraw();
}
#endif // }}}
Expand Down
2 changes: 1 addition & 1 deletion src/contour/opengl/TerminalWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ void TerminalWidget::assertInitialized()

void TerminalWidget::onScrollBarValueChanged(int _value)
{
terminal().viewport().scrollToAbsolute(terminal::StaticScrollbackPosition::cast_from(_value));
terminal().viewport().scrollTo(terminal::ScrollOffset::cast_from(_value));
scheduleRedraw();
}

Expand Down
13 changes: 9 additions & 4 deletions src/crispy/boxed.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ template <typename T, typename Tag> struct boxed
}
};

template <typename T, typename U> constexpr T& operator++(boxed<T, U>& a) noexcept { ++a.value; return a; }
template <typename T, typename U> constexpr T& operator++(boxed<T, U>& a, int) noexcept { a.value++; return a; }
template <typename T, typename U> constexpr T& operator--(boxed<T, U>& a) noexcept { --a.value; return a; }
template <typename T, typename U> constexpr T& operator--(boxed<T, U>& a, int) noexcept { a.value--; return a; }
template <typename T, typename U> constexpr boxed<T, U>& operator++(boxed<T, U>& a) noexcept { ++a.value; return a; }
template <typename T, typename U> constexpr boxed<T, U>& operator++(boxed<T, U>& a, int) noexcept { a.value++; return a; }
template <typename T, typename U> constexpr boxed<T, U>& operator--(boxed<T, U>& a) noexcept { --a.value; return a; }
template <typename T, typename U> constexpr boxed<T, U>& operator--(boxed<T, U>& a, int) noexcept { a.value--; return a; }
template <typename T, typename U> constexpr T const& operator*(boxed<T, U> const& a) noexcept { return a.value; }
template <typename T, typename U> constexpr bool operator<(boxed<T, U> const& a, boxed<T, U> const& b) noexcept { return a.value < b.value; }
template <typename T, typename U> constexpr bool operator>(boxed<T, U> const& a, boxed<T, U> const& b) noexcept { return a.value > b.value; }
Expand All @@ -102,6 +102,10 @@ template <typename T, typename U> constexpr boxed<T, U> operator+(boxed<T, U> co
template <typename T, typename U> constexpr boxed<T, U> operator-(boxed<T, U> const& a, boxed<T, U> const& b) noexcept { return boxed<T, U>{a.value - b.value}; }
template <typename T, typename U> constexpr boxed<T, U> operator*(boxed<T, U> const& a, boxed<T, U> const& b) noexcept { return boxed<T, U>{a.value * b.value}; }
template <typename T, typename U> constexpr boxed<T, U> operator/(boxed<T, U> const& a, boxed<T, U> const& b) noexcept { return boxed<T, U>{a.value / b.value}; }
template <typename T, typename U> constexpr boxed<T, U> operator%(boxed<T, U> const& a, boxed<T, U> const& b) noexcept { return boxed<T, U>{a.value % b.value}; }

template <typename T, typename U> constexpr boxed<T, U> operator-(boxed<T, U> const& a) noexcept { return boxed<T, U>{-a.value}; }
template <typename T, typename U> constexpr boxed<T, U> operator+(boxed<T, U> const& a) noexcept { return boxed<T, U>{+a.value}; }

template <typename T, typename U> constexpr boxed<T, U> operator+(boxed<T, U> const& a, T b) noexcept { return boxed<T, U>{a.value + b}; }
template <typename T, typename U> constexpr boxed<T, U> operator-(boxed<T, U> const& a, T b) noexcept { return boxed<T, U>{a.value - b}; }
Expand All @@ -112,6 +116,7 @@ template <typename T, typename U> constexpr boxed<T, U>& operator+=(boxed<T, U>&
template <typename T, typename U> constexpr boxed<T, U>& operator-=(boxed<T, U>& a, boxed<T, U> const& b) noexcept { a.value -= b.value; return a; }
template <typename T, typename U> constexpr boxed<T, U>& operator*=(boxed<T, U>& a, boxed<T, U> const& b) noexcept { a.value *= b.value; return a; }
template <typename T, typename U> constexpr boxed<T, U>& operator/=(boxed<T, U>& a, boxed<T, U> const& b) noexcept { a.value /= b.value; return a; }
template <typename T, typename U> constexpr boxed<T, U>& operator%=(boxed<T, U>& a, boxed<T, U> const& b) noexcept { a.value %= b.value; return a; }

template <typename T, typename U> std::ostream& operator<<(std::ostream& os, boxed<T, U> const& v) { return os << v.value; }

Expand Down
3 changes: 2 additions & 1 deletion src/terminal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ set(terminal_SOURCES
Capabilities.cpp
Color.cpp
Grid.cpp
Screen.cpp # TODO(pr) move back. only moved here for test-compiles
Functions.cpp
Image.cpp
InputBinding.cpp
Expand All @@ -69,7 +70,7 @@ set(terminal_SOURCES
Parser.cpp
Process.cpp
RenderBuffer.cpp
Screen.cpp
#Screen.cpp
Sequence.cpp
Sequencer.cpp
Selector.cpp
Expand Down
20 changes: 16 additions & 4 deletions src/terminal/Charset.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,23 @@ class CharsetMapping {
}
{}

char32_t map(char _code) noexcept
char32_t map(char32_t _code) noexcept
{
auto result = map(shift_, _code);
shift_ = selected_;
return result;
// TODO: could surely be implemented branchless with a jump-table and computed goto.
if (_code < 127)
{
auto result = map(shift_, static_cast<char>(_code));
shift_ = selected_;
return result;
}
else if (_code != 127)
{
return static_cast<char32_t>(_code);
}
else
{
return L' ';
}
}

char32_t map(CharsetTable _table, char _code) const noexcept
Expand Down
42 changes: 18 additions & 24 deletions src/terminal/Coordinate.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,39 @@
*/
#pragma once

#include <crispy/point.h>
#include <terminal/primitives.h>
#include <ostream>

namespace terminal {

struct [[nodiscard]] Coordinate {
int row = 0;
int column = 0;
LineOffset row{};
ColumnOffset column{};

constexpr Coordinate& operator+=(Coordinate const& a) noexcept
constexpr Coordinate& operator+=(Coordinate a) noexcept
{
row += a.row;
column += a.column;
return *this;
}

constexpr Coordinate(int _row, int _column) : row{_row}, column{_column} {}
constexpr explicit Coordinate(crispy::Point p) : row{p.y}, column{p.x} {}
constexpr Coordinate() = default;
constexpr Coordinate(Coordinate const&) = default;
constexpr Coordinate(Coordinate&& v) = default;
constexpr Coordinate& operator=(Coordinate const&) = default;
constexpr Coordinate& operator=(Coordinate &&) = default;
};

inline std::ostream& operator<<(std::ostream& os, Coordinate coord)
{
return os << fmt::format("({}, {})", coord.row, coord.column);
}

constexpr void swap(Coordinate& a, Coordinate& b) noexcept
{
auto c = a;
a = b;
b = c;
}

constexpr bool operator==(Coordinate const& a, Coordinate const& b) noexcept { return a.row == b.row && a.column == b.column; }
constexpr bool operator!=(Coordinate const& a, Coordinate const& b) noexcept { return !(a == b); }
constexpr bool operator==(Coordinate a, Coordinate b) noexcept { return a.row == b.row && a.column == b.column; }
constexpr bool operator!=(Coordinate a, Coordinate b) noexcept { return !(a == b); }

constexpr bool operator<(Coordinate const& a, Coordinate const& b) noexcept
constexpr bool operator<(Coordinate a, Coordinate b) noexcept
{
if (a.row < b.row)
return true;
Expand All @@ -58,27 +56,22 @@ constexpr bool operator<(Coordinate const& a, Coordinate const& b) noexcept
return false;
}

constexpr bool operator<=(Coordinate const& a, Coordinate const& b) noexcept
constexpr bool operator<=(Coordinate a, Coordinate b) noexcept
{
return a < b || a == b;
}

constexpr bool operator>=(Coordinate const& a, Coordinate const& b) noexcept
constexpr bool operator>=(Coordinate a, Coordinate b) noexcept
{
return !(a < b);
}

constexpr bool operator>(Coordinate const& a, Coordinate const& b) noexcept
constexpr bool operator>(Coordinate a, Coordinate b) noexcept
{
return !(a == b || a < b);
}

inline Coordinate operator+(Coordinate const& a, Coordinate const& b) noexcept { return {a.row + b.row, a.column + b.column}; }

constexpr Coordinate operator+(Coordinate const& a, crispy::Point b) noexcept
{
return {a.row + b.y, a.column + b.x};
}
inline Coordinate operator+(Coordinate a, Coordinate b) noexcept { return {a.row + b.row, a.column + b.column}; }

}

Expand All @@ -97,3 +90,4 @@ namespace fmt {
}
};
}

Loading

0 comments on commit 44e2297

Please sign in to comment.