diff --git a/kitty/screen.c b/kitty/screen.c index 578a0dbbf..8a6112c91 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -3632,30 +3632,24 @@ extend_tuple(PyObject *a, PyObject *b) { static PyObject* current_url_text(Screen *self, PyObject *args UNUSED) { - PyObject *empty_string = PyUnicode_FromString(""), *ans = NULL; + RAII_PyObject(empty_string, PyUnicode_FromString("")); if (!empty_string) return NULL; + RAII_PyObject(ans, NULL); for (size_t i = 0; i < self->url_ranges.count; i++) { Selection *s = self->url_ranges.items + i; if (!is_selection_empty(s)) { - PyObject *temp = text_for_range(self, s, false, false); - if (!temp) goto error; - PyObject *text = PyUnicode_Join(empty_string, temp); - Py_CLEAR(temp); - if (!text) goto error; + RAII_PyObject(temp, text_for_range(self, s, false, false)); + if (!temp) return NULL; + RAII_PyObject(text, PyUnicode_Join(empty_string, temp)); + if (!text) return NULL; if (ans) { - PyObject *t = ans; - ans = PyUnicode_Concat(ans, text); - Py_CLEAR(text); Py_CLEAR(t); - if (!ans) goto error; - } else ans = text; + PyObject *t = PyUnicode_Concat(ans, text); + if (!t) return NULL; + Py_CLEAR(ans); ans = t; + } else ans = Py_NewRef(text); } } - Py_CLEAR(empty_string); - if (!ans) Py_RETURN_NONE; - return ans; -error: - Py_CLEAR(empty_string); Py_CLEAR(ans); - return NULL; + return Py_NewRef(ans ? ans : Py_None); } @@ -4702,12 +4696,18 @@ screen_mark_url(Screen *self, index_type start_x, index_type start_y, index_type } static bool -mark_hyperlinks_in_line(Screen *self, Line *line, hyperlink_id_type id, index_type y) { +mark_hyperlinks_in_line(Screen *self, Line *line, hyperlink_id_type id, index_type y, bool *found_nonzero_multiline) { index_type start = 0; bool found = false; bool in_range = false; + *found_nonzero_multiline = false; for (index_type x = 0; x < line->xnum; x++) { bool has_hyperlink = line->cpu_cells[x].hyperlink_id == id; + bool is_nonzero_multiline = line->cpu_cells[x].is_multicell && line->cpu_cells[x].y > 0; + if (has_hyperlink && is_nonzero_multiline) { + has_hyperlink = false; + *found_nonzero_multiline = true; + } if (in_range) { if (!has_hyperlink) { add_url_range(self, start, y, x - 1, y, true); @@ -4745,8 +4745,9 @@ screen_mark_hyperlink(Screen *self, index_type x, index_type y) { hyperlink_id_type id = line->cpu_cells[x].hyperlink_id; if (!id) return 0; index_type ypos = y, last_marked_line = y; + bool found_nonzero_multiline; do { - if (mark_hyperlinks_in_line(self, line, id, ypos)) last_marked_line = ypos; + if (mark_hyperlinks_in_line(self, line, id, ypos, &found_nonzero_multiline) || found_nonzero_multiline) last_marked_line = ypos; if (ypos == 0) break; ypos--; line = screen_visual_line(self, ypos); @@ -4754,7 +4755,7 @@ screen_mark_hyperlink(Screen *self, index_type x, index_type y) { ypos = y + 1; last_marked_line = y; while (ypos < self->lines - 1 && ypos - last_marked_line < 5) { line = screen_visual_line(self, ypos); - if (mark_hyperlinks_in_line(self, line, id, ypos)) last_marked_line = ypos; + if (mark_hyperlinks_in_line(self, line, id, ypos, &found_nonzero_multiline)) last_marked_line = ypos; ypos++; } if (self->url_ranges.count > 1) sort_ranges(self, &self->url_ranges); diff --git a/kitty_tests/multicell.py b/kitty_tests/multicell.py index 2a216d32d..6c5467130 100644 --- a/kitty_tests/multicell.py +++ b/kitty_tests/multicell.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # License: GPLv3 Copyright: 2024, Kovid Goyal +from functools import partial from kitty.fast_data_types import EXTEND_CELL, TEXT_SIZE_CODE, test_ch_and_idx, wcswidth @@ -662,3 +663,19 @@ def test_multicell(self: TestMulticell) -> None: asl((0, 0, 1), (1, 0, 3)) ast('Xab') asa(f'\x1b]{TEXT_SIZE_CODE};w=1:s=2;X\x07ab', '\x1b[m') + + # Hyperlinks + asu = partial(asl, bp=2) + def set_link(url=None, id=None): + parse_bytes(s, '\x1b]8;id={};{}\x1b\\'.format(id or '', url or '').encode('utf-8')) + + s.reset() + set_link('url-a', 'a') + multicell(s, 'ab', scale=2) + for y in (0, 1): + self.ae(s.line(y).hyperlink_ids(), (1, 1, 1, 1, 0, 0, 0, 0)) + for y in (0, 1): + for x in (0, 3): + self.ae('url-a', s.hyperlink_at(x, y)) + asu((0, 0, 3), (1, 0, 3)) + self.ae(s.current_url_text(), 'ab')