Add scrollback support to the openurlonclick patch
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
This commit is contained in:
parent
9e0e419781
commit
3eb170a9a5
9 changed files with 256 additions and 64 deletions
|
|
@ -1,59 +1,140 @@
|
|||
#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)
|
||||
{
|
||||
int row_start = row;
|
||||
int col_start = col;
|
||||
int row_end = row;
|
||||
int col_end = col;
|
||||
|
||||
if (term.line[row][col].u == ' ')
|
||||
return;
|
||||
|
||||
/* while previous character is not space */
|
||||
while (term.line[row_start][col_start-1].u != ' ') {
|
||||
if (col_start == 0)
|
||||
{
|
||||
// Before moving start pointer to the previous line we check if it ends with space
|
||||
if (term.line[row_start - 1][term.col - 1].u == ' ')
|
||||
break;
|
||||
col_start=term.col - 1;
|
||||
row_start--;
|
||||
} else {
|
||||
col_start--;
|
||||
}
|
||||
}
|
||||
|
||||
/* while next character is not space nor end of line */
|
||||
while (term.line[row_end][col_end].u != ' ') {
|
||||
col_end++;
|
||||
if (col_end == term.col - 1)
|
||||
{
|
||||
if (term.line[row_end + 1][0].u == ' ')
|
||||
break;
|
||||
col_end=0;
|
||||
row_end++;
|
||||
}
|
||||
}
|
||||
|
||||
char url[200] = "";
|
||||
int url_index=0;
|
||||
do {
|
||||
url[url_index] = term.line[row_start][col_start].u;
|
||||
url_index++;
|
||||
col_start++;
|
||||
if (col_start == term.col)
|
||||
{
|
||||
col_start = 0;
|
||||
row_start++;
|
||||
}
|
||||
} while (url_index < (sizeof(url)-1) &&
|
||||
(row_start != row_end || col_start != col_end));
|
||||
|
||||
if (strncmp("http", url, 4) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
char command[strlen(url_opener)+strlen(url)+2];
|
||||
sprintf(command, "%s %s", url_opener, url);
|
||||
system(command);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,6 @@
|
|||
static void openUrlOnClick(int col, int row, char* url_opener);
|
||||
static inline void restoremousecursor(void) {
|
||||
if (!(win.mode & MODE_MOUSE) && xw.pointerisvisible)
|
||||
XDefineCursor(xw.dpy, xw.win, xw.vpointer);
|
||||
}
|
||||
static void clearurl(void);
|
||||
static void openUrlOnClick(int col, int row, char* url_opener);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ kscrolldown(const Arg* a)
|
|||
#if SIXEL_PATCH
|
||||
scroll_images(-1*n);
|
||||
#endif // SIXEL_PATCH
|
||||
|
||||
#if OPENURLONCLICK_PATCH
|
||||
if (n > 0)
|
||||
restoremousecursor();
|
||||
#endif // OPENURLONCLICK_PATCH
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -42,4 +47,9 @@ kscrollup(const Arg* a)
|
|||
#if SIXEL_PATCH
|
||||
scroll_images(n);
|
||||
#endif // SIXEL_PATCH
|
||||
|
||||
#if OPENURLONCLICK_PATCH
|
||||
if (n > 0)
|
||||
restoremousecursor();
|
||||
#endif // OPENURLONCLICK_PATCH
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@
|
|||
#if KEYBOARDSELECT_PATCH
|
||||
#include "keyboardselect_st.h"
|
||||
#endif
|
||||
#if OPENURLONCLICK_PATCH
|
||||
#include "openurlonclick.h"
|
||||
#endif
|
||||
#if RIGHTCLICKTOPLUMB_PATCH
|
||||
#include "rightclicktoplumb_st.h"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,9 +20,6 @@
|
|||
#if NETWMICON_PATCH
|
||||
#include "netwmicon.h"
|
||||
#endif
|
||||
#if OPENURLONCLICK_PATCH
|
||||
#include "openurlonclick.h"
|
||||
#endif
|
||||
#if RIGHTCLICKTOPLUMB_PATCH
|
||||
#include "rightclicktoplumb_x.h"
|
||||
#endif
|
||||
|
|
@ -34,4 +31,4 @@
|
|||
#endif
|
||||
#if VIM_BROWSE_PATCH
|
||||
#include "normalMode.h"
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue