summaryrefslogtreecommitdiff
path: root/src/ring.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/ring.hh')
-rw-r--r--src/ring.hh253
1 files changed, 198 insertions, 55 deletions
diff --git a/src/ring.hh b/src/ring.hh
index b5df883e..1b17ca7a 100644
--- a/src/ring.hh
+++ b/src/ring.hh
@@ -28,28 +28,167 @@
#include "vterowdata.hh"
#include "vtestream.h"
-G_BEGIN_DECLS
-
-
-typedef guint32 hyperlink_idx_t;
+#include <type_traits>
typedef struct _VteVisualPosition {
long row, col;
} VteVisualPosition;
-/*
- * VteRing: A scrollback buffer ring
+namespace vte {
+
+namespace base {
+
+/**
+ * ring: A scrollback buffer ring
*/
+class Ring {
+public:
+ typedef guint32 hyperlink_idx_t;
+ // FIXME make this size_t (or off_t?)
+ typedef gulong row_t;
+ typedef glong column_t;
+
+ static const row_t kDefaultMaxRows = VTE_SCROLLBACK_INIT;
+
+ Ring(row_t max_rows = kDefaultMaxRows,
+ bool has_streams = false);
+ ~Ring();
+
+ // prevent accidents
+ Ring(Ring& o) = delete;
+ Ring(Ring const& o) = delete;
+ Ring(Ring&& o) = delete;
+ Ring& operator= (Ring& o) = delete;
+ Ring& operator= (Ring const& o) = delete;
+ Ring& operator= (Ring&& o) = delete;
+
+ inline bool contains(row_t position) const {
+ return (position >= m_start && position < m_end);
+ }
+
+ inline row_t delta() const { return m_start; }
+ inline row_t length() const { return m_end - m_start; }
+ inline row_t next() const { return m_end; }
+
+ //FIXMEchpe rename this to at()
+ //FIXMEchpe use references not pointers
+ VteRowData const* index(row_t position); /* const? */
+ VteRowData* index_writable(row_t position);
+
+ void hyperlink_maybe_gc(row_t increment);
+ hyperlink_idx_t get_hyperlink_idx(char const* hyperlink);
+ hyperlink_idx_t get_hyperlink_at_position(row_t position,
+ column_t col,
+ bool update_hover_idx,
+ char const** hyperlink);
+
+ row_t reset();
+ void resize(row_t max_rows = kDefaultMaxRows);
+ void shrink(row_t max_len = kDefaultMaxRows);
+ VteRowData* insert(row_t position);
+ VteRowData* append();
+ void remove(row_t position);
+ void drop_scrollback(row_t position);
+ void set_visible_rows(row_t rows);
+ void rewrap(column_t columns,
+ VteVisualPosition** markers);
+ bool write_contents(GOutputStream* stream,
+ VteWriteFlags flags,
+ GCancellable* cancellable,
+ GError** error);
+
+private:
+
+ #ifdef VTE_DEBUG
+ void validate() const;
+ #endif
+
+ inline GString* hyperlink_get(hyperlink_idx_t idx) const { return (GString*)g_ptr_array_index(m_hyperlinks, idx); }
+
+ inline VteRowData* get_writable_index(row_t position) const { return &m_array[position & m_mask]; }
-typedef struct _VteRing VteRing;
-struct _VteRing {
- gulong max;
+ void hyperlink_gc();
+ hyperlink_idx_t get_hyperlink_idx_no_update_current(char const* hyperlink);
- gulong start, end;
+ typedef struct _CellAttrChange {
+ gsize text_end_offset; /* offset of first character no longer using this attr */
+ VteStreamCellAttr attr;
+ } CellAttrChange;
+
+ typedef struct _RowRecord {
+ size_t text_start_offset; /* offset where text of this row begins */
+ size_t attr_start_offset; /* offset of the first character's attributes */
+ int soft_wrapped: 1; /* end of line is not '\n' */
+ int is_ascii: 1; /* for rewrapping speedup: guarantees that line contains 32..126 bytes only. Can be 0 even when ascii only. */
+ } RowRecord;
+
+ static_assert(std::is_pod<RowRecord>::value, "Ring::RowRecord is not POD");
+
+ /* Represents a cell position, see ../doc/rewrap.txt */
+ typedef struct _CellTextOffset {
+ size_t text_offset; /* byte offset in text_stream (or perhaps beyond) */
+ int fragment_cells; /* extra number of cells to walk within a multicell character */
+ int eol_cells; /* -1 if over a character, >=0 if at EOL or beyond */
+ } CellTextOffset;
+
+ static_assert(std::is_pod<CellTextOffset>::value, "Ring::CellTextOffset is not POD");
+
+ inline bool read_row_record(RowRecord* record /* out */,
+ row_t position)
+ {
+ return _vte_stream_read(m_row_stream,
+ position * sizeof(*record),
+ (char*)record,
+ sizeof(*record));
+ }
+
+ inline void append_row_record(RowRecord const* record,
+ row_t position)
+ {
+ _vte_stream_append(m_row_stream,
+ (char const*)record,
+ sizeof(*record));
+ }
+
+ bool frozen_row_column_to_text_offset(row_t position,
+ column_t column,
+ CellTextOffset* offset);
+ bool frozen_row_text_offset_to_column(row_t position,
+ CellTextOffset const* offset,
+ column_t* column);
+
+ bool write_row(GOutputStream* stream,
+ VteRowData* row,
+ VteWriteFlags flags,
+ GCancellable* cancellable,
+ GError** error);
+
+ void ensure_writable(row_t position);
+ void ensure_writable_room();
+
+ void freeze_one_row();
+ void maybe_freeze_one_row();
+ void thaw_one_row();
+ void discard_one_row();
+ void maybe_discard_one_row();
+
+ void freeze_row(row_t position,
+ VteRowData const* row);
+ void thaw_row(row_t position,
+ VteRowData* row,
+ bool do_truncate,
+ int hyperlink_column,
+ char const** hyperlink);
+ void reset_streams(row_t position);
+
+ row_t m_max;
+ row_t m_start{0};
+ row_t m_end{0};
/* Writable */
- gulong writable, mask;
- VteRowData *array;
+ row_t m_writable{0};
+ row_t m_mask{31};
+ VteRowData *m_array;
/* Storage:
*
@@ -65,56 +204,60 @@ struct _VteRing {
* if nonempty, it actually contains the ID and URI separated with a semicolon. Not NUL terminated.
* - 2 bytes repeating attr.hyperlink_length so that we can walk backwards.
*/
- VteStream *attr_stream, *text_stream, *row_stream;
- gsize last_attr_text_start_offset;
- VteCellAttr last_attr;
- GString *utf8_buffer;
+ bool m_has_streams;
+ VteStream *m_attr_stream, *m_text_stream, *m_row_stream;
+ size_t m_last_attr_text_start_offset{0};
+ VteCellAttr m_last_attr;
+ GString *m_utf8_buffer;
- VteRowData cached_row;
- gulong cached_row_num;
+ VteRowData m_cached_row;
+ row_t m_cached_row_num{(row_t)-1};
- gboolean has_streams;
- gulong visible_rows; /* to keep at least a screenful of lines in memory, bug 646098 comment 12 */
+ row_t m_visible_rows{0}; /* to keep at least a screenful of lines in memory, bug 646098 comment 12 */
- GPtrArray *hyperlinks; /* The hyperlink pool. Contains GString* items.
+ GPtrArray *m_hyperlinks; /* The hyperlink pool. Contains GString* items.
[0] points to an empty GString, [1] to [VTE_HYPERLINK_COUNT_MAX] contain the id;uri pairs. */
- char hyperlink_buf[VTE_HYPERLINK_TOTAL_LENGTH_MAX + 1]; /* One more hyperlink buffer to get the value if it's not placed in the pool. */
- hyperlink_idx_t hyperlink_highest_used_idx; /* 0 if no hyperlinks at all in the pool. */
- hyperlink_idx_t hyperlink_current_idx; /* The hyperlink idx used for newly created cells.
+ char m_hyperlink_buf[VTE_HYPERLINK_TOTAL_LENGTH_MAX + 1]; /* One more hyperlink buffer to get the value if it's not placed in the pool. */
+ hyperlink_idx_t m_hyperlink_highest_used_idx{0}; /* 0 if no hyperlinks at all in the pool. */
+ hyperlink_idx_t m_hyperlink_current_idx{0}; /* The hyperlink idx used for newly created cells.
Must not be GC'd even if doesn't occur onscreen. */
- hyperlink_idx_t hyperlink_hover_idx; /* The hyperlink idx of the hovered cell.
+ hyperlink_idx_t m_hyperlink_hover_idx{0}; /* The hyperlink idx of the hovered cell.
An idx is allocated on hover even if the cell is scrolled out to the streams. */
- gulong hyperlink_maybe_gc_counter; /* Do a GC when it reaches 65536. */
+ row_t m_hyperlink_maybe_gc_counter{0}; /* Do a GC when it reaches 65536. */
};
-#define _vte_ring_contains(__ring, __position) \
- (((gulong) (__position) >= (__ring)->start) && \
- ((gulong) (__position) < (__ring)->end))
-#define _vte_ring_delta(__ring) ((glong) (__ring)->start)
-#define _vte_ring_length(__ring) ((glong) ((__ring)->end - (__ring)->start))
-#define _vte_ring_next(__ring) ((glong) (__ring)->end)
-
-const VteRowData *_vte_ring_index (VteRing *ring, gulong position);
-VteRowData *_vte_ring_index_writable (VteRing *ring, gulong position);
-
-void _vte_ring_init (VteRing *ring, gulong max_rows, gboolean has_streams);
-void _vte_ring_fini (VteRing *ring);
-void _vte_ring_hyperlink_maybe_gc (VteRing *ring, gulong increment);
-hyperlink_idx_t _vte_ring_get_hyperlink_idx (VteRing *ring, const char *hyperlink);
-hyperlink_idx_t _vte_ring_get_hyperlink_at_position (VteRing *ring, gulong position, int col, bool update_hover_idx, const char **hyperlink);
-long _vte_ring_reset (VteRing *ring);
-void _vte_ring_resize (VteRing *ring, gulong max_rows);
-void _vte_ring_shrink (VteRing *ring, gulong max_len);
-VteRowData *_vte_ring_insert (VteRing *ring, gulong position);
-VteRowData *_vte_ring_append (VteRing *ring);
-void _vte_ring_remove (VteRing *ring, gulong position);
-void _vte_ring_drop_scrollback (VteRing *ring, gulong position);
-void _vte_ring_set_visible_rows (VteRing *ring, gulong rows);
-void _vte_ring_rewrap (VteRing *ring, glong columns, VteVisualPosition **markers);
-gboolean _vte_ring_write_contents (VteRing *ring,
- GOutputStream *stream,
- VteWriteFlags flags,
- GCancellable *cancellable,
- GError **error);
+}; /* namespace base */
+
+}; /* namespace vte */
+
+G_BEGIN_DECLS
+
+/* temp compat API */
+
+typedef vte::base::Ring VteRing;
+
+static inline bool _vte_ring_contains(VteRing *ring, gulong position) { return ring->contains(position); }
+static inline glong _vte_ring_delta(VteRing *ring) { return ring->delta(); }
+static inline glong _vte_ring_length(VteRing *ring) { return ring->length(); }
+static inline glong _vte_ring_next(VteRing *ring) { return ring->next(); }
+static inline const VteRowData *_vte_ring_index (VteRing *ring, gulong position) { return ring->index(position); }
+static inline VteRowData *_vte_ring_index_writable (VteRing *ring, gulong position) { return ring->index_writable(position); }
+static inline void _vte_ring_hyperlink_maybe_gc (VteRing *ring, gulong increment) { ring->hyperlink_maybe_gc(increment); }
+static inline auto _vte_ring_get_hyperlink_idx (VteRing *ring, const char *hyperlink) { return ring->get_hyperlink_idx(hyperlink); }
+static inline auto _vte_ring_get_hyperlink_at_position (VteRing *ring, gulong position, int col, bool update_hover_idx, const char **hyperlink) { return ring->get_hyperlink_at_position(position, col, update_hover_idx, hyperlink); }
+static inline long _vte_ring_reset (VteRing *ring) { return ring->reset(); }
+static inline void _vte_ring_resize (VteRing *ring, gulong max_rows) { ring->resize(max_rows); }
+static inline void _vte_ring_shrink (VteRing *ring, gulong max_len) { ring->shrink(max_len); }
+static inline VteRowData *_vte_ring_insert (VteRing *ring, gulong position) { return ring->insert(position); }
+static inline VteRowData *_vte_ring_append (VteRing *ring) { return ring->append(); }
+static inline void _vte_ring_remove (VteRing *ring, gulong position) { ring->remove(position); }
+static inline void _vte_ring_drop_scrollback (VteRing *ring, gulong position) { ring->drop_scrollback(position); }
+static inline void _vte_ring_set_visible_rows (VteRing *ring, gulong rows) { ring->set_visible_rows(rows); }
+static inline void _vte_ring_rewrap (VteRing *ring, glong columns, VteVisualPosition **markers) { ring->rewrap(columns, markers); }
+static inline gboolean _vte_ring_write_contents (VteRing *ring,
+ GOutputStream *stream,
+ VteWriteFlags flags,
+ GCancellable *cancellable,
+ GError **error) { return ring->write_contents(stream, flags, cancellable, error); }
G_END_DECLS