270 lines
7.4 KiB
C
270 lines
7.4 KiB
C
/*
|
|
* HACK: PuttyTray / Nutty
|
|
* Hyperlink stuff: CORE FILE! Don't forget to COPY IT TO THE NEXT VERSION
|
|
*/
|
|
#include <windows.h>
|
|
#include <string.h>
|
|
#include "urlhack.h"
|
|
#include "misc.h"
|
|
#include "puttymem.h"
|
|
#include <assert.h>
|
|
|
|
int urlhack_mouse_old_x = -1, urlhack_mouse_old_y = -1, urlhack_current_region = -1;
|
|
|
|
static text_region **link_regions;
|
|
static unsigned int link_regions_len;
|
|
static unsigned int link_regions_current_pos;
|
|
|
|
/*
|
|
const char* urlhack_default_regex = "(((https?|ftp):\\/\\/)|www\\.)(([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)|localhost|([a-zA-Z0-9\\-]+\\.)*[a-zA-Z0-9\\-]+\\.(aero|asia|biz|cat|com|coop|info|int|jobs|mobi|museum|name|net|org|post|pro|tel|travel|xxx|edu|gov|mil|[a-zA-Z][a-zA-Z]))(:[0-9]+)?((\\/|\\?)[^ \"]*[^ ,;\\.:\">)])?";
|
|
|
|
// Simplification de la regex par defaut pour essayer de résoudre le problème de crash (fuite mémoire) avec le patch hyperlink
|
|
*/
|
|
|
|
const char* urlhack_default_regex = "(((https?|ftp):\\/\\/)|www\\.)(([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)|localhost|([a-zA-Z0-9\\-]+\\.)*[a-zA-Z0-9\\-]+\\.(com|net|org|info|biz|gov|name|edu|[a-zA-Z][a-zA-Z]))(:[0-9]+)?((\\/|\\?)[^ \"]*[^ ,;\\.:\">)])?";
|
|
|
|
|
|
const char* urlhack_liberal_regex =
|
|
"("
|
|
"([a-zA-Z]+://|[wW][wW][wW]\\.|spotify:|telnet:)"
|
|
"[^ '\")>]+"
|
|
")"
|
|
;
|
|
|
|
int urlhack_is_in_link_region(int x, int y)
|
|
{
|
|
unsigned int i = 0;
|
|
|
|
while (i != link_regions_current_pos) {
|
|
text_region r = *link_regions[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+1;
|
|
i++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
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 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
text_region urlhack_get_link_bounds(int x, int y)
|
|
{
|
|
unsigned int i = 0;
|
|
text_region region;
|
|
|
|
while (i != link_regions_current_pos) {
|
|
text_region r = *link_regions[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 *link_regions[i];
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
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 >= link_regions_current_pos) {
|
|
region.x0 = region.y0 = region.x1 = region.y1 = -1;
|
|
return region;
|
|
}
|
|
else {
|
|
return *link_regions[index];
|
|
}
|
|
}
|
|
|
|
void urlhack_add_link_region(int x0, int y0, int x1, int y1)
|
|
{
|
|
if (link_regions_current_pos >= link_regions_len) {
|
|
unsigned int i;
|
|
link_regions_len *= 2;
|
|
link_regions = sresize(link_regions, link_regions_len, text_region*);
|
|
for (i = link_regions_current_pos; i < link_regions_len; ++i) {
|
|
link_regions[i] = NULL;
|
|
}
|
|
}
|
|
|
|
link_regions[link_regions_current_pos] = snew(text_region);
|
|
link_regions[link_regions_current_pos]->x0 = x0;
|
|
link_regions[link_regions_current_pos]->y0 = y0;
|
|
link_regions[link_regions_current_pos]->x1 = x1;
|
|
link_regions[link_regions_current_pos]->y1 = y1;
|
|
|
|
link_regions_current_pos++;
|
|
}
|
|
|
|
void urlhack_launch_url(const char* app, const char *url)
|
|
{
|
|
if (app) {
|
|
ShellExecute(NULL, NULL, app, url, NULL, SW_SHOWNORMAL);
|
|
} else {
|
|
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
|
}
|
|
}
|
|
|
|
int urlhack_is_ctrl_pressed()
|
|
{
|
|
return HIWORD(GetAsyncKeyState(VK_CONTROL));
|
|
}
|
|
|
|
void urlhack_link_regions_clear()
|
|
{
|
|
unsigned int i;
|
|
for (i = 0; i < link_regions_len; ++i) {
|
|
if (link_regions[i] != NULL) {
|
|
sfree(link_regions[i]);
|
|
link_regions[i] = NULL;
|
|
}
|
|
}
|
|
link_regions_current_pos = 0;
|
|
}
|
|
|
|
// Regular expression stuff
|
|
|
|
static int urlhack_disabled = 0;
|
|
static int is_regexp_compiled = 0;
|
|
static regexp* urlhack_rx=NULL;
|
|
|
|
static char *window_text;
|
|
static int window_text_len;
|
|
static int window_text_current_pos;
|
|
|
|
void urlhack_init()
|
|
{
|
|
unsigned int i;
|
|
|
|
/* 32 links seems like a sane base value */
|
|
link_regions_current_pos = 0;
|
|
link_regions_len = 32;
|
|
link_regions = snewn(link_regions_len, text_region*);
|
|
|
|
for (i = 0; i < link_regions_len; ++i) {
|
|
link_regions[i] = NULL;
|
|
}
|
|
|
|
/* Start with default terminal size */
|
|
//window_text_len = 80*24+1;
|
|
window_text_len = 500*300+1;
|
|
window_text = snewn(window_text_len, char);
|
|
urlhack_reset();
|
|
}
|
|
|
|
void urlhack_cleanup()
|
|
{
|
|
urlhack_link_regions_clear();
|
|
sfree(link_regions);
|
|
sfree(window_text);
|
|
}
|
|
|
|
void urlhack_putchar(char ch)
|
|
{
|
|
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;
|
|
}
|
|
|
|
void urlhack_reset()
|
|
{
|
|
memset(window_text, '\0', window_text_len);
|
|
window_text_current_pos = 0;
|
|
}
|
|
|
|
static void rtfm(char *error)
|
|
{
|
|
char std_msg[] = "The following error occured when compiling the regular expression\n" \
|
|
"for the hyperlink support. Hyperlink detection is disabled during\n" \
|
|
"this session (restart to try again).\n\n";
|
|
|
|
char *full_msg = dupprintf("%s%s", std_msg, error);
|
|
|
|
urlhack_disabled = 1 ;
|
|
//SetHyperlinkFlag(0);
|
|
|
|
MessageBox(0, full_msg, "Hyperlink patch error", MB_OK);
|
|
free(full_msg);
|
|
|
|
}
|
|
|
|
void urlhack_set_regular_expression(int mode, const char* expression)
|
|
{
|
|
#ifndef MOD_NOHYPERLINK
|
|
const char *to_use=NULL;
|
|
switch (mode) {
|
|
case URLHACK_REGEX_CUSTOM:
|
|
to_use = expression;
|
|
break;
|
|
case URLHACK_REGEX_CLASSIC:
|
|
to_use = urlhack_default_regex;
|
|
break;
|
|
case URLHACK_REGEX_LIBERAL:
|
|
to_use = urlhack_liberal_regex;
|
|
break;
|
|
default:
|
|
assert(!"illegal default regex setting");
|
|
}
|
|
|
|
is_regexp_compiled = 0;
|
|
urlhack_disabled = 0;
|
|
if (urlhack_rx != NULL) {
|
|
regfree(urlhack_rx);
|
|
urlhack_rx=NULL;
|
|
}
|
|
|
|
set_regerror_func(rtfm);
|
|
urlhack_rx = regcomp((char*)(to_use));
|
|
|
|
if (urlhack_rx == 0) {
|
|
urlhack_disabled = 1;
|
|
}
|
|
|
|
is_regexp_compiled = 1;
|
|
#endif
|
|
}
|
|
|
|
void urlhack_go_find_me_some_hyperlinks(int screen_width)
|
|
{
|
|
#ifndef MOD_NOHYPERLINK
|
|
char* text_pos;
|
|
if (urlhack_disabled != 0) return;
|
|
if (is_regexp_compiled == 0) {
|
|
urlhack_set_regular_expression(URLHACK_REGEX_CLASSIC,urlhack_default_regex);
|
|
}
|
|
urlhack_link_regions_clear();
|
|
text_pos = window_text;
|
|
while (regexec(urlhack_rx, text_pos) == 1) {
|
|
char* start_pos = *urlhack_rx->startp[0] == ' ' ? urlhack_rx->startp[0] + 1: urlhack_rx->startp[0];
|
|
|
|
int x0 = (start_pos - window_text) % screen_width;
|
|
int y0 = (start_pos - window_text) / screen_width;
|
|
int x1 = (urlhack_rx->endp[0] - window_text) % screen_width;
|
|
int y1 = (urlhack_rx->endp[0] - window_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 = urlhack_rx->endp[0] + 1;
|
|
}
|
|
#endif
|
|
}
|