[vte/wip/egmont/bidi: 14/21] etap12
- From: Egmont Koblinger <egmontkob src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte/wip/egmont/bidi: 14/21] etap12
- Date: Fri, 31 May 2019 17:24:50 +0000 (UTC)
commit bc306da3067dd6bc6116f82f415c9cee0719a197
Author: Egmont Koblinger <egmont gmail com>
Date: Sat May 25 13:29:41 2019 +0200
etap12
src/bidi.cc | 6 ++--
src/ringview.cc | 15 +++++-----
src/ringview.hh | 4 +--
src/vte.cc | 87 +++++++++++++++++++++++++++++++++++----------------------
4 files changed, 66 insertions(+), 46 deletions(-)
---
diff --git a/src/bidi.cc b/src/bidi.cc
index dfee836b..1a3b0ee8 100644
--- a/src/bidi.cc
+++ b/src/bidi.cc
@@ -203,7 +203,7 @@ void BidiRunner::explicit_line_shape(vte::grid::row_t row)
if (G_UNLIKELY (row_data == nullptr))
return;
- BidiRow *bidirow = m_ringview->get_row_map_writable(row);
+ BidiRow *bidirow = m_ringview->get_bidirow_writable(row);
auto width = m_ringview->get_width();
@@ -318,7 +318,7 @@ void BidiRunner::explicit_line(vte::grid::row_t row, bool rtl, bool shape)
{
int i;
- BidiRow *bidirow = m_ringview->get_row_map_writable(row);
+ BidiRow *bidirow = m_ringview->get_bidirow_writable(row);
if (G_UNLIKELY (bidirow == nullptr))
return;
bidirow->m_base_rtl = rtl;
@@ -588,7 +588,7 @@ bool BidiRunner::implicit_paragraph(vte::grid::row_t start, vte::grid::row_t end
/* Reshuffle line by line. */
for (row = start, line = 0; row < end; row++, line++) {
- bidirow = m_ringview->get_row_map_writable(row);
+ bidirow = m_ringview->get_bidirow_writable(row);
if (bidirow == nullptr)
continue;
diff --git a/src/ringview.cc b/src/ringview.cc
index 5138f7f3..82c428db 100644
--- a/src/ringview.cc
+++ b/src/ringview.cc
@@ -93,13 +93,12 @@ void RingView::unpause()
m_bidirows[i] = new BidiRow();
}
- m_invalid = true;
m_paused = false;
}
void RingView::set_ring(Ring *ring)
{
- if (ring == m_ring)
+ if (G_LIKELY (ring == m_ring))
return;
m_ring = ring;
@@ -108,7 +107,7 @@ void RingView::set_ring(Ring *ring)
void RingView::set_width(vte::grid::column_t width)
{
- if (width == m_width)
+ if (G_LIKELY (width == m_width))
return;
m_width = width;
@@ -117,12 +116,12 @@ void RingView::set_width(vte::grid::column_t width)
void RingView::set_rows(vte::grid::row_t start, vte::grid::row_t len)
{
- g_assert_cmpint (len, >=, 1);
-
if (start == m_start && len == m_len)
return;
- /* m_rows is expended on demand in update() */
+ g_assert_cmpint (len, >=, 1);
+
+ /* m_rows is expanded on demand in update() */
/* m_bidirows needs exactly these many lines */
if (G_UNLIKELY (!m_paused && len > m_bidirows_alloc_len)) {
@@ -234,7 +233,7 @@ void RingView::update()
m_invalid = false;
}
-BidiRow const* RingView::get_row_map(vte::grid::row_t row) const
+BidiRow const* RingView::get_bidirow(vte::grid::row_t row) const
{
g_assert_cmpint (row, >=, m_start);
g_assert_cmpint (row, <, m_start + m_len);
@@ -246,7 +245,7 @@ BidiRow const* RingView::get_row_map(vte::grid::row_t row) const
/* For internal use by BidiRunner. Get where the BiDi mapping for the given row
* needs to be stored, of nullptr if it's a context row. */
-BidiRow* RingView::get_row_map_writable(vte::grid::row_t row) const
+BidiRow* RingView::get_bidirow_writable(vte::grid::row_t row) const
{
if (row < m_start || row >= m_start + m_len)
return nullptr;
diff --git a/src/ringview.hh b/src/ringview.hh
index 3a68fdb9..77bac334 100644
--- a/src/ringview.hh
+++ b/src/ringview.hh
@@ -76,8 +76,8 @@ public:
VteRowData *get_row(vte::grid::row_t row);
- BidiRow const* get_row_map(vte::grid::row_t row) const;
- BidiRow* get_row_map_writable(vte::grid::row_t row) const;
+ BidiRow const* get_bidirow(vte::grid::row_t row) const;
+ BidiRow* get_bidirow_writable(vte::grid::row_t row) const;
private:
Ring *m_ring;
diff --git a/src/vte.cc b/src/vte.cc
index 23863f7c..9b8969d7 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -1567,7 +1567,7 @@ 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_row_map(confine_grid_row(row));
+ vte::base::BidiRow const* bidirow = m_ringview.get_bidirow(confine_grid_row(row));
col = bidirow->vis2log(col);
return vte::grid::coords(row, col);
@@ -1675,7 +1675,7 @@ Terminal::selection_grid_halfcoords_from_view_coords(vte::view::coords const& po
if (!m_selection_block_mode) {
/* BiDi: convert from visual to logical half column. */
- vte::base::BidiRow const* bidirow = m_ringview.get_row_map(confine_grid_row(row));
+ vte::base::BidiRow const* bidirow = m_ringview.get_bidirow(confine_grid_row(row));
if (bidirow->vis_is_rtl(col))
half = 1 - half;
@@ -5014,21 +5014,21 @@ Terminal::widget_key_press(GdkEventKey *event)
/* If the above switch statement didn't do the job, try mapping
* it to a literal or capability name. */
if (handled == FALSE) {
- /* In keyboard arrow swapping mode, the left and right arrows
- * are swapped if the cursor stands inside an RTL paragraph. */
- if (m_modes_private.VTE_BIDI_SWAP_ARROW_KEYS() &&
- (keyval == GDK_KEY_Left ||
- keyval == GDK_KEY_Right ||
- keyval == GDK_KEY_KP_Left ||
- keyval == GDK_KEY_KP_Right)) {
- /* m_ringview is for the onscreen contents and the cursor may be
- * offscreen, so use a temporary ringview for the cursor's row. */
- vte::base::RingView *ringview = new vte::base::RingView();
- ringview->set_ring(m_screen->row_data);
- ringview->set_rows(m_screen->cursor.row, 1);
- ringview->set_width(m_column_count);
- ringview->update();
- if (ringview->get_row_map(m_screen->cursor.row)->base_is_rtl()) {
+ if (G_UNLIKELY (m_modes_private.VTE_BIDI_SWAP_ARROW_KEYS() &&
+ (keyval == GDK_KEY_Left ||
+ keyval == GDK_KEY_Right ||
+ keyval == GDK_KEY_KP_Left ||
+ keyval == GDK_KEY_KP_Right))) {
+ /* In keyboard arrow swapping mode, the left and right arrows are swapped
+ * if the cursor stands inside a (possibly autodetected) RTL paragraph.
+ * m_ringview is for the onscreen contents and the cursor may be offscreen.
+ * Better leave that alone and use a temporary ringview for the cursor's
row. */
+ vte::base::RingView ringview;
+ ringview.set_ring(m_screen->row_data);
+ ringview.set_rows(m_screen->cursor.row, 1);
+ ringview.set_width(m_column_count);
+ ringview.update();
+ if (ringview.get_bidirow(m_screen->cursor.row)->base_is_rtl()) {
switch (keyval) {
case GDK_KEY_Left:
keyval = GDK_KEY_Right;
@@ -5044,7 +5044,6 @@ Terminal::widget_key_press(GdkEventKey *event)
break;
}
}
- delete ringview;
}
_vte_keymap_map(keyval, m_modifiers,
@@ -5596,7 +5595,7 @@ Terminal::cell_is_selected_vis(vte::grid::column_t col,
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_row_map(row);
+ vte::base::BidiRow const* bidirow = m_ringview.get_bidirow(row);
col = bidirow->vis2log(col);
while (col > 0) {
VteCell const* cell = find_charcell(col, row);
@@ -5609,7 +5608,7 @@ Terminal::cell_is_selected_vis(vte::grid::column_t col,
return m_selection_resolved.box_contains ({ row, col });
} else {
/* BiDi: convert to logical column. */
- vte::base::BidiRow const* bidirow = m_ringview.get_row_map(row);
+ 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 });
@@ -6072,7 +6071,7 @@ Terminal::match_hilite_update()
glong row = pixel_to_row(pos.y);
/* BiDi: convert to logical column. */
- vte::base::BidiRow const* bidirow = m_ringview.get_row_map(confine_grid_row(row));
+ vte::base::BidiRow const* bidirow = m_ringview.get_bidirow(confine_grid_row(row));
col = bidirow->vis2log(col);
_vte_debug_print(VTE_DEBUG_EVENTS,
@@ -6295,9 +6294,9 @@ Terminal::get_text(vte::grid::row_t start_row,
if (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.
- * Modifying m_ringview and then reverting would be a bit cumbersome,
- * creating a new one for the selection is simpler. */
+ * 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);
@@ -6320,7 +6319,7 @@ Terminal::get_text(vte::grid::row_t start_row,
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_row_map(row) : nullptr;
+ bidirow = ringview ? ringview->get_bidirow(row) : nullptr;
while (col < line_last_column &&
(pcell = _vte_row_data_get (row_data, col))) {
@@ -7019,8 +7018,6 @@ Terminal::widget_motion_notify(GdkEventMotion *event)
"Motion notify %s %s\n",
pos.to_string(), rowcol.to_string());
- ringview_update();
-
read_modifiers(base_event);
switch (event->type) {
@@ -9114,7 +9111,7 @@ Terminal::draw_rows(VteScreen *screen_,
if (row_data == nullptr)
continue; /* Skip row. FIXME: just paint this row empty? */
- bidirow = m_ringview.get_row_map(row);
+ 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. */
@@ -9194,7 +9191,7 @@ 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};
- bidirow = m_ringview.get_row_map(row);
+ 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. */
@@ -9273,6 +9270,30 @@ 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. */
+ 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;
@@ -9283,7 +9304,7 @@ Terminal::draw_rows(VteScreen *screen_,
g_assert_cmpint (item_count, <, column_count);
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;
+ 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_BOX_MIRROR);
@@ -9343,7 +9364,7 @@ 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_row_map(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) {
@@ -9496,7 +9517,7 @@ Terminal::paint_im_preedit_string()
row = m_screen->cursor.row;
if (row < first_displayed_row() || row > last_displayed_row())
return;
- vte::base::BidiRow const *bidirow = m_ringview.get_row_map(row);
+ vte::base::BidiRow const *bidirow = m_ringview.get_bidirow(row);
/* Keep local copies of rendering information. */
width = m_cell_width;
@@ -9721,7 +9742,7 @@ Terminal::widget_scroll(GdkEventScroll *event)
GdkEvent *base_event = reinterpret_cast<GdkEvent*>(event);
- ringview_update();
+// ringview_update(); // needed?
read_modifiers(base_event);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]