summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xperf/deco.sh85
-rw-r--r--src/Makefile.am1
-rw-r--r--src/attr.hh137
-rw-r--r--src/ring.cc32
-rw-r--r--src/vte.cc276
-rw-r--r--src/vteinternal.hh8
-rw-r--r--src/vterowdata.h108
-rw-r--r--src/vteseq.cc47
8 files changed, 453 insertions, 241 deletions
diff --git a/perf/deco.sh b/perf/deco.sh
new file mode 100755
index 00000000..bce86e28
--- /dev/null
+++ b/perf/deco.sh
@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+
+# Test deco color support
+# Copyright © 2014 Egmont Koblinger
+# Copyright © 2018 Christian Persch
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+sep=":"
+sepsep="::"
+if [ "$1" = "-colon" -o "$1" = "-official" -o "$1" = "-dejure" ]; then
+ shift
+elif [ "$1" = "-semicolon" -o "$1" = "-common" -o "$1" = "-defacto" ]; then
+ sep=";"
+ sepsep=";" # no empty param for legacy format
+ shift
+fi
+
+if [ $# != 0 ]; then
+ echo 'Usage: deco.sh [FORMAT]' >&2
+ echo >&2
+ echo ' -colon|-official|-dejure: Official format (default) CSI 58:2::R:G:Bm' >&2
+ echo ' -semicolon|-common|-defacto: Commonly used format CSI 58;2;R;G;Bm' >&2
+ exit 1
+fi
+
+row() {
+ local format="$1"
+ local n="$2"
+ local v;
+ for m in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
+ v=$(($n * 16 + $m))
+ printf "\e[${format};4m%02X\e[0m%.0s%.0s%.0s" 38 $v $v $v $v $v $v
+ done
+ printf "\t"
+ for m in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
+ v=$(($n * 16 + $m))
+ printf "\e[${format};4m%02X\e[0m%.0s%.0s%.0s" 48 $v $v $v $v $v $v
+ done
+ printf "\n"
+}
+
+cubes() {
+ local format1="$1"
+ local format2="$2"
+ local format="%d${sep}2${sepsep}${format1};58${sep}2${sepsep}${format2}"
+ for n in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
+ row "$format" $n
+ done
+}
+
+printf "\e[0m"
+cubes "%d${sep}0${sep}0" "%d${sep}0${sep}0"
+printf "\n"
+cubes "0${sep}%d${sep}0" "0${sep}%d${sep}0"
+printf "\n"
+cubes "0${sep}0${sep}%d" "0${sep}0${sep}%d"
+printf "\n"
+cubes "%d${sep}0${sep}0" "0${sep}%d${sep}0"
+printf "\n"
+cubes "%d${sep}0${sep}0" "0${sep}0${sep}%d"
+printf "\n"
+cubes "0${sep}%d${sep}0" "%d${sep}0${sep}0"
+printf "\n"
+cubes "0${sep}%d${sep}0" "0${sep}0${sep}%d"
+printf "\n"
+cubes "0${sep}0${sep}%d" "%d${sep}0${sep}0"
+printf "\n"
+cubes "0${sep}0${sep}%d" "0${sep}%d${sep}0"
+printf "\n"
+printf "\e[0m"
+
+exit 0
diff --git a/src/Makefile.am b/src/Makefile.am
index 6f68b1ec..e26d9e5e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,7 @@ libvte_@VTE_API_MAJOR_VERSION@_@VTE_API_MINOR_VERSION@_la_SOURCES = \
vte/vtepty.h \
vte/vteregex.h \
vte/vteterminal.h \
+ attr.hh \
buffer.h \
caps.hh \
caps-list.hh \
diff --git a/src/attr.hh b/src/attr.hh
new file mode 100644
index 00000000..90899274
--- /dev/null
+++ b/src/attr.hh
@@ -0,0 +1,137 @@
+/*
+ * Copyright © 2018 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#define VTE_ATTR_VALUE_MASK(bits) ((1U << (bits)) - 1U)
+#define VTE_ATTR_MASK(shift,bits) (VTE_ATTR_VALUE_MASK(bits) << (shift))
+
+/* Number of visible columns (as determined by g_unicode_iswide(c)).
+ * Also (ab)used for tabs; bug 353610.
+ */
+#define VTE_ATTR_COLUMNS_SHIFT (0)
+#define VTE_ATTR_COLUMNS_BITS (4) /* Has to be able to store the value of 8. */
+#define VTE_ATTR_COLUMNS_MASK (VTE_ATTR_MASK(VTE_ATTR_COLUMNS_SHIFT, VTE_ATTR_COLUMNS_BITS))
+#define VTE_ATTR_COLUMNS_VALUE_MASK (VTE_ATTR_VALUE_MASK(VTE_ATTR_COLUMNS_BITS))
+#define VTE_ATTR_COLUMNS(v) ((v) << VTE_ATTR_COLUMNS_SHIFT)
+
+/* A continuation cell */
+#define VTE_ATTR_FRAGMENT_SHIFT (VTE_ATTR_COLUMNS_SHIFT + VTE_ATTR_COLUMNS_BITS)
+#define VTE_ATTR_FRAGMENT_BITS (1)
+#define VTE_ATTR_FRAGMENT_MASK (VTE_ATTR_MASK(VTE_ATTR_FRAGMENT_SHIFT, VTE_ATTR_FRAGMENT_BITS))
+#define VTE_ATTR_FRAGMENT (1U << VTE_ATTR_FRAGMENT_SHIFT)
+
+#define VTE_ATTR_BOLD_SHIFT (VTE_ATTR_FRAGMENT_SHIFT + VTE_ATTR_FRAGMENT_BITS)
+#define VTE_ATTR_BOLD_BITS (1)
+#define VTE_ATTR_BOLD_MASK (VTE_ATTR_MASK(VTE_ATTR_BOLD_SHIFT, VTE_ATTR_BOLD_BITS))
+#define VTE_ATTR_BOLD (1U << VTE_ATTR_BOLD_SHIFT)
+
+#define VTE_ATTR_ITALIC_SHIFT (VTE_ATTR_BOLD_SHIFT + VTE_ATTR_BOLD_BITS)
+#define VTE_ATTR_ITALIC_BITS (1)
+#define VTE_ATTR_ITALIC_MASK (VTE_ATTR_MASK(VTE_ATTR_ITALIC_SHIFT, VTE_ATTR_ITALIC_BITS))
+#define VTE_ATTR_ITALIC (1U << VTE_ATTR_ITALIC_SHIFT)
+
+/* 0: none, 1: single, 2: double, 3: curly */
+#define VTE_ATTR_UNDERLINE_SHIFT (VTE_ATTR_ITALIC_SHIFT + VTE_ATTR_ITALIC_BITS)
+#define VTE_ATTR_UNDERLINE_BITS (2)
+#define VTE_ATTR_UNDERLINE_MASK (VTE_ATTR_MASK(VTE_ATTR_UNDERLINE_SHIFT, VTE_ATTR_UNDERLINE_BITS))
+#define VTE_ATTR_UNDERLINE_VALUE_MASK (VTE_ATTR_VALUE_MASK(VTE_ATTR_UNDERLINE_BITS))
+#define VTE_ATTR_UNDERLINE(v) ((v) << VTE_ATTR_UNDERLINE_SHIFT)
+
+#define VTE_ATTR_STRIKETHROUGH_SHIFT (VTE_ATTR_UNDERLINE_SHIFT + VTE_ATTR_UNDERLINE_BITS)
+#define VTE_ATTR_STRIKETHROUGH_BITS (1)
+#define VTE_ATTR_STRIKETHROUGH_MASK (VTE_ATTR_MASK(VTE_ATTR_STRIKETHROUGH_SHIFT, VTE_ATTR_STRIKETHROUGH_BITS))
+#define VTE_ATTR_STRIKETHROUGH (1U << VTE_ATTR_STRIKETHROUGH_SHIFT)
+
+#define VTE_ATTR_OVERLINE_SHIFT (VTE_ATTR_STRIKETHROUGH_SHIFT + VTE_ATTR_STRIKETHROUGH_BITS)
+#define VTE_ATTR_OVERLINE_BITS (1)
+#define VTE_ATTR_OVERLINE_MASK (VTE_ATTR_MASK(VTE_ATTR_OVERLINE_SHIFT, VTE_ATTR_OVERLINE_BITS))
+#define VTE_ATTR_OVERLINE (1U << VTE_ATTR_OVERLINE_SHIFT)
+
+#define VTE_ATTR_REVERSE_SHIFT (VTE_ATTR_OVERLINE_SHIFT + VTE_ATTR_OVERLINE_BITS)
+#define VTE_ATTR_REVERSE_BITS (1)
+#define VTE_ATTR_REVERSE_MASK (VTE_ATTR_MASK(VTE_ATTR_REVERSE_SHIFT, VTE_ATTR_REVERSE_BITS))
+#define VTE_ATTR_REVERSE (1U << VTE_ATTR_REVERSE_SHIFT)
+
+#define VTE_ATTR_BLINK_SHIFT (VTE_ATTR_REVERSE_SHIFT + VTE_ATTR_REVERSE_BITS)
+#define VTE_ATTR_BLINK_BITS (1)
+#define VTE_ATTR_BLINK_MASK (VTE_ATTR_MASK(VTE_ATTR_BLINK_SHIFT, VTE_ATTR_BLINK_BITS))
+#define VTE_ATTR_BLINK (1U << VTE_ATTR_BLINK_SHIFT)
+
+/* also known as faint, half intensity etc. */
+#define VTE_ATTR_DIM_SHIFT (VTE_ATTR_BLINK_SHIFT + VTE_ATTR_BLINK_BITS)
+#define VTE_ATTR_DIM_BITS (1)
+#define VTE_ATTR_DIM_MASK (VTE_ATTR_MASK(VTE_ATTR_DIM_SHIFT, VTE_ATTR_DIM_BITS))
+#define VTE_ATTR_DIM (1U << VTE_ATTR_DIM_SHIFT)
+
+#define VTE_ATTR_INVISIBLE_SHIFT (VTE_ATTR_DIM_SHIFT + VTE_ATTR_DIM_BITS)
+#define VTE_ATTR_INVISIBLE_BITS (1)
+#define VTE_ATTR_INVISIBLE_MASK (VTE_ATTR_MASK(VTE_ATTR_INVISIBLE_SHIFT, VTE_ATTR_INVISIBLE_BITS))
+#define VTE_ATTR_INVISIBLE (1U << VTE_ATTR_INVISIBLE_SHIFT)
+
+/* Used internally only */
+#define VTE_ATTR_BOXED_SHIFT (31)
+#define VTE_ATTR_BOXED_BITS (1)
+#define VTE_ATTR_BOXED_MASK (VTE_ATTR_MASK(VTE_ATTR_BOXED_SHIFT, VTE_ATTR_BOXED_BITS))
+#define VTE_ATTR_BOXED (1U << VTE_ATTR_BOXED_SHIFT)
+
+/* All attributes except DIM and BOXED */
+#define VTE_ATTR_ALL_MASK (VTE_ATTR_BOLD_MASK | \
+ VTE_ATTR_ITALIC_MASK | \
+ VTE_ATTR_UNDERLINE_MASK | \
+ VTE_ATTR_STRIKETHROUGH_MASK | \
+ VTE_ATTR_OVERLINE_MASK | \
+ VTE_ATTR_REVERSE_MASK | \
+ VTE_ATTR_BLINK_MASK | \
+ VTE_ATTR_INVISIBLE_MASK)
+
+#define VTE_ATTR_NONE (0U)
+#define VTE_ATTR_DEFAULT (VTE_ATTR_COLUMNS(1))
+
+static constexpr inline void vte_attr_set_bool(uint32_t* attr,
+ uint32_t mask,
+ bool value)
+{
+ if (value)
+ *attr |= mask;
+ else
+ *attr &= ~mask;
+}
+
+static constexpr inline void vte_attr_set_value(uint32_t* attr,
+ uint32_t mask,
+ unsigned int shift,
+ uint32_t value)
+{
+ g_assert_cmpuint(value << shift, <=, mask); /* assurance */
+ *attr = (*attr & ~mask) | ((value << shift) & mask /* assurance */);
+}
+
+static constexpr inline bool vte_attr_get_bool(uint32_t attr,
+ unsigned int shift)
+{
+ return (attr >> shift) & 1U;
+}
+
+static constexpr inline unsigned int vte_attr_get_value(uint32_t attr,
+ uint32_t value_mask,
+ unsigned int shift)
+{
+ return (attr >> shift) & value_mask;
+}
diff --git a/src/ring.cc b/src/ring.cc
index d91dc97d..05e938ea 100644
--- a/src/ring.cc
+++ b/src/ring.cc
@@ -362,7 +362,7 @@ _vte_ring_freeze_row (VteRing *ring, gulong position, const VteRowData *row)
* the text in real UTF-8.
*/
attr = cell->attr;
- if (G_LIKELY (!attr.fragment)) {
+ if (G_LIKELY (!attr.fragment())) {
VteCellAttrChange attr_change;
guint16 hyperlink_length;
@@ -389,7 +389,7 @@ _vte_ring_freeze_row (VteRing *ring, gulong position, const VteRowData *row)
num_chars = _vte_unistr_strlen (cell->c);
if (num_chars > 1) {
/* Combining chars */
- attr.columns = 0;
+ attr.set_columns(0);
ring->last_attr_text_start_offset = record.text_start_offset + buffer->len
+ g_unichar_to_utf8 (_vte_unistr_get_base (cell->c), NULL);
memset(&attr_change, 0, sizeof (attr_change));
@@ -514,7 +514,7 @@ _vte_ring_thaw_row (VteRing *ring, gulong position, VteRowData *row, gboolean do
_VTE_DEBUG_IF(VTE_DEBUG_RING | VTE_DEBUG_HYPERLINK) {
/* Debug: Reverse the colors for the stream's contents. */
if (!do_truncate) {
- cell.attr.reverse = !cell.attr.reverse;
+ cell.attr.attr ^= VTE_ATTR_REVERSE;
}
}
cell.c = g_utf8_get_char (p);
@@ -523,12 +523,12 @@ _vte_ring_thaw_row (VteRing *ring, gulong position, VteRowData *row, gboolean do
record.text_start_offset += q - p;
p = q;
- if (G_UNLIKELY (cell.attr.columns == 0)) {
+ if (G_UNLIKELY (cell.attr.columns() == 0)) {
if (G_LIKELY (row->len)) {
/* Combine it */
row->cells[row->len - 1].c = _vte_unistr_append_unichar (row->cells[row->len - 1].c, cell.c);
} else {
- cell.attr.columns = 1;
+ cell.attr.set_columns(1);
if (row->len == hyperlink_column && hyperlink != NULL)
*hyperlink = strcpy(ring->hyperlink_buf, hyperlink_readbuf);
_vte_row_data_append (row, &cell);
@@ -537,11 +537,11 @@ _vte_ring_thaw_row (VteRing *ring, gulong position, VteRowData *row, gboolean do
if (row->len == hyperlink_column && hyperlink != NULL)
*hyperlink = strcpy(ring->hyperlink_buf, hyperlink_readbuf);
_vte_row_data_append (row, &cell);
- if (cell.attr.columns > 1) {
+ if (cell.attr.columns() > 1) {
/* Add the fragments */
- int i, columns = cell.attr.columns;
- cell.attr.fragment = 1;
- cell.attr.columns = 1;
+ int i, columns = cell.attr.columns();
+ cell.attr.set_fragment(true);
+ cell.attr.set_columns(1);
for (i = 1; i < columns; i++) {
if (row->len == hyperlink_column && hyperlink != NULL)
*hyperlink = strcpy(ring->hyperlink_buf, hyperlink_readbuf);
@@ -1043,8 +1043,8 @@ _vte_frozen_row_column_to_text_offset (VteRing *ring,
offset->eol_cells = -1;
num_chars = 0;
for (i = 0, cell = row->cells; i < row->len && i < column; i++, cell++) {
- if (G_LIKELY (!cell->attr.fragment)) {
- if (G_UNLIKELY (i + cell->attr.columns > column)) {
+ if (G_LIKELY (!cell->attr.fragment())) {
+ if (G_UNLIKELY (i + cell->attr.columns() > column)) {
offset->fragment_cells = column - i;
break;
}
@@ -1125,7 +1125,7 @@ _vte_frozen_row_text_offset_to_column (VteRing *ring,
/* count the number of columns for the given number of characters */
for (i = 0, cell = row->cells; i < row->len; i++, cell++) {
- if (G_LIKELY (!cell->attr.fragment)) {
+ if (G_LIKELY (!cell->attr.fragment())) {
if (num_chars == 0) break;
nc = _vte_unistr_strlen(cell->c);
if (nc > num_chars) break;
@@ -1280,13 +1280,13 @@ _vte_ring_rewrap (VteRing *ring,
}
runlength = MIN(paragraph_len, attr_change.text_end_offset - text_offset);
- if (G_UNLIKELY (attr_change.attr.columns == 0)) {
+ if (G_UNLIKELY (attr_change.attr.columns() == 0)) {
/* Combining characters all fit in the current row */
text_offset += runlength;
paragraph_len -= runlength;
} else {
while (runlength) {
- if (col >= columns - attr_change.attr.columns + 1) {
+ if (col >= columns - attr_change.attr.columns() + 1) {
/* Wrap now, write the soft wrapped row's record */
new_record.soft_wrapped = 1;
_vte_stream_append(new_row_stream, (const char *) &new_record, sizeof (new_record));
@@ -1319,7 +1319,7 @@ _vte_ring_rewrap (VteRing *ring,
/* Process one character only. */
char textbuf[6]; /* fits at least one UTF-8 character */
int textbuf_len;
- col += attr_change.attr.columns;
+ col += attr_change.attr.columns();
/* Find beginning of next UTF-8 character */
text_offset++; paragraph_len--; runlength--;
textbuf_len = MIN(runlength, sizeof (textbuf));
@@ -1414,7 +1414,7 @@ _vte_ring_write_row (VteRing *ring,
* TODO Should unify one day */
g_string_set_size (buffer, 0);
for (i = 0, cell = row->cells; i < row->len; i++, cell++) {
- if (G_LIKELY (!cell->attr.fragment))
+ if (G_LIKELY (!cell->attr.fragment()))
_vte_unistr_append_to_string (cell->c, buffer);
}
if (!row->attr.soft_wrapped)
diff --git a/src/vte.cc b/src/vte.cc
index 4d3cddae..aa6a8103 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -534,7 +534,7 @@ VteTerminalPrivate::find_start_column(vte::grid::column_t col,
return col;
if (row_data != nullptr) {
const VteCell *cell = _vte_row_data_get (row_data, col);
- while (col > 0 && cell != NULL && cell->attr.fragment) {
+ while (col > 0 && cell != NULL && cell->attr.fragment()) {
cell = _vte_row_data_get (row_data, --col);
}
}
@@ -552,11 +552,11 @@ VteTerminalPrivate::find_end_column(vte::grid::column_t col,
return col;
if (row_data != NULL) {
const VteCell *cell = _vte_row_data_get (row_data, col);
- while (col > 0 && cell != NULL && cell->attr.fragment) {
+ while (col > 0 && cell != NULL && cell->attr.fragment()) {
cell = _vte_row_data_get (row_data, --col);
}
if (cell) {
- columns = cell->attr.columns - 1;
+ columns = cell->attr.columns() - 1;
}
}
// FIXMEchp m__column_count - 1 ?
@@ -632,11 +632,11 @@ VteTerminalPrivate::invalidate_cell(vte::grid::column_t col,
const VteCell *cell;
cell = _vte_row_data_get (row_data, col);
if (cell != NULL) {
- while (cell->attr.fragment && col> 0) {
+ while (cell->attr.fragment() && col> 0) {
cell = _vte_row_data_get (row_data, --col);
}
- columns = cell->attr.columns;
- style = _vte_draw_get_style(cell->attr.bold, cell->attr.italic);
+ columns = cell->attr.columns();
+ style = _vte_draw_get_style(cell->attr.bold(), cell->attr.italic());
if (cell->c != 0) {
int right;
_vte_draw_get_char_edges(m_draw, cell->c, columns, style, NULL, &right);
@@ -677,8 +677,8 @@ VteTerminalPrivate::invalidate_cursor_once(bool periodic)
auto cell = find_charcell(column, row);
if (cell != NULL) {
- columns = cell->attr.columns;
- auto style = _vte_draw_get_style(cell->attr.bold, cell->attr.italic);
+ columns = cell->attr.columns();
+ auto style = _vte_draw_get_style(cell->attr.bold(), cell->attr.italic());
if (cell->c != 0) {
int right;
_vte_draw_get_char_edges(m_draw, cell->c, columns, style, NULL, &right);
@@ -2741,35 +2741,35 @@ VteTerminalPrivate::cleanup_fragments(long start,
* handling the left hand side, but handling the right hand side first might
* overwrite it if start == end (inserting to the middle of a character). */
cell_start = _vte_row_data_get (row, start);
- cell_start_is_fragment = cell_start != NULL && cell_start->attr.fragment;
+ cell_start_is_fragment = cell_start != NULL && cell_start->attr.fragment();
/* On the right hand side, try to replace a TAB by a shorter TAB if we can.
* This requires that the TAB on the left (which might be the same TAB) is
* not yet converted to spaces, so start on the right hand side. */
cell_end = _vte_row_data_get_writable (row, end);
- if (G_UNLIKELY (cell_end != NULL && cell_end->attr.fragment)) {
+ if (G_UNLIKELY (cell_end != NULL && cell_end->attr.fragment())) {
col = end;
do {
col--;
g_assert(col >= 0); /* The first cell can't be a fragment. */
cell_col = _vte_row_data_get_writable (row, col);
- } while (cell_col->attr.fragment);
+ } while (cell_col->attr.fragment());
if (cell_col->c == '\t') {
_vte_debug_print(VTE_DEBUG_MISC,
"Replacing right part of TAB with a shorter one at %ld (%ld cells) => %ld (%ld cells)\n",
- col, (long) cell_col->attr.columns, end, (long) cell_col->attr.columns - (end - col));
+ col, (long) cell_col->attr.columns(), end, (long) cell_col->attr.columns() - (end - col));
cell_end->c = '\t';
- cell_end->attr.fragment = 0;
- g_assert(cell_col->attr.columns > end - col);
- cell_end->attr.columns = cell_col->attr.columns - (end - col);
+ cell_end->attr.set_fragment(false);
+ g_assert(cell_col->attr.columns() > end - col);
+ cell_end->attr.set_columns(cell_col->attr.columns() - (end - col));
} else {
_vte_debug_print(VTE_DEBUG_MISC,
"Cleaning CJK right half at %ld\n",
end);
- g_assert(end - col == 1 && cell_col->attr.columns == 2);
+ g_assert(end - col == 1 && cell_col->attr.columns() == 2);
cell_end->c = ' ';
- cell_end->attr.fragment = 0;
- cell_end->attr.columns = 1;
+ cell_end->attr.set_fragment(false);
+ cell_end->attr.set_columns(1);
invalidate_cells(
end, 1,
m_screen->cursor.row, 1);
@@ -2785,11 +2785,11 @@ VteTerminalPrivate::cleanup_fragments(long start,
col--;
g_assert(col >= 0); /* The first cell can't be a fragment. */
cell_col = _vte_row_data_get_writable (row, col);
- if (!cell_col->attr.fragment) {
+ if (!cell_col->attr.fragment()) {
if (cell_col->c == '\t') {
_vte_debug_print(VTE_DEBUG_MISC,
"Replacing left part of TAB with spaces at %ld (%ld => %ld cells)\n",
- col, (long)cell_col->attr.columns, start - col);
+ col, (long)cell_col->attr.columns(), start - col);
/* nothing to do here */
} else {
_vte_debug_print(VTE_DEBUG_MISC,
@@ -2803,8 +2803,8 @@ VteTerminalPrivate::cleanup_fragments(long start,
keep_going = FALSE;
}
cell_col->c = ' ';
- cell_col->attr.fragment = 0;
- cell_col->attr.columns = 1;
+ cell_col->attr.set_fragment(false);
+ cell_col->attr.set_columns(1);
} while (keep_going);
}
}
@@ -3065,7 +3065,7 @@ VteTerminalPrivate::insert_char(gunichar c,
goto not_inserted;
/* Find the previous cell */
- while (cell && cell->attr.fragment && col > 0)
+ while (cell && cell->attr.fragment() && col > 0)
cell = _vte_row_data_get_writable (row, --col);
if (G_UNLIKELY (!cell || cell->c == '\t'))
goto not_inserted;
@@ -3074,7 +3074,7 @@ VteTerminalPrivate::insert_char(gunichar c,
c = _vte_unistr_append_unichar (cell->c, c);
/* And set it */
- columns = cell->attr.columns;
+ columns = cell->attr.columns();
for (i = 0; i < columns; i++) {
cell = _vte_row_data_get_writable (row, col++);
cell->c = c;
@@ -3107,7 +3107,7 @@ VteTerminalPrivate::insert_char(gunichar c,
attr = m_defaults.attr;
attr.copy_colors(m_color_defaults.attr);
- attr.columns = columns;
+ attr.set_columns(columns);
{
VteCell *pcell = _vte_row_data_get_writable (row, col);
@@ -3117,7 +3117,7 @@ VteTerminalPrivate::insert_char(gunichar c,
}
/* insert wide-char fragments */
- attr.fragment = 1;
+ attr.set_fragment(true);
for (i = 1; i < columns; i++) {
VteCell *pcell = _vte_row_data_get_writable (row, col);
pcell->c = c;
@@ -6035,7 +6035,7 @@ VteTerminalPrivate::get_text(vte::grid::row_t start_row,
/* If it's not part of a multi-column character,
* and passes the selection criterion, add it to
* the selection. */
- if (!pcell->attr.fragment) {
+ if (!pcell->attr.fragment()) {
/* Store the attributes of this character. */
// FIXMEchpe shouldn't this use determine_colors?
uint32_t fg, bg, dc;
@@ -6048,8 +6048,8 @@ VteTerminalPrivate::get_text(vte::grid::row_t start_row,
attr.back.red = back.red;
attr.back.green = back.green;
attr.back.blue = back.blue;
- attr.underline = (pcell->attr.underline == 1);
- attr.strikethrough = pcell->attr.strikethrough;
+ attr.underline = (pcell->attr.underline() == 1);
+ attr.strikethrough = pcell->attr.strikethrough();
/* Store the cell string */
if (pcell->c == 0) {
@@ -6085,7 +6085,7 @@ VteTerminalPrivate::get_text(vte::grid::row_t start_row,
while ((pcell = _vte_row_data_get (row_data, col))) {
col++;
- if (pcell->attr.fragment)
+ if (pcell->attr.fragment())
continue;
if (pcell->c != 0)
@@ -6179,15 +6179,9 @@ static bool
vte_terminal_cellattr_equal(VteCellAttr const* attr1,
VteCellAttr const* attr2)
{
- return (attr1->bold == attr2->bold &&
- attr1->italic == attr2->italic &&
- attr1->colors() == attr2->colors() &&
- attr1->underline == attr2->underline &&
- attr1->strikethrough == attr2->strikethrough &&
- attr1->overline == attr2->overline &&
- attr1->reverse == attr2->reverse &&
- attr1->blink == attr2->blink &&
- attr1->invisible == attr2->invisible &&
+ //FIXMEchpe why exclude DIM here?
+ return (((attr1->attr ^ attr2->attr) & VTE_ATTR_ALL_MASK) == 0 &&
+ attr1->colors() == attr2->colors() &&
attr1->hyperlink_idx == attr2->hyperlink_idx);
}
@@ -6207,16 +6201,16 @@ VteTerminalPrivate::cellattr_to_html(VteCellAttr const* attr,
determine_colors(attr, false, false, &fore, &back, &deco);
- if (attr->bold) {
+ if (attr->bold()) {
g_string_prepend(string, "<b>");
g_string_append(string, "</b>");
}
- if (attr->italic) {
+ if (attr->italic()) {
g_string_prepend(string, "<i>");
g_string_append(string, "</i>");
}
/* <u> should be inside <font> so that it inherits its color by default */
- if (attr->underline) {
+ if (attr->underline() != 0) {
static const char styles[][7] = {"", "single", "double", "wavy"};
char *tag, *colorattr;
@@ -6233,14 +6227,14 @@ VteTerminalPrivate::cellattr_to_html(VteCellAttr const* attr,
}
tag = g_strdup_printf("<u style=\"text-decoration-style:%s%s\">",
- styles[attr->underline],
+ styles[attr->underline()],
colorattr);
g_string_prepend(string, tag);
g_free(tag);
g_free(colorattr);
g_string_append(string, "</u>");
}
- if (fore != VTE_DEFAULT_FG || attr->reverse) {
+ if (fore != VTE_DEFAULT_FG || attr->reverse()) {
vte::color::rgb color;
char *tag;
@@ -6253,7 +6247,7 @@ VteTerminalPrivate::cellattr_to_html(VteCellAttr const* attr,
g_free(tag);
g_string_append(string, "</font>");
}
- if (back != VTE_DEFAULT_BG || attr->reverse) {
+ if (back != VTE_DEFAULT_BG || attr->reverse()) {
vte::color::rgb color;
char *tag;
@@ -6266,15 +6260,15 @@ VteTerminalPrivate::cellattr_to_html(VteCellAttr const* attr,
g_free(tag);
g_string_append(string, "</span>");
}
- if (attr->strikethrough) {
+ if (attr->strikethrough()) {
g_string_prepend(string, "<strike>");
g_string_append(string, "</strike>");
}
- if (attr->overline) {
+ if (attr->overline()) {
g_string_prepend(string, "<span style=\"text-decoration-line:overline\">");
g_string_append(string, "</span>");
}
- if (attr->blink) {
+ if (attr->blink()) {
g_string_prepend(string, "<blink>");
g_string_append(string, "</blink>");
}
@@ -6631,7 +6625,7 @@ VteTerminalPrivate::extend_selection_expand()
/* Find the last non-empty character on the first line. */
for (i = _vte_row_data_length (rowdata); i > 0; i--) {
cell = _vte_row_data_get (rowdata, i - 1);
- if (cell->attr.fragment || cell->c != 0)
+ if (cell->attr.fragment() || cell->c != 0)
break;
}
} else {
@@ -6657,7 +6651,7 @@ VteTerminalPrivate::extend_selection_expand()
/* Find the last non-empty character on the last line. */
for (i = _vte_row_data_length (rowdata); i > 0; i--) {
cell = _vte_row_data_get (rowdata, i - 1);
- if (cell->attr.fragment || cell->c != 0)
+ if (cell->attr.fragment() || cell->c != 0)
break;
}
/* If the end point is to its right, then extend the
@@ -8878,7 +8872,7 @@ VteTerminalPrivate::determine_colors(VteCellAttr const* attr,
}
/* Handle bold by using set bold color or brightening */
- if (attr->bold && m_bold_is_bright) {
+ if (attr->bold() && m_bold_is_bright) {
if (fore == VTE_DEFAULT_FG)
fore = VTE_BOLD_FG;
else if (fore >= VTE_LEGACY_COLORS_OFFSET && fore < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_COLOR_SET_SIZE) {
@@ -8889,12 +8883,12 @@ VteTerminalPrivate::determine_colors(VteCellAttr const* attr,
/* Handle dim colors. Only apply to palette colors, dimming direct RGB wouldn't make sense.
* Apply to the foreground color only, but do this before handling reverse/highlight so that
* those can be used to dim the background instead. */
- if (attr->dim && !(fore & VTE_RGB_COLOR_MASK(8, 8, 8))) {
+ if (attr->dim() && !(fore & VTE_RGB_COLOR_MASK(8, 8, 8))) {
fore |= VTE_DIM_COLOR;
}
/* Reverse cell? */
- if (attr->reverse) {
+ if (attr->reverse()) {
swap (&fore, &back);
}
@@ -8934,7 +8928,7 @@ VteTerminalPrivate::determine_colors(VteCellAttr const* attr,
/* FIXME: This is dead code, this is not where we actually handle invisibile.
* Instead, draw_cells() is not called from draw_rows().
* That is required for the foreground to be transparent if so is the background. */
- if (attr->invisible) {
+ if (attr->invisible()) {
fore = back;
deco = VTE_DEFAULT_FG;
}
@@ -8985,15 +8979,9 @@ VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
uint32_t deco,
bool clear,
bool draw_default_bg,
- bool bold,
- bool italic,
- guint underline,
- bool strikethrough,
- bool overline,
- bool blink,
+ uint32_t attr,
bool hyperlink,
bool hilite,
- bool boxed,
int column_width,
int row_height)
{
@@ -9002,6 +8990,7 @@ VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
vte::color::rgb fg, bg, dc;
g_assert(n > 0);
+#if 0
_VTE_DEBUG_IF(VTE_DEBUG_CELLS) {
GString *str = g_string_new (NULL);
gchar *tmp;
@@ -9017,8 +9006,9 @@ VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
hyperlink, hilite, boxed);
g_free (tmp);
}
+#endif
- bold = bold && m_allow_bold;
+ auto bold = (attr & VTE_ATTR_BOLD) && m_allow_bold;
rgb_from_index<8, 8, 8>(fore, fg);
rgb_from_index<8, 8, 8>(back, bg);
// FIXMEchpe defer resolving deco color until we actually need to draw an underline?
@@ -9046,7 +9036,7 @@ VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
}
} while (i < n);
- if (blink) {
+ if (attr & VTE_ATTR_BLINK) {
/* Notify the caller that cells with the "blink" attribute were encountered (regardless of
* whether they're actually painted or skipped now), so that the caller can set up a timer
* to make them blink if it wishes to. */
@@ -9065,7 +9055,11 @@ VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
* so that if the descent of a letter crosses an underline of a different color,
* it's the letter's color that wins. Other kinds of decorations always have the
* same color as the text, so the order is irrelevant there. */
- if (underline | strikethrough | overline | hyperlink | hilite | boxed) {
+ if ((attr & (VTE_ATTR_UNDERLINE_MASK |
+ VTE_ATTR_STRIKETHROUGH_MASK |
+ VTE_ATTR_OVERLINE_MASK |
+ VTE_ATTR_BOXED_MASK)) |
+ hyperlink | hilite) {
i = 0;
do {
x = items[i].x;
@@ -9073,7 +9067,7 @@ VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
for (columns = 0; i < n && items[i].y == y; i++) {
columns += items[i].columns;
}
- switch (underline) {
+ switch (vte_attr_get_value(attr, VTE_ATTR_UNDERLINE_VALUE_MASK, VTE_ATTR_UNDERLINE_SHIFT)) {
case 1:
_vte_draw_draw_line(m_draw,
x,
@@ -9108,7 +9102,7 @@ VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
&dc, VTE_DRAW_OPAQUE);
break;
}
- if (strikethrough) {
+ if (attr & VTE_ATTR_STRIKETHROUGH) {
_vte_draw_draw_line(m_draw,
x,
y + m_strikethrough_position,
@@ -9117,7 +9111,7 @@ VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
VTE_LINE_WIDTH,
&fg, VTE_DRAW_OPAQUE);
}
- if (overline) {
+ if (attr & VTE_ATTR_OVERLINE) {
_vte_draw_draw_line(m_draw,
x,
y + m_overline_position,
@@ -9144,7 +9138,7 @@ VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
&fg, VTE_DRAW_OPAQUE);
}
}
- if (boxed) {
+ if (attr & VTE_ATTR_BOXED) {
_vte_draw_draw_rectangle(m_draw,
x, y,
MAX(0, (columns * column_width)),
@@ -9157,7 +9151,8 @@ VteTerminalPrivate::draw_cells(struct _vte_draw_text_request *items,
_vte_draw_text(m_draw,
items, n,
&fg, VTE_DRAW_OPAQUE,
- _vte_draw_get_style(bold, italic));
+ _vte_draw_get_style(attr & VTE_ATTR_BOLD,
+ attr & VTE_ATTR_ITALIC));
}
/* FIXME: we don't have a way to tell GTK+ what the default text attributes
@@ -9230,7 +9225,7 @@ VteTerminalPrivate::fudge_pango_colors(GSList *attributes,
(props[i].bg.green == 0) &&
(props[i].bg.blue == 0)) {
cells[i].attr.copy_colors(m_color_defaults.attr);
- cells[i].attr.reverse = TRUE;
+ cells[i].attr.set_reverse(true);
}
}
}
@@ -9270,7 +9265,7 @@ VteTerminalPrivate::apply_pango_attr(PangoAttribute *attr,
for (i = attr->start_index;
(i < attr->end_index) && (i < n_cells);
i++) {
- cells[i].attr.strikethrough = (ival != FALSE);
+ cells[i].attr.set_strikethrough(ival != FALSE);
}
break;
case PANGO_ATTR_UNDERLINE:
@@ -9279,7 +9274,7 @@ VteTerminalPrivate::apply_pango_attr(PangoAttribute *attr,
for (i = attr->start_index;
(i < attr->end_index) && (i < n_cells);
i++) {
- cells[i].attr.underline = (ival != PANGO_UNDERLINE_NONE);
+ cells[i].attr.set_underline(ival == PANGO_UNDERLINE_SINGLE ? 1 : 0);
}
break;
case PANGO_ATTR_WEIGHT:
@@ -9288,7 +9283,7 @@ VteTerminalPrivate::apply_pango_attr(PangoAttribute *attr,
for (i = attr->start_index;
(i < attr->end_index) && (i < n_cells);
i++) {
- cells[i].attr.bold = (ival >= PANGO_WEIGHT_BOLD);
+ cells[i].attr.set_bold(ival >= PANGO_WEIGHT_BOLD);
}
break;
default:
@@ -9375,14 +9370,9 @@ VteTerminalPrivate::draw_cells_with_attributes(struct _vte_draw_text_request *it
back,
deco,
TRUE, draw_default_bg,
- cells[j].attr.bold,
- cells[j].attr.italic,
- cells[j].attr.underline,
- cells[j].attr.strikethrough,
- cells[j].attr.overline,
- cells[j].attr.blink,
+ cells[j].attr.attr,
m_allow_hyperlink && cells[j].attr.hyperlink_idx != 0,
- FALSE, FALSE, column_width, height);
+ FALSE, column_width, height);
j += g_unichar_to_utf8(items[i].c, scratch_buf);
}
g_free(cells);
@@ -9407,11 +9397,9 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
vte::grid::row_t row, rows;
vte::grid::column_t i, j;
long x, y;
- guint fore, nfore, back, nback, deco, ndeco, underline, nunderline;
- gboolean bold, nbold, italic, nitalic,
- hyperlink, nhyperlink, hilite, nhilite,
- selected, nselected, strikethrough, nstrikethrough,
- overline, noverline, invisible, ninvisible, blink, nblink;
+ guint fore, nfore, back, nback, deco, ndeco;
+ gboolean hyperlink, nhyperlink, hilite, nhilite,
+ selected, nselected;
guint item_count;
const VteCell *cell;
VteRowData const* row_data;
@@ -9432,7 +9420,7 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
if (row_data != NULL) {
cell = _vte_row_data_get (row_data, i);
if (cell != NULL) {
- while (cell->attr.fragment && i > 0) {
+ while (cell->attr.fragment() && i > 0) {
cell = _vte_row_data_get (row_data, --i);
}
}
@@ -9444,8 +9432,8 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
selected = cell_is_selected(i, row);
determine_colors(cell, selected, &fore, &back, &deco);
- bold = cell && cell->attr.bold;
- j = i + (cell ? cell->attr.columns : 1);
+ bool bold = cell && cell->attr.bold();
+ j = i + (cell ? cell->attr.columns() : 1);
while (j < end_column){
/* Retrieve the cell. */
@@ -9453,7 +9441,7 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
/* Don't render fragments of multicolumn characters
* which have the same attributes as the initial
* portions. */
- if (cell != NULL && cell->attr.fragment) {
+ if (cell != NULL && cell->attr.fragment()) {
j++;
continue;
}
@@ -9465,8 +9453,8 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
if (nback != back) {
break;
}
- bold = cell && cell->attr.bold;
- j += cell ? cell->attr.columns : 1;
+ bold = cell && cell->attr.bold();
+ j += cell ? cell->attr.columns() : 1;
}
if (back != VTE_DEFAULT_BG) {
vte::color::rgb bg;
@@ -9532,7 +9520,7 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
if (cell == NULL) {
goto fg_skip_row;
}
- while (cell->attr.fragment && i > 0)
+ while (cell->attr.fragment() && i > 0)
cell = _vte_row_data_get (row_data, --i);
/* Walk the line. */
@@ -9542,13 +9530,13 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
if (cell == NULL) {
goto fg_skip_row;
}
- while (cell->c == 0 || cell->attr.invisible ||
+ while (cell->c == 0 || cell->attr.invisible() ||
(cell->c == ' ' &&
- !cell->attr.underline &&
- !cell->attr.strikethrough &&
- !cell->attr.overline &&
+ cell->attr.has_none(VTE_ATTR_UNDERLINE_MASK |
+ VTE_ATTR_STRIKETHROUGH_MASK |
+ VTE_ATTR_OVERLINE_MASK) &&
(!m_allow_hyperlink || cell->attr.hyperlink_idx == 0)) ||
- cell->attr.fragment) {
+ cell->attr.fragment()) {
if (++i >= end_column) {
goto fg_skip_row;
}
@@ -9560,14 +9548,10 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
/* Find the colors for this cell. */
selected = cell_is_selected(i, row);
determine_colors(cell, selected, &fore, &back, &deco);
- underline = cell->attr.underline;
- strikethrough = cell->attr.strikethrough;
- overline = cell->attr.overline;
- invisible = cell->attr.invisible;
+
+ uint32_t const attr = cell->attr.attr;
+
hyperlink = (m_allow_hyperlink && cell->attr.hyperlink_idx != 0);
- bold = cell->attr.bold;
- italic = cell->attr.italic;
- blink = cell->attr.blink;
if (cell->attr.hyperlink_idx != 0 && cell->attr.hyperlink_idx == m_hyperlink_hover_idx) {
hilite = true;
} else if (m_hyperlink_hover_idx == 0 && m_show_match) {
@@ -9577,7 +9561,7 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
}
items[0].c = cell->c;
- items[0].columns = cell->attr.columns;
+ items[0].columns = cell->attr.columns();
items[0].x = start_x + i * column_width;
items[0].y = y;
j = i + items[0].columns;
@@ -9593,7 +9577,7 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
}
/* Ignore the attributes on a fragment, the attributes
* of the preceding character cell should apply. */
- if (cell->attr.fragment) {
+ if (cell->attr.fragment()) {
j++;
continue;
}
@@ -9601,7 +9585,10 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
/* only break the run if we
* are drawing attributes
*/
- if (underline || strikethrough || overline || hyperlink || hilite) {
+ if ((attr & (VTE_ATTR_UNDERLINE_MASK |
+ VTE_ATTR_STRIKETHROUGH_MASK |
+ VTE_ATTR_OVERLINE_MASK)) |
+ hyperlink | hilite) {
break;
} else {
j++;
@@ -9619,39 +9606,24 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
if (ndeco != deco) {
break;
}
- nbold = cell->attr.bold;
- if (nbold != bold) {
- break;
- }
- nitalic = cell->attr.italic;
- if (nitalic != italic) {
- break;
- }
- /* Break up underlined/not-underlined text. */
- nunderline = cell->attr.underline;
- if (nunderline != underline) {
- break;
- }
- nstrikethrough = cell->attr.strikethrough;
- if (nstrikethrough != strikethrough) {
- break;
- }
- noverline = cell->attr.overline;
- if (noverline != overline) {
- break;
- }
- nblink = cell->attr.blink;
- if (nblink != blink) {
+
+ /* Bold, italic, underline, strikethrough,
+ * overline, blink, or invisible differ;
+ * break the run.
+ */
+ if ((cell->attr.attr ^ attr) & (VTE_ATTR_BOLD_MASK |
+ VTE_ATTR_ITALIC_MASK |
+ VTE_ATTR_UNDERLINE_MASK |
+ VTE_ATTR_STRIKETHROUGH_MASK |
+ VTE_ATTR_OVERLINE_MASK |
+ VTE_ATTR_BLINK_MASK |
+ VTE_ATTR_INVISIBLE_MASK))
break;
- }
+
nhyperlink = (m_allow_hyperlink && cell->attr.hyperlink_idx != 0);
if (nhyperlink != hyperlink) {
break;
}
- ninvisible = cell->attr.invisible;
- if (ninvisible != invisible) {
- break;
- }
/* Break up matched/not-matched text. */
nhilite = false;
if (cell->attr.hyperlink_idx != 0 && cell->attr.hyperlink_idx == m_hyperlink_hover_idx) {
@@ -9664,7 +9636,7 @@ VteTerminalPrivate::draw_rows(VteScreen *screen_,
}
/* Add this cell to the draw list. */
items[item_count].c = cell->c;
- items[item_count].columns = cell->attr.columns;
+ items[item_count].columns = cell->attr.columns();
items[item_count].x = start_x + j * column_width;
items[item_count].y = y;
j += items[item_count].columns;
@@ -9694,7 +9666,7 @@ fg_next_row:
j = start_column;
cell = _vte_row_data_get (row_data, j);
} while (cell == NULL);
- while (cell->attr.fragment && j > 0) {
+ while (cell->attr.fragment() && j > 0) {
cell = _vte_row_data_get (row_data, --j);
}
} while (TRUE);
@@ -9704,8 +9676,8 @@ fg_draw:
items,
item_count,
fore, back, deco, FALSE, FALSE,
- bold, italic, underline, strikethrough,
- overline, blink, hyperlink, hilite, FALSE,
+ attr /* & VTE_ATTR_ALL_MASK */,
+ hyperlink, hilite,
column_width, row_height);
item_count = 1;
/* We'll need to continue at the first cell which didn't
@@ -9838,18 +9810,18 @@ VteTerminalPrivate::paint_cursor()
/* Find the first cell of the character "under" the cursor.
* This is for CJK. For TAB, paint the cursor where it really is. */
auto cell = find_charcell(col, drow);
- while (cell != NULL && cell->attr.fragment && cell->c != '\t' && col > 0) {
+ while (cell != NULL && cell->attr.fragment() && cell->c != '\t' && col > 0) {
col--;
cell = find_charcell(col, drow);
}
/* Draw the cursor. */
item.c = (cell && cell->c) ? cell->c : ' ';
- item.columns = item.c == '\t' ? 1 : cell ? cell->attr.columns : 1;
+ item.columns = item.c == '\t' ? 1 : cell ? cell->attr.columns() : 1;
item.x = col * width;
item.y = row_to_pixel(drow);
if (cell && cell->c != 0) {
- style = _vte_draw_get_style(cell->attr.bold, cell->attr.italic);
+ style = _vte_draw_get_style(cell->attr.bold(), cell->attr.italic());
}
selected = cell_is_selected(col, drow);
@@ -9899,7 +9871,7 @@ VteTerminalPrivate::paint_cursor()
if (cell && cell->c != 0 && cell->c != ' ' && cell->c != '\t') {
int l, r;
- _vte_draw_get_char_edges (m_draw, cell->c, cell->attr.columns, style, &l, &r);
+ _vte_draw_get_char_edges (m_draw, cell->c, cell->attr.columns(), style, &l, &r);
left = MIN(left, l);
right = MAX(right, r);
}
@@ -9918,7 +9890,7 @@ VteTerminalPrivate::paint_cursor()
cursor_width = item.columns * width;
if (cell && cell->c != 0 && cell->c != ' ' && cell->c != '\t') {
int r;
- _vte_draw_get_char_edges (m_draw, cell->c, cell->attr.columns, style, NULL, &r);
+ _vte_draw_get_char_edges (m_draw, cell->c, cell->attr.columns(), style, NULL, &r);
cursor_width = MAX(cursor_width, r);
}
@@ -9933,15 +9905,9 @@ VteTerminalPrivate::paint_cursor()
draw_cells(
&item, 1,
fore, back, deco, TRUE, FALSE,
- cell->attr.bold,
- cell->attr.italic,
- cell->attr.underline,
- cell->attr.strikethrough,
- cell->attr.overline,
- cell->attr.blink,
+ cell->attr.attr,
m_allow_hyperlink && cell->attr.hyperlink_idx != 0,
FALSE,
- FALSE,
width,
height);
}
@@ -10025,15 +9991,9 @@ VteTerminalPrivate::paint_im_preedit_string()
fore, back, deco,
TRUE, /* clear */
TRUE, /* draw_default_bg */
- FALSE, /* bold */
- FALSE, /* italic */
- 0, /* underline */
- FALSE, /* strikethrough */
- FALSE, /* overline */
- FALSE, /* blink */
+ VTE_ATTR_NONE | VTE_ATTR_BOXED,
FALSE, /* hyperlink */
FALSE, /* hilite */
- TRUE, /* boxed */
width, height);
}
g_free(items);
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 41c1824e..f25c87ec 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -848,15 +848,9 @@ public:
uint32_t deco,
bool clear,
bool draw_default_bg,
- bool bold,
- bool italic,
- guint underline,
- bool strikethrough,
- bool overline,
- bool blink,
+ uint32_t attr,
bool hyperlink,
bool hilite,
- bool boxed,
int column_width,
int row_height);
void fudge_pango_colors(GSList *attributes,
diff --git a/src/vterowdata.h b/src/vterowdata.h
index d600ba9f..410219a5 100644
--- a/src/vterowdata.h
+++ b/src/vterowdata.h
@@ -21,19 +21,18 @@
#ifndef vterowdata_h_included
#define vterowdata_h_included
-#include <cstdint>
-
#include <string.h>
#include "vteunistr.h"
#include "vtemacros.h"
#include "vtedefines.hh"
+
+#include "attr.hh"
#include "color-triple.hh"
G_BEGIN_DECLS
-#define VTE_TAB_WIDTH_BITS 4 /* Has to be able to store the value of 8. */
-#define VTE_TAB_WIDTH_MAX ((1 << VTE_TAB_WIDTH_BITS) - 1)
+#define VTE_TAB_WIDTH_MAX ((1 << VTE_ATTR_COLUMNS_BITS) - 1)
#define VTE_CELL_ATTR_COMMON_BYTES 12 /* The number of common bytes in VteCellAttr and VteStreamCellAttr */
@@ -45,22 +44,30 @@ G_BEGIN_DECLS
* Also don't forget to update basic_cell below!
*/
+#define CELL_ATTR_BOOL(lname,uname) \
+ inline constexpr void set_##lname(bool value) \
+ { \
+ vte_attr_set_bool(&attr, VTE_ATTR_##uname##_MASK, value); \
+ } \
+ \
+ inline constexpr bool lname() const \
+ { \
+ return vte_attr_get_bool(attr, VTE_ATTR_##uname##_SHIFT); \
+ }
+
+#define CELL_ATTR_UINT(lname,uname) \
+ inline constexpr void set_##lname(unsigned int value) \
+ { \
+ vte_attr_set_value(&attr, VTE_ATTR_##uname##_MASK, VTE_ATTR_##uname##_SHIFT, value); \
+ } \
+ \
+ inline constexpr uint32_t lname() const \
+ { \
+ return vte_attr_get_value(attr, VTE_ATTR_##uname##_VALUE_MASK, VTE_ATTR_##uname##_SHIFT); \
+ }
+
typedef struct _VTE_GNUC_PACKED VteCellAttr {
- uint32_t fragment : 1; /* A continuation cell. */
- uint32_t columns : VTE_TAB_WIDTH_BITS; /* Number of visible columns
- * (as determined by g_unicode_iswide(c)).
- * Also abused for tabs; bug 353610
- */
- uint32_t bold : 1;
- uint32_t italic : 1;
- uint32_t underline : 2; /* 0: none, 1: single, 2: double, 3: curly */
- uint32_t strikethrough : 1;
- uint32_t reverse : 1;
- uint32_t blink : 1;
- uint32_t dim : 1; /* also known as faint, half intensity etc. */
- uint32_t invisible : 1;
- uint32_t overline : 1;
- uint32_t padding_unused : 17;
+ uint32_t attr;
/* 4-byte boundary (8-byte boundary in VteCell) */
uint64_t m_colors; /* fore, back and deco (underline) colour */
@@ -74,6 +81,8 @@ typedef struct _VTE_GNUC_PACKED VteCellAttr {
(currently the height rounded up to the next power of two, times width)
for supported VTE sizes, and update VTE_HYPERLINK_IDX_TARGET_IN_STREAM. */
+ /* Methods */
+
inline constexpr uint64_t colors() const { return m_colors; }
inline constexpr void copy_colors(VteCellAttr const& other)
@@ -96,6 +105,39 @@ typedef struct _VTE_GNUC_PACKED VteCellAttr {
CELL_ATTR_COLOR(back)
CELL_ATTR_COLOR(deco)
#undef CELL_ATTR_COLOR
+
+ inline constexpr bool has_any(uint32_t mask) const
+ {
+ return !!(attr & mask);
+ }
+
+ inline constexpr bool has_all(uint32_t mask) const
+ {
+ return (attr & mask) == mask;
+ }
+
+ inline constexpr bool has_none(uint32_t mask) const
+ {
+ return !(attr & mask);
+ }
+
+ inline constexpr void unset(uint32_t mask)
+ {
+ attr &= ~mask;
+ }
+
+ CELL_ATTR_UINT(columns, COLUMNS)
+ CELL_ATTR_BOOL(fragment, FRAGMENT)
+ CELL_ATTR_BOOL(bold, BOLD)
+ CELL_ATTR_BOOL(italic, ITALIC)
+ CELL_ATTR_UINT(underline, UNDERLINE)
+ CELL_ATTR_BOOL(strikethrough, STRIKETHROUGH)
+ CELL_ATTR_BOOL(overline, OVERLINE)
+ CELL_ATTR_BOOL(reverse, REVERSE)
+ CELL_ATTR_BOOL(blink, BLINK)
+ CELL_ATTR_BOOL(dim, DIM)
+ CELL_ATTR_BOOL(invisible, INVISIBLE)
+ /* ATTR_BOOL(boxed, BOXED) */
} VteCellAttr;
G_STATIC_ASSERT (sizeof (VteCellAttr) == 16);
G_STATIC_ASSERT (offsetof (VteCellAttr, hyperlink_idx) == VTE_CELL_ATTR_COMMON_BYTES);
@@ -108,19 +150,24 @@ G_STATIC_ASSERT (offsetof (VteCellAttr, hyperlink_idx) == VTE_CELL_ATTR_COMMON_B
*/
typedef struct _VTE_GNUC_PACKED _VteStreamCellAttr {
- uint32_t fragment : 1;
- uint32_t columns : VTE_TAB_WIDTH_BITS;
- uint32_t remaining_main_attributes_1 : 27; /* All the non-hyperlink related attributes from VteCellAttr, part 1.
- We don't individually access them in the stream, so there's
- no point in repeating each field separately. */
+ uint32_t attr; /* Same as VteCellAttr. We only access columns
+ * and fragment, however.
+ */
/* 4-byte boundary */
uint64_t colors;
/* 12-byte boundary */
guint16 hyperlink_length; /* make sure it fits VTE_HYPERLINK_TOTAL_LENGTH_MAX */
+
+ /* Methods */
+ CELL_ATTR_UINT(columns, COLUMNS)
+ CELL_ATTR_BOOL(fragment, FRAGMENT)
} VteStreamCellAttr;
G_STATIC_ASSERT (sizeof (VteStreamCellAttr) == 14);
G_STATIC_ASSERT (offsetof (VteStreamCellAttr, hyperlink_length) == VTE_CELL_ATTR_COMMON_BYTES);
+#undef CELL_ATTR_BOOL
+#undef CELL_ATTR_UINT
+
/*
* VteCell: A single cell's data
*/
@@ -134,18 +181,7 @@ G_STATIC_ASSERT (sizeof (VteCell) == 20);
static const VteCell basic_cell = {
0,
{
- 0, /* fragment */
- 1, /* columns */
- 0, /* bold */
- 0, /* italic */
- 0, /* underline */
- 0, /* strikethrough */
- 0, /* reverse */
- 0, /* blink */
- 0, /* dim */
- 0, /* invisible */
- 0, /* overline */
- 0, /* padding_unused */
+ VTE_ATTR_DEFAULT, /* attr */
VTE_COLOR_TRIPLE_INIT_DEFAULT, /* colors */
0, /* hyperlink_idx */
}
diff --git a/src/vteseq.cc b/src/vteseq.cc
index 3f25b1b9..3c651107 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -1724,7 +1724,7 @@ VteTerminalPrivate::move_cursor_tab()
glong i;
VteCell *cell = _vte_row_data_get_writable (rowdata, col);
VteCell tab = *cell;
- tab.attr.columns = newcol - col;
+ tab.attr.set_columns(newcol - col);
tab.c = '\t';
/* Save tab char */
*cell = tab;
@@ -1732,8 +1732,8 @@ VteTerminalPrivate::move_cursor_tab()
for (i = col + 1; i < newcol; i++) {
cell = _vte_row_data_get_writable (rowdata, i);
cell->c = '\t';
- cell->attr.columns = 1;
- cell->attr.fragment = 1;
+ cell->attr.set_columns(1);
+ cell->attr.set_fragment(true);
}
}
@@ -1879,7 +1879,7 @@ VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
switch (param0) {
case 4:
if (subparams.number_at(1, param1) && param1 >= 0 && param1 <= 3)
- m_defaults.attr.underline = param1;
+ m_defaults.attr.set_underline(param1);
break;
case 38: {
unsigned int index = 1;
@@ -1916,53 +1916,52 @@ VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
reset_default_attributes(false);
break;
case 1:
- m_defaults.attr.bold = 1;
+ m_defaults.attr.set_bold(true);
break;
case 2:
- m_defaults.attr.dim = 1;
+ m_defaults.attr.set_dim(true);
break;
case 3:
- m_defaults.attr.italic = 1;
+ m_defaults.attr.set_italic(true);
break;
case 4:
- m_defaults.attr.underline = 1;
+ m_defaults.attr.set_underline(1);
break;
case 5:
- m_defaults.attr.blink = 1;
+ m_defaults.attr.set_blink(true);
break;
case 7:
- m_defaults.attr.reverse = 1;
+ m_defaults.attr.set_reverse(true);
break;
case 8:
- m_defaults.attr.invisible = 1;
+ m_defaults.attr.set_invisible(true);
break;
case 9:
- m_defaults.attr.strikethrough = 1;
+ m_defaults.attr.set_strikethrough(true);
break;
case 21:
- m_defaults.attr.underline = 2;
+ m_defaults.attr.set_underline(2);
break;
case 22: /* ECMA 48. */
- m_defaults.attr.bold = 0;
- m_defaults.attr.dim = 0;
+ m_defaults.attr.unset(VTE_ATTR_BOLD_MASK | VTE_ATTR_DIM_MASK);
break;
case 23:
- m_defaults.attr.italic = 0;
+ m_defaults.attr.set_italic(false);
break;
case 24:
- m_defaults.attr.underline = 0;
+ m_defaults.attr.set_underline(0);
break;
case 25:
- m_defaults.attr.blink = 0;
+ m_defaults.attr.set_blink(false);
break;
case 27:
- m_defaults.attr.reverse = 0;
+ m_defaults.attr.set_reverse(false);
break;
case 28:
- m_defaults.attr.invisible = 0;
+ m_defaults.attr.set_invisible(false);
break;
case 29:
- m_defaults.attr.strikethrough = 0;
+ m_defaults.attr.set_strikethrough(false);
break;
case 30:
case 31:
@@ -2033,10 +2032,10 @@ VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
m_defaults.attr.set_back(VTE_DEFAULT_BG);
break;
case 53:
- m_defaults.attr.overline = 1;
+ m_defaults.attr.set_overline(true);
break;
case 55:
- m_defaults.attr.overline = 0;
+ m_defaults.attr.set_overline(false);
break;
/* case 58: was handled above at 38 to avoid code duplication */
case 59:
@@ -2682,7 +2681,7 @@ VteTerminalPrivate::seq_screen_alignment_test(vte::parser::Params const& params)
VteCell cell;
cell.c = 'E';
cell.attr = basic_cell.attr;
- cell.attr.columns = 1;
+ cell.attr.set_columns(1);
_vte_row_data_fill(rowdata, &cell, m_column_count);
emit_text_inserted();
}