[vte/wip/egmont/bidi: 4/7] widget, bidi: Display according to the BiDi mapping
- From: Egmont Koblinger <egmontkob src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte/wip/egmont/bidi: 4/7] widget, bidi: Display according to the BiDi mapping
- Date: Tue, 4 Jun 2019 13:03:37 +0000 (UTC)
commit 9a7ff95531bb62f4dbf07332937e6b72d3fbeb08
Author: Egmont Koblinger <egmont gmail com>
Date: Sat Jun 1 15:47:16 2019 +0200
widget,bidi: Display according to the BiDi mapping
Display each row according to the BiDi treatment (shuffling, basic Arabic
shaping) it received.
src/vte.cc | 247 ++++++++++++++++++++++++++++++++++++++++++-----------
src/vtedraw.cc | 6 ++
src/vtedraw.hh | 2 +
src/vteinternal.hh | 8 +-
4 files changed, 208 insertions(+), 55 deletions(-)
---
diff --git a/src/vte.cc b/src/vte.cc
index 98d73b6a..3a2dfd3e 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -36,6 +36,7 @@
#include <vte/vte.h>
#include "vteinternal.hh"
+#include "bidi.hh"
#include "buffer.h"
#include "debug.h"
#include "vtedraw.hh"
@@ -1623,9 +1624,22 @@ Terminal::grid_coords_from_view_coords(vte::view::coords const& pos) const
vte::grid::row_t row = pixel_to_row(pos.y);
+ /* BiDi: convert to logical column. */
+ vte::base::BidiRow const* bidirow = m_ringview.get_bidirow(confine_grid_row(row));
+ col = bidirow->vis2log(col);
+
return vte::grid::coords(row, col);
}
+vte::grid::row_t
+Terminal::confine_grid_row(vte::grid::row_t const& row) const
+{
+ auto first_row = first_displayed_row();
+ auto last_row = last_displayed_row();
+
+ return CLAMP(row, first_row, last_row);
+}
+
/*
* Terminal::confined_grid_coords_from_view_coords:
* @pos: the view coordinates
@@ -1687,34 +1701,47 @@ Terminal::confine_grid_coords(vte::grid::coords const& rowcol) const
/*
* Track mouse click and drag positions (the "origin" and "last" coordinates) with half cell accuracy,
- * that is, know whether the event occurred over the left or right half of the cell.
+ * that is, know whether the event occurred over the left/start or right/end half of the cell.
* This is required because some selection modes care about the cell over which the event occurred,
* while some care about the closest boundary between cells.
*
* Storing the actual view coordinates would become problematic when the font size changes (bug 756058),
* and would cause too much work when the mouse moves within the half cell.
*
- * Left margin or anything further to the left is denoted by column -1's right half,
- * right margin or anything further to the right is denoted by column m_column_count's left half.
+ * Left/start margin or anything further to the left/start is denoted by column -1's right half,
+ * right/end margin or anything further to the right/end is denoted by column m_column_count's left half.
+ *
+ * BiDi: returns logical position (start or end) for normal selection modes, visual position (left or
+ * right) for block mode.
*/
vte::grid::halfcoords
Terminal::selection_grid_halfcoords_from_view_coords(vte::view::coords const& pos) const
{
vte::grid::row_t row = pixel_to_row(pos.y);
- vte::grid::halfcolumn_t halfcolumn;
+ vte::grid::column_t col;
+ vte::grid::half_t half;
if (pos.x < 0) {
- halfcolumn.set_column(-1);
- halfcolumn.set_half(1);
+ col = -1;
+ half = 1;
} else if (pos.x >= m_column_count * m_cell_width) {
- halfcolumn.set_column(m_column_count);
- halfcolumn.set_half(0);
+ col = m_column_count;
+ half = 0;
} else {
- halfcolumn.set_column(pos.x / m_cell_width);
- halfcolumn.set_half((pos.x * 2 / m_cell_width) % 2);
+ col = pos.x / m_cell_width;
+ half = (pos.x * 2 / m_cell_width) % 2;
+ }
+
+ if (!m_selection_block_mode) {
+ /* BiDi: convert from visual to logical half column. */
+ vte::base::BidiRow const* bidirow = m_ringview.get_bidirow(confine_grid_row(row));
+
+ if (bidirow->vis_is_rtl(col))
+ half = 1 - half;
+ col = bidirow->vis2log(col);
}
- return { row, halfcolumn };
+ return { row, vte::grid::halfcolumn_t(col, half) };
}
/*
@@ -5305,7 +5332,7 @@ Terminal::line_is_wrappable(vte::grid::row_t row) const
* In block mode, similarly to char mode, we care about vertical character boundary. (This is somewhat
* debatable, as results in asymmetrical behavior along the two axes: a rectangle can disappear by
* becoming zero wide, but not zero high.) We cannot take care of CJKs at the endpoints now because CJKs
- * can cross the boundary in any included row. Taking care of them needs to go to cell_is_selected().
+ * can cross the boundary in any included row. Taking care of them needs to go to cell_is_selected_vis().
* We don't care about used vs. unused cells either. The event coordinate is simply rounded to the
* nearest vertical cell boundary.
*/
@@ -5604,21 +5631,29 @@ Terminal::modify_selection (vte::view::coords const& pos)
resolve_selection();
}
-/* Check if a cell is selected or not. */
+/* Check if a cell is selected or not. BiDi: the coordinate is visual. */
bool
-Terminal::cell_is_selected(vte::grid::column_t col,
- vte::grid::row_t row) const
+Terminal::cell_is_selected_vis(vte::grid::column_t col,
+ vte::grid::row_t row) const
{
if (m_selection_block_mode) {
/* In block mode, make sure CJKs and TABs aren't cut in half. */
+ /* BiDi: convert to logical column... */
+ vte::base::BidiRow const* bidirow = m_ringview.get_bidirow(row);
+ col = bidirow->vis2log(col);
while (col > 0) {
VteCell const* cell = find_charcell(col, row);
if (!cell || !cell->attr.fragment())
break;
col--;
}
+ /* ... and back to visual. */
+ col = bidirow->log2vis(col);
return m_selection_resolved.box_contains ({ row, col });
} else {
+ /* BiDi: convert to logical column. */
+ vte::base::BidiRow const* bidirow = m_ringview.get_bidirow(row);
+ col = bidirow->vis2log(col);
/* In normal modes, resolve_selection() made sure to generate such boundaries for
m_selection_resolved. */
return m_selection_resolved.contains ({ row, col });
}
@@ -6080,6 +6115,10 @@ Terminal::match_hilite_update()
glong col = pos.x / m_cell_width;
glong row = pixel_to_row(pos.y);
+ /* BiDi: convert to logical column. */
+ vte::base::BidiRow const* bidirow = m_ringview.get_bidirow(confine_grid_row(row));
+ col = bidirow->vis2log(col);
+
_vte_debug_print(VTE_DEBUG_EVENTS,
"Match hilite update (%ld, %ld) -> %ld, %ld\n",
pos.x, pos.y, col, row);
@@ -6284,6 +6323,9 @@ Terminal::get_text(vte::grid::row_t start_row,
GString *string;
struct _VteCharAttributes attr;
vte::color::rgb fore, back;
+ vte::base::RingView *ringview = nullptr;
+ vte::base::BidiRow const *bidirow = nullptr;
+ vte::grid::column_t col_vis;
if (attributes)
g_array_set_size (attributes, 0);
@@ -6294,26 +6336,50 @@ Terminal::get_text(vte::grid::row_t start_row,
if (start_col < 0)
start_col = 0;
- vte::grid::column_t next_first_column = block ? start_col : 0;
- vte::grid::column_t col = start_col;
+ if (m_allow_bidi && block) {
+ /* Rectangular selection operates on the visual contents, not the logical.
+ * m_ringview corresponds to the currently onscreen bits, therefore does not
+ * necessarily include the entire selection. Also we want m_ringview's size
+ * to be limited, even if the user selects a giant rectangle.
+ * So use a new ringview for the selection. */
+ ringview = new vte::base::RingView();
+ ringview->set_ring(m_screen->row_data);
+ ringview->set_rows(start_row, end_row - start_row + 1);
+ ringview->set_width(m_column_count);
+ ringview->update();
+ }
+
+ vte::grid::column_t col = block ? 0 : start_col;
vte::grid::row_t row;
- for (row = start_row; row < end_row + 1; row++, col = next_first_column) {
+ for (row = start_row; row < end_row + 1; row++, col = 0) {
VteRowData const* row_data = find_row_data(row);
gsize last_empty, last_nonempty;
vte::grid::column_t last_emptycol, last_nonemptycol;
- vte::grid::column_t line_last_column = (block || row == end_row) ? end_col : G_MAXLONG;
+ vte::grid::column_t line_last_column = (!block && row == end_row) ? end_col : m_column_count;
last_empty = last_nonempty = string->len;
last_emptycol = last_nonemptycol = -1;
attr.row = row;
- attr.column = col;
+ attr.column = col; // FIXME is attr.column supposed to contain logical or visual? What is
it used for?
pcell = NULL;
if (row_data != NULL) {
+ bidirow = ringview ? ringview->get_bidirow(row) : nullptr;
while (col < line_last_column &&
(pcell = _vte_row_data_get (row_data, col))) {
- attr.column = col;
+ /* In block mode, we scan each row from its very beginning to its very end
in logical order,
+ * and here filter out the characters that are visually outside of the
block. */
+ if (bidirow) {
+ col_vis = bidirow->log2vis(col);
+ // FIXME handle CJK and friends consistently with cell_is_selected().
+ if (col_vis < start_col || col_vis >= end_col) {
+ col++;
+ continue;
+ }
+ }
+
+ attr.column = col; // FIXME ditto
/* If it's not part of a multi-column character,
* and passes the selection criterion, add it to
@@ -6412,6 +6478,8 @@ Terminal::get_text(vte::grid::row_t start_row,
}
}
+ delete ringview;
+
/* Sanity check. */
if (attributes != nullptr)
g_assert_cmpuint(string->len, ==, attributes->len);
@@ -9036,6 +9104,10 @@ Terminal::ringview_update()
m_ringview.update ();
}
+/* XXX tmp hack */
+#define _vte_row_data_get_visual(row_data_p, bidimap, col) \
+ row_data_p == nullptr ? nullptr : _vte_row_data_get(row_data_p, bidimap->vis2log(col))
+
/* Paint the contents of a given row at the given location. Take advantage
* of multiple-draw APIs by finding runs of characters with identical
* attributes and bundling them together. */
@@ -9050,15 +9122,17 @@ Terminal::draw_rows(VteScreen *screen_,
{
struct _vte_draw_text_request *items;
vte::grid::row_t row;
- vte::grid::column_t i, j, col;
+ vte::grid::column_t i, j, lcol, vcol;
int y;
guint fore = VTE_DEFAULT_FG, nfore, back = VTE_DEFAULT_BG, nback, deco = VTE_DEFAULT_FG, ndeco;
gboolean hyperlink = FALSE, nhyperlink, hilite = FALSE, nhilite;
gboolean selected;
+ gboolean nrtl = FALSE, rtl; /* for debugging */
uint32_t attr = 0, nattr;
guint item_count;
const VteCell *cell;
VteRowData const* row_data;
+ vte::base::BidiRow const* bidirow;
auto const column_count = m_column_count;
uint32_t const attr_mask = m_allow_bold ? ~0 : ~VTE_ATTR_BOLD_MASK;
@@ -9086,25 +9160,28 @@ Terminal::draw_rows(VteScreen *screen_,
if (row_data == nullptr)
continue; /* Skip row. FIXME: just paint this row empty? */
+ bidirow = m_ringview.get_bidirow(row);
i = j = 0;
/* Walk the line.
* Locate runs of identical bg colors within a row, and paint each run as a single
rectangle. */
do {
/* Get the first cell's contents. */
- cell = row_data ? _vte_row_data_get (row_data, i) : nullptr;
+ cell = row_data ? _vte_row_data_get_visual (row_data, bidirow, i) : nullptr;
/* Find the colors for this cell. */
- selected = cell_is_selected(i, row);
+ selected = cell_is_selected_vis(i, row);
determine_colors(cell, selected, &fore, &back, &deco);
+ rtl = bidirow->vis_is_rtl(i);
while (++j < column_count) {
/* Retrieve the next cell. */
- cell = row_data ? _vte_row_data_get (row_data, j) : nullptr;
+ cell = row_data ? _vte_row_data_get_visual (row_data, bidirow, j) : nullptr;
/* Resolve attributes to colors where possible and
* compare visual attributes to the first character
* in this chunk. */
- selected = cell_is_selected(j, row);
+ selected = cell_is_selected_vis(j, row);
determine_colors(cell, selected, &nfore, &nback, &ndeco);
- if (nback != back) {
+ nrtl = bidirow->vis_is_rtl(j);
+ if (nback != back || (_vte_debug_on (VTE_DEBUG_BIDI) && nrtl != rtl)) {
break;
}
}
@@ -9118,6 +9195,21 @@ Terminal::draw_rows(VteScreen *screen_,
row_height,
&bg, VTE_DRAW_OPAQUE);
}
+ if (G_UNLIKELY (_vte_debug_on (VTE_DEBUG_BIDI) && rtl)) {
+ /* Debug: Highlight RTL letters with a slightly different background. */
+ vte::color::rgb bg;
+ rgb_from_index<8, 8, 8>(back, bg);
+ bg.red = 0xC000 + (bg.red - 0xC000) / 2;
+ bg.green = 0xC000 + (bg.green - 0xC000) / 2;
+ bg.blue = 0xC000 + (bg.blue - 0xC000) / 2;
+ _vte_draw_fill_rectangle (
+ m_draw,
+ i * column_width,
+ y + row_height / 8,
+ (j - i) * column_width,
+ row_height * 3 / 4,
+ &bg, VTE_DRAW_OPAQUE);
+ }
/* We'll need to continue at the first cell which didn't
* match the first one in this set. */
i = j;
@@ -9148,16 +9240,17 @@ Terminal::draw_rows(VteScreen *screen_,
/* Ensure that drawing is restricted to the cell (plus the overdraw area) */
_vte_draw_autoclip_t clipper{m_draw, &rect};
- /* Walk the line.
+ bidirow = m_ringview.get_bidirow(row);
+
+ /* Walk the line in logical order.
* Locate runs of identical attributes within a row, and draw each run using a single
draw_cells() call. */
item_count = 0;
- for (col = 0; col < column_count; ) {
+ for (lcol = 0; lcol < row_data->len && lcol < column_count; ) {
+ vcol = bidirow->log2vis(lcol);
+
/* Get the character cell's contents. */
- cell = _vte_row_data_get (row_data, col);
- if (cell == NULL) {
- /* There'll be no more real cells in this row. */
- break;
- }
+ cell = _vte_row_data_get (row_data, lcol);
+ g_assert(cell != nullptr);
nhyperlink = (m_allow_hyperlink && cell->attr.hyperlink_idx != 0);
if (cell->c == 0 ||
@@ -9169,17 +9262,17 @@ Terminal::draw_rows(VteScreen *screen_,
cell->attr.fragment() ||
cell->attr.invisible()) {
/* Skip empty or fragment cell. */
- col++;
+ lcol++;
continue;
}
/* Find the colors for this cell. */
nattr = cell->attr.attr;
- selected = cell_is_selected(col, row);
+ selected = cell_is_selected_vis(vcol, row);
determine_colors(cell, selected, &nfore, &nback, &ndeco);
nhilite = (nhyperlink && cell->attr.hyperlink_idx == m_hyperlink_hover_idx) ||
- (!nhyperlink && m_match != nullptr && m_match_span.contains(row, col));
+ (!nhyperlink && m_match != nullptr && m_match_span.contains(row, lcol));
/* See if it no longer fits the run. */
if (item_count > 0 &&
@@ -9206,16 +9299,16 @@ Terminal::draw_rows(VteScreen *screen_,
/* Combine with subsequent spacing marks. */
vteunistr c = cell->c;
- j = col + cell->attr.columns();
- if (G_UNLIKELY (col == 0 && g_unichar_ismark (_vte_unistr_get_base (cell->c)))) {
+ j = lcol + cell->attr.columns();
+ if (G_UNLIKELY (lcol == 0 && g_unichar_ismark (_vte_unistr_get_base (cell->c)))) {
/* A rare special case: the first cell contains a spacing mark.
* Place on top of a NBSP, along with additional spacing marks if any,
* and display beginning at offscreen column -1.
* Additional spacing marks, if any, will be combined by the loop below. */
c = _vte_unistr_append_unistr (0x00A0, cell->c);
- col = -1;
+ lcol = -1;
}
- while (j < m_column_count) {
+ while (j < row_data->len && j < column_count) {
/* Combine with subsequent spacing marks. */
cell = _vte_row_data_get (row_data, j);
if (cell && !cell->attr.fragment() && g_unichar_ismark (_vte_unistr_get_base
(cell->c))) {
@@ -9226,6 +9319,33 @@ Terminal::draw_rows(VteScreen *screen_,
}
}
+ /* There are certain mandatory ligatures in Arabic, e.g.
+ * LAM U+0644 (on the right) + ALEF U+0627 (on the left)
+ * needs to become a single symbol (U+FEFB or U+FEFC in the
+ * legacy presentation form characters).
+ * FriBidi replaces the first (right) character with ZWNBSP U+FEFF and
+ * the second (left) character with the desired presentational form.
+ * Detect if we're about to render this glyph, and shift by half a cell
+ * to the right. */
+ // FIXME Get FriBidi devs document this behavior.
+ // FIXME Check what Arabic monospace fonts do. Is there any where these
+ // ligated glyphs are wide, thus we now break its positioning?
+ vteunistr c_shaped = bidirow->vis_get_shaped_char(vcol, c);
+ int xoff = 0;
+ if (G_UNLIKELY (c_shaped != c && lcol > 0 && vcol < column_count - 1)) {
+ int vcol2 = vcol + 1;
+ int lcol2 = bidirow->vis2log(vcol2);
+ if (lcol2 == lcol - 1) {
+ const VteCell *cell2 = _vte_row_data_get (row_data, lcol2);
+ g_assert(cell2 != nullptr);
+ vteunistr c2 = cell2->c;
+ vteunistr c2_shaped = bidirow->vis_get_shaped_char(vcol2, c2);
+ if (c2 != 0xFEFF && c2_shaped == 0xFEFF) {
+ xoff = column_width / 2;
+ }
+ }
+ }
+
attr = nattr;
fore = nfore;
back = nback;
@@ -9234,14 +9354,16 @@ Terminal::draw_rows(VteScreen *screen_,
hilite = nhilite;
g_assert_cmpint (item_count, <, column_count);
- items[item_count].c = c;
- items[item_count].columns = j - col;
- items[item_count].x = col * column_width;
+ items[item_count].c = bidirow->vis_get_shaped_char(vcol, c);
+ items[item_count].columns = j - lcol;
+ items[item_count].x = (vcol - (bidirow->vis_is_rtl(vcol) ? items[item_count].columns
- 1 : 0)) * column_width + xoff;
items[item_count].y = y;
+ items[item_count].mirror = bidirow->vis_is_rtl(vcol);
+ items[item_count].box_mirror = !!(row_data->attr.bidi_flags &
VTE_BIDI_FLAG_BOX_MIRROR);
item_count++;
- g_assert_cmpint (j, >, col);
- col = j;
+ g_assert_cmpint (j, >, lcol);
+ lcol = j;
}
/* Draw the last run of cells in the row. */
@@ -9260,7 +9382,7 @@ Terminal::paint_cursor()
{
struct _vte_draw_text_request item;
vte::grid::row_t drow;
- vte::grid::column_t col;
+ vte::grid::column_t col, viscol;
int width, height, cursor_width;
guint style = 0;
guint fore, back, deco;
@@ -9293,6 +9415,9 @@ Terminal::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. */
+ VteRowData const *row_data = find_row_data(drow);
+ vte::base::BidiRow const *bidirow = m_ringview.get_bidirow(drow);
+
auto cell = find_charcell(col, drow);
while (cell != NULL && cell->attr.fragment() && cell->c != '\t' && col > 0) {
col--;
@@ -9300,15 +9425,18 @@ Terminal::paint_cursor()
}
/* Draw the cursor. */
- item.c = (cell && cell->c) ? cell->c : ' ';
+ viscol = bidirow->log2vis(col);
+ item.c = (cell && cell->c) ? bidirow->vis_get_shaped_char(viscol, cell->c) : ' ';
item.columns = item.c == '\t' ? 1 : cell ? cell->attr.columns() : 1;
- item.x = col * width;
+ item.x = (viscol - ((cell && bidirow->vis_is_rtl(viscol)) ? cell->attr.columns() - 1 : 0)) * width;
item.y = row_to_pixel(drow);
+ item.mirror = bidirow->vis_is_rtl(viscol);
+ item.box_mirror = (row_data && (row_data->attr.bidi_flags & VTE_BIDI_FLAG_BOX_MIRROR));
if (cell && cell->c != 0) {
style = _vte_draw_get_style(cell->attr.bold(), cell->attr.italic());
}
- selected = cell_is_selected(col, drow);
+ selected = cell_is_selected_vis(viscol, drow);
determine_cursor_colors(cell, selected, &fore, &back, &deco);
rgb_from_index<8, 8, 8>(back, bg);
@@ -9330,9 +9458,17 @@ Terminal::paint_cursor()
stem_width = (int) (((float) (m_char_ascent + m_char_descent)) *
m_cursor_aspect_ratio + 0.5);
stem_width = CLAMP (stem_width, VTE_LINE_WIDTH, m_cell_width);
+ // FIXME make an exception when the cursor is just after the last character:
+ // show it next to the last character (wherever it appears due to BiDi) rather than
+ // beyond the end of the string, as KDE/Qt does. Maybe not just for I-beam.
+
+ if (row_data && bidirow->vis_is_rtl(viscol))
+ x += item.columns * m_cell_width - stem_width;
+
_vte_draw_fill_rectangle(m_draw,
x, y + m_char_padding.top, stem_width, m_char_ascent +
m_char_descent,
&bg, VTE_DRAW_OPAQUE);
+
break;
}
@@ -9416,12 +9552,19 @@ void
Terminal::paint_im_preedit_string()
{
int col, columns;
+ long row;
long width, height;
int i, len;
if (m_im_preedit.empty())
return;
+ /* Get the row's BiDi information. */
+ row = m_screen->cursor.row;
+ if (row < first_displayed_row() || row > last_displayed_row())
+ return;
+ vte::base::BidiRow const *bidirow = m_ringview.get_bidirow(row);
+
/* Keep local copies of rendering information. */
width = m_cell_width;
height = m_cell_height;
@@ -9432,7 +9575,7 @@ Terminal::paint_im_preedit_string()
/* If the pre-edit string won't fit on the screen if we start
* drawing it at the cursor's position, move it left. */
- col = m_screen->cursor.col;
+ col = bidirow->log2vis(m_screen->cursor.col);
if (col + columns > m_column_count) {
col = MAX(0, m_column_count - columns);
}
@@ -9443,7 +9586,7 @@ Terminal::paint_im_preedit_string()
const char *preedit = m_im_preedit.c_str();
int preedit_cursor;
- items = g_new(struct _vte_draw_text_request, len);
+ items = g_new0(struct _vte_draw_text_request, len);
for (i = columns = 0; i < len; i++) {
items[i].c = g_utf8_get_char(preedit);
items[i].columns = _vte_unichar_width(items[i].c,
diff --git a/src/vtedraw.cc b/src/vtedraw.cc
index 215e27ee..6314c956 100644
--- a/src/vtedraw.cc
+++ b/src/vtedraw.cc
@@ -26,6 +26,7 @@
#include <glib.h>
#include <gtk/gtk.h>
+#include "bidi.hh"
#include "vtedraw.hh"
#include "vtedefines.hh"
#include "debug.h"
@@ -1487,6 +1488,11 @@ _vte_draw_text_internal (struct _vte_draw *draw,
for (i = 0; i < n_requests; i++) {
vteunistr c = requests[i].c;
+
+ if (G_UNLIKELY (requests[i].mirror)) {
+ vte_bidi_get_mirror_char (c, requests[i].box_mirror, &c);
+ }
+
struct unistr_info *uinfo = font_info_get_unistr_info (font, c);
union unistr_font_info *ufi = &uinfo->ufi;
int x, y;
diff --git a/src/vtedraw.hh b/src/vtedraw.hh
index 7352d376..73dcdae1 100644
--- a/src/vtedraw.hh
+++ b/src/vtedraw.hh
@@ -44,6 +44,8 @@ struct _vte_draw;
struct _vte_draw_text_request {
vteunistr c;
gshort x, y, columns;
+ guint8 mirror : 1;
+ guint8 box_mirror : 1;
};
guint _vte_draw_get_style(gboolean bold, gboolean italic);
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index a12a99fa..9ea592d6 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -24,6 +24,7 @@
#include "vtetypes.hh"
#include "vtedraw.hh"
#include "reaper.hh"
+#include "bidi.hh"
#include "ring.hh"
#include "ringview.hh"
#include "buffer.h"
@@ -401,7 +402,7 @@ public:
gboolean m_selecting_had_delta;
gboolean m_selection_block_mode; // FIXMEegmont move it into a 4th value in vte_selection_type?
enum vte_selection_type m_selection_type;
- vte::grid::halfcoords m_selection_origin, m_selection_last;
+ vte::grid::halfcoords m_selection_origin, m_selection_last; /* BiDi: logical in normal modes,
visual in m_selection_block_mode */
vte::grid::span m_selection_resolved;
/* Clipboard data information. */
@@ -735,6 +736,7 @@ public:
inline bool grid_coords_in_scrollback(vte::grid::coords const& rowcol) const { return rowcol.row() <
m_screen->insert_delta; }
+ vte::grid::row_t confine_grid_row(vte::grid::row_t const& row) const;
vte::grid::coords confine_grid_coords(vte::grid::coords const& rowcol) const;
vte::grid::coords confined_grid_coords_from_event(GdkEvent const* event) const;
vte::grid::coords confined_grid_coords_from_view_coords(vte::view::coords const& pos) const;
@@ -959,8 +961,8 @@ public:
void resolve_selection();
void selection_maybe_swap_endpoints(vte::view::coords const& pos);
void modify_selection(vte::view::coords const& pos);
- bool cell_is_selected(vte::grid::column_t col,
- vte::grid::row_t) const;
+ bool cell_is_selected_vis(vte::grid::column_t col,
+ vte::grid::row_t) const;
void reset_default_attributes(bool reset_hyperlink);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]