mirror of
https://github.com/mintycube/st.git
synced 2024-10-22 14:05:49 +02:00
3eb170a9a5
The openurlonclick and scrollback patches are now working together, so links can be clicked in the scrollback buffer too. This update also adds url underlining and other improvements to the openurlonclick patch. The full list of changes in the openurlonclick patch: - Adds scrollback support - Adds modkey option - Better url detection - Underlines url when the mouse pointer is over a link - Opens a browser as a background process, so it won't lock the terminal anymore - Fixes a segmentation fault bug
141 lines
3.3 KiB
C
141 lines
3.3 KiB
C
#if SCROLLBACK_PATCH && !VIM_BROWSE_PATCH
|
|
#define TLINEURL(y) TLINE(y)
|
|
#else
|
|
#define TLINEURL(y) term.line[y]
|
|
#endif // SCROLLBACK_PATCH
|
|
|
|
#if VIM_BROWSE_PATCH
|
|
extern int buffCols;
|
|
#endif // VIM_BROWSE_PATCH
|
|
|
|
int url_x1, url_y1, url_x2, url_y2 = -1;
|
|
int url_draw, url_click, url_maxcol;
|
|
|
|
static int
|
|
isvalidurlchar(Rune u)
|
|
{
|
|
/* () and [] can appear in urls, but excluding them here will reduce false
|
|
* positives when figuring out where a given url ends. See copyurl patch.
|
|
*/
|
|
static char urlchars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
"abcdefghijklmnopqrstuvwxyz"
|
|
"0123456789-._~:/?#@!$&'*+,;=%";
|
|
return u < 128 && strchr(urlchars, (int)u) != NULL;
|
|
}
|
|
|
|
/* find the end of the wrapped line */
|
|
static int
|
|
findeowl(int row)
|
|
{
|
|
#if VIM_BROWSE_PATCH
|
|
int col = buffCols - 1;
|
|
#elif COLUMNS_PATCH
|
|
int col = term.maxcol - 1;
|
|
#else
|
|
int col = term.col - 1;
|
|
#endif // VIM_BROWSE_PATCH
|
|
|
|
do {
|
|
if (TLINEURL(row)[col].mode & ATTR_WRAP)
|
|
return col;
|
|
} while (TLINEURL(row)[col].u == ' ' && --col >= 0);
|
|
return -1;
|
|
}
|
|
|
|
void
|
|
clearurl(void)
|
|
{
|
|
while (url_y1 <= url_y2)
|
|
term.dirty[url_y1++] = 1;
|
|
url_y2 = -1;
|
|
}
|
|
|
|
char *
|
|
detecturl(int col, int row, int draw)
|
|
{
|
|
static char url[2048];
|
|
int x1, y1, x2, y2, wrapped;
|
|
int row_start = row;
|
|
int col_start = col;
|
|
int i = sizeof(url)/2+1, j = sizeof(url)/2;
|
|
#if SCROLLBACK_PATCH && !VIM_BROWSE_PATCH
|
|
int minrow = term.scr - term.histn, maxrow = term.scr + term.row - 1;
|
|
/* Fixme: MODE_ALTSCREEN is not defined here, I had to use the magic number 1<<2 */
|
|
if ((term.mode & (1 << 2)) != 0)
|
|
minrow = 0, maxrow = term.row - 1;
|
|
#else
|
|
int minrow = 0, maxrow = term.row - 1;
|
|
#endif // scrollback_patch
|
|
url_maxcol = 0;
|
|
|
|
/* clear previously underlined url */
|
|
if (draw)
|
|
clearurl();
|
|
|
|
if (!isvalidurlchar(TLINEURL(row)[col].u))
|
|
return NULL;
|
|
|
|
/* find the first character of url */
|
|
do {
|
|
x1 = col_start, y1 = row_start;
|
|
url_maxcol = MAX(url_maxcol, x1);
|
|
url[--i] = TLINEURL(row_start)[col_start].u;
|
|
if (--col_start < 0) {
|
|
if (--row_start < minrow || (col_start = findeowl(row_start)) < 0)
|
|
break;
|
|
}
|
|
} while (i > 0 && isvalidurlchar(TLINEURL(row_start)[col_start].u));
|
|
|
|
/* early detection */
|
|
if (url[i] != 'h')
|
|
return NULL;
|
|
|
|
/* find the last character of url */
|
|
do {
|
|
x2 = col, y2 = row;
|
|
url_maxcol = MAX(url_maxcol, x2);
|
|
url[j++] = TLINEURL(row)[col].u;
|
|
wrapped = TLINEURL(row)[col].mode & ATTR_WRAP;
|
|
#if VIM_BROWSE_PATCH
|
|
if (++col >= buffCols || wrapped) {
|
|
#elif COLUMNS_PATCH
|
|
if (++col >= term.maxcol || wrapped) {
|
|
#else
|
|
if (++col >= term.col || wrapped) {
|
|
#endif // VIM_BROWSE_PATCH
|
|
col = 0;
|
|
if (++row > maxrow || !wrapped)
|
|
break;
|
|
}
|
|
} while (j < sizeof(url)-1 && isvalidurlchar(TLINEURL(row)[col].u));
|
|
|
|
url[j] = 0;
|
|
|
|
if (strncmp("https://", &url[i], 8) && strncmp("http://", &url[i], 7))
|
|
return NULL;
|
|
|
|
/* underline url (see xdrawglyphfontspecs() in x.c) */
|
|
if (draw) {
|
|
url_x1 = (y1 >= 0) ? x1 : 0;
|
|
url_x2 = (y2 < term.row) ? x2 : url_maxcol;
|
|
url_y1 = MAX(y1, 0);
|
|
url_y2 = MIN(y2, term.row-1);
|
|
url_draw = 1;
|
|
for (y1 = url_y1; y1 <= url_y2; y1++)
|
|
term.dirty[y1] = 1;
|
|
}
|
|
|
|
return &url[i];
|
|
}
|
|
|
|
void
|
|
openUrlOnClick(int col, int row, char* url_opener)
|
|
{
|
|
char *url = detecturl(col, row, 1);
|
|
if (url) {
|
|
char command[strlen(url_opener) + strlen(url) + 5];
|
|
sprintf(command, "%s \"%s\"&", url_opener, url);
|
|
system(command);
|
|
}
|
|
}
|