Skip to content
This repository has been archived by the owner on Apr 19, 2024. It is now read-only.

Commit

Permalink
gh-42: Fix for wide (two-cell) characters messing up the URL detectio…
Browse files Browse the repository at this point in the history
…n boxes.
  • Loading branch information
twpol authored and FauxFaux committed Aug 7, 2013
1 parent 7a8fec0 commit 445cbfc
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 3 deletions.
2 changes: 1 addition & 1 deletion terminal.c
Expand Up @@ -4811,7 +4811,7 @@ static void do_paint(Terminal *term, Context ctx, int may_optimise)
termline *lp = lineptr(term->disptop + i);

for (j = 0; j < term->cols; j++) {
urlhack_putchar((char)(lp->chars[j].chr & CHAR_MASK));
urlhack_putchar((char)(lp->chars[j].chr & CHAR_MASK), j < term->cols-1 && lp->chars[j+1].chr == UCSWIDE ? 1 : 0);
}

unlineptr(lp);
Expand Down
4 changes: 3 additions & 1 deletion urlhack.c
Expand Up @@ -142,14 +142,16 @@ void urlhack_cleanup()
sfree(window_text);
}

void urlhack_putchar(char ch)
void urlhack_putchar(char ch, int wide)
{
if (window_text_current_pos >= window_text_len) {
window_text = sresize(window_text, 2 * window_text_len, char);
memset(window_text + window_text_current_pos, '\0', window_text_len - window_text_current_pos);
window_text_len *= 2;
}
window_text[window_text_current_pos++] = ch;
if (wide)
window_text[window_text_current_pos++] = ch;
}

void urlhack_reset()
Expand Down
178 changes: 178 additions & 0 deletions urlhack.cpp
@@ -0,0 +1,178 @@
#include <vector>
#include <string>
#include <sstream>
#include "urlhack.h"

int urlhack_mouse_old_x = -1, urlhack_mouse_old_y = -1, urlhack_current_region = -1;

static std::vector<text_region> link_regions;

void urlhack_clear_link_regions()
{
link_regions.clear();
}



int urlhack_is_in_link_region(int x, int y)
{
std::vector<text_region>::iterator i = link_regions.begin();
int loopCounter = 1;

while (i != link_regions.end()) {
text_region r = *i;

if ((r.y0 == r.y1 && y == r.y0 && y == r.y1 && x >= r.x0 && x < r.x1) ||
(r.y0 != r.y1 && ((y == r.y0 && x >= r.x0) || (y == r.y1 && x < r.x1) || (y > r.y0 && y < r.y1))))
return loopCounter; //Changed: was return true

loopCounter++;
i++;
}

return false;
}



int urlhack_is_in_this_link_region(text_region r, int x, int y)
{
if ((r.y0 == r.y1 && y == r.y0 && y == r.y1 && x >= r.x0 && x < r.x1) || (r.y0 != r.y1 && ((y == r.y0 && x >= r.x0) || (y == r.y1 && x < r.x1) || (y > r.y0 && y < r.y1)))) {
return true;
}

return false;
}



text_region urlhack_get_link_bounds(int x, int y)
{
std::vector<text_region>::iterator i = link_regions.begin();

while (i != link_regions.end()) {
text_region r = *i;

if ((r.y0 == r.y1 && y == r.y0 && y == r.y1 && x >= r.x0 && x < r.x1) ||
(r.y0 != r.y1 && ((y == r.y0 && x >= r.x0) || (y == r.y1 && x < r.x1) || (y > r.y0 && y < r.y1))))
return *i;

i++;
}

text_region region;
region.x0 = region.y0 = region.x1 = region.y1 = -1;
return region;
}



text_region urlhack_get_link_region(int index)
{
text_region region;

if (index < 0 || index >= (int)link_regions.size()) {
region.x0 = region.y0 = region.x1 = region.y1 = -1;
return region;
}
else {
return link_regions.at(index);
}
}



void urlhack_add_link_region(int x0, int y0, int x1, int y1)
{
text_region region;

region.x0 = x0;
region.y0 = y0;
region.x1 = x1;
region.y1 = y1;

link_regions.insert(link_regions.end(), region);
}


// Regular expression stuff

static int urlhack_disabled = 0;
static int is_regexp_compiled = 0;
static regexp* urlhack_rx;
static std::string text_mass;



void urlhack_reset()
{
text_mass.clear();
}



void urlhack_putchar(char ch, int wide)
{
char r00fles[3] = { ch, wide ? ch : 0, 0 };
text_mass.append(r00fles);
}



void urlhack_set_regular_expression(const char* expression)
{
is_regexp_compiled = 0;
urlhack_disabled = 0;

set_regerror_func(rtfm);
urlhack_rx = regcomp(const_cast<char*>(expression));

if (urlhack_rx == 0) {
urlhack_disabled = 1;
}

is_regexp_compiled = 1;
}



void urlhack_go_find_me_some_hyperlinks(int screen_width)
{
if (urlhack_disabled != 0) return;

if (is_regexp_compiled == 0) {
urlhack_set_regular_expression(urlhack_default_regex);
}

urlhack_clear_link_regions();


char* text = const_cast<char*>(text_mass.c_str());
char* text_pos = text;

while (regexec(urlhack_rx, text_pos) == 1) {
char* start_pos = *urlhack_rx->startp[0] == ' ' ? urlhack_rx->startp[0] + 1: urlhack_rx->startp[0];
char* end_pos = urlhack_rx->endp[0];
int max_brackets = 0;
for (char *c = start_pos; c < end_pos; ++c) {
switch (*c) {
case '(': ++max_brackets; break;
case ')': --max_brackets; break;
}
}
while (max_brackets --> 0 && *end_pos == ')')
++end_pos;

int x0 = (start_pos - text) % screen_width;
int y0 = (start_pos - text) / screen_width;
int x1 = (end_pos - text) % screen_width;
int y1 = (end_pos - text) / screen_width;

if (x0 >= screen_width) x0 = screen_width - 1;
if (x1 >= screen_width) x1 = screen_width - 1;

urlhack_add_link_region(x0, y0, x1, y1);

text_pos = end_pos + 1;
}
}
2 changes: 1 addition & 1 deletion windows/urlhack.h
Expand Up @@ -11,7 +11,7 @@ extern int urlhack_mouse_old_x, urlhack_mouse_old_y, urlhack_current_region;

void urlhack_reset();
void urlhack_go_find_me_some_hyperlinks(int screen_width);
void urlhack_putchar(char ch);
void urlhack_putchar(char ch, int width);
text_region urlhack_get_link_region(int index);

int urlhack_is_in_link_region(int x, int y);
Expand Down

0 comments on commit 445cbfc

Please sign in to comment.