This commit is contained in:
Kovid Goyal 2025-01-13 14:52:08 +05:30
parent 6a19918687
commit c3db7c9464
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
3 changed files with 43 additions and 21 deletions

View file

@ -172,14 +172,14 @@ is_url_lc(const ListOfChars *lc) {
return true;
}
static index_type
index_type
next_char_pos(const Line *self, index_type x, index_type num) {
const CPUCell *ans = self->cpu_cells + x, *limit = self->cpu_cells + self->xnum;
while (num-- && ans < limit) ans += ans->is_multicell ? mcd_x_limit(ans) - ans->x : 1;
return ans - self->cpu_cells;
}
static index_type
index_type
prev_char_pos(const Line *self, index_type x, index_type num) {
const CPUCell *ans = self->cpu_cells + x, *limit = self->cpu_cells - 1;
if (ans->is_multicell) ans -= ans->x;
@ -323,6 +323,14 @@ line_startswith_url_chars(Line *self, bool in_hostname, ListOfChars *lc) {
return is_url_lc(lc);
}
index_type
find_char(Line *self, index_type start, char_type ch) {
do {
if (cell_is_char(self->cpu_cells + start, ch)) return start;
} while ((start = next_char_pos(self, start, 1)) < self->xnum);
return self->xnum;
}
char_type
get_url_sentinel(Line *line, index_type url_start) {
char_type before = 0, sentinel;

View file

@ -73,6 +73,9 @@ index_type line_url_start_at(Line *self, index_type x, ListOfChars *lc);
index_type line_url_end_at(Line *self, index_type x, bool, char_type, bool, bool, index_type, ListOfChars*);
bool line_startswith_url_chars(Line*, bool, ListOfChars*);
char_type get_url_sentinel(Line *line, index_type url_start);
index_type find_char(Line *self, index_type start, char_type ch);
index_type next_char_pos(const Line *self, index_type x, index_type num);
index_type prev_char_pos(const Line *self, index_type x, index_type num);
bool line_as_ansi(Line *self, ANSILineState *s, index_type start_at, index_type stop_before, char_type prefix_char, bool skip_multiline_non_zero_lines) __attribute__((nonnull));
unsigned int line_length(Line *self);
size_t cell_as_unicode_for_fallback(const ListOfChars *lc, Py_UCS4 *buf);

View file

@ -3694,42 +3694,54 @@ screen_open_url(Screen *self) {
// }}}
// URLs {{{
static index_type
get_last_hostname_char_pos(Line *line, index_type url_start) {
index_type slash_count = 0;
while (url_start < line->xnum) {
index_type pos = find_char(line, url_start, '/');
if (pos >= line->xnum) return line->xnum;
if (++slash_count > 2) return prev_char_pos(line, pos, 1);
url_start = next_char_pos(line, pos, 1);
}
return line->xnum;
}
static void
extend_url(Screen *screen, Line *line, index_type *x, index_type *y, char_type sentinel, bool newlines_allowed, index_type last_hostname_char_pos) {
extend_url(Screen *screen, Line *line, index_type *x, index_type *y, char_type sentinel, bool newlines_allowed, index_type last_hostname_char_pos, index_type scale) {
unsigned int count = 0;
bool has_newline = false;
index_type orig_y = *y;
while(count++ < 10) {
while (count++ < 10) {
bool in_hostname = last_hostname_char_pos >= line->xnum;
has_newline = !line->cpu_cells[line->xnum-1].next_char_was_wrapped;
if (*x != line->xnum - 1 || (!newlines_allowed && has_newline)) break;
bool next_line_starts_with_url_chars = false;
line = screen_visual_line(screen, *y + 2);
line = screen_visual_line(screen, *y + 2 * scale);
if (line) {
next_line_starts_with_url_chars = line_startswith_url_chars(line, in_hostname, screen->lc);
has_newline = !line->attrs.is_continued;
if (next_line_starts_with_url_chars && has_newline && !newlines_allowed) next_line_starts_with_url_chars = false;
if (sentinel && next_line_starts_with_url_chars && cell_is_char(line->cpu_cells, sentinel)) next_line_starts_with_url_chars = false;
}
line = screen_visual_line(screen, *y + 1);
line = screen_visual_line(screen, *y + scale);
if (!line) break;
if (in_hostname) {
for (last_hostname_char_pos = 0; last_hostname_char_pos < line->xnum; last_hostname_char_pos++) {
if (cell_is_char(line->cpu_cells + last_hostname_char_pos, '/')) {
if (last_hostname_char_pos > 0) last_hostname_char_pos--;
else { in_hostname = false; last_hostname_char_pos = line->xnum; }
break;
}
last_hostname_char_pos = find_char(line, 0, '/');
if (last_hostname_char_pos < line->xnum) {
last_hostname_char_pos = prev_char_pos(line, last_hostname_char_pos, 1);
if (last_hostname_char_pos >= line->xnum) in_hostname = false;
}
}
index_type new_x = line_url_end_at(line, 0, false, sentinel, next_line_starts_with_url_chars, in_hostname, last_hostname_char_pos, screen->lc);
if (!new_x && !line_startswith_url_chars(line, in_hostname, screen->lc)) break;
*y += 1; *x = new_x;
*y += scale; *x = new_x;
}
if (sentinel && *x == 0 && *y > orig_y) {
line = screen_visual_line(screen, *y);
if (line && cell_is_char(line->cpu_cells, sentinel)) {
*y -= 1; *x = line->xnum - 1;
*y -= scale;
*x = line->xnum - 1;
if (line->cpu_cells[*x].is_multicell) *x -= line->cpu_cells[*x].x;
}
}
}
@ -3756,24 +3768,23 @@ screen_detect_url(Screen *screen, unsigned int x, unsigned int y) {
index_type last_hostname_char_pos = screen->columns;
url_start = line_url_start_at(line, x, screen->lc);
Line scratch = {.xnum=line->xnum, .text_cache=line->text_cache};
index_type scale = 1;
if (url_start < line->xnum) {
scale = cell_scale(line->cpu_cells + url_start);
bool next_line_starts_with_url_chars = false;
if (y < screen->lines - 1) {
visual_line(screen, y + 1, &scratch);
if (y + scale < screen->lines) {
visual_line(screen, y + scale, &scratch);
next_line_starts_with_url_chars = line_startswith_url_chars(&scratch, last_hostname_char_pos >= line->xnum, screen->lc);
if (next_line_starts_with_url_chars && !newlines_allowed && !scratch.attrs.is_continued) next_line_starts_with_url_chars = false;
}
sentinel = get_url_sentinel(line, url_start);
index_type slash_count = 0;
for (index_type i = url_start; i < line->xnum; i++) {
if (cell_is_char(line->cpu_cells + i, '/') && ++slash_count > 2) { last_hostname_char_pos = i - 1; break; }
}
last_hostname_char_pos = get_last_hostname_char_pos(line, url_start);
url_end = line_url_end_at(line, x, true, sentinel, next_line_starts_with_url_chars, x <= last_hostname_char_pos, last_hostname_char_pos, screen->lc);
}
has_url = url_end > url_start;
if (has_url) {
index_type y_extended = y;
extend_url(screen, line, &url_end, &y_extended, sentinel, newlines_allowed, last_hostname_char_pos);
extend_url(screen, line, &url_end, &y_extended, sentinel, newlines_allowed, last_hostname_char_pos, scale);
screen_mark_url(screen, url_start, y, url_end, y_extended);
} else {
screen_mark_url(screen, 0, 0, 0, 0);