[st][patch][clickurl-nocontrol] rebase to 0.9.2 - sites - public wiki contents … | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
commit cfa09ab783ca478ab7d4ba81b3215d455ad92e18 | |
parent 28ebdf173efca3ce3e297d55a72d6f4be2ec552a | |
Author: kroovy <[email protected]> | |
Date: Sun, 2 Mar 2025 00:08:22 +0100 | |
[st][patch][clickurl-nocontrol] rebase to 0.9.2 | |
Diffstat: | |
M st.suckless.org/patches/clickurl-n… | 2 ++ | |
A st.suckless.org/patches/clickurl-n… | 215 +++++++++++++++++++++++++++… | |
2 files changed, 217 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/st.suckless.org/patches/clickurl-nocontrol/index.md b/st.suckless.… | |
@@ -13,7 +13,9 @@ Notes | |
Download | |
-------- | |
* [st-clickurl-nocontrol-0.8.5.diff](st-clickurl-nocontrol-0.8.5.diff) | |
+* [st-clickurl-nocontrol-0.9.2.diff](st-clickurl-nocontrol-0.9.2.diff) | |
Authors | |
------- | |
* Kyle Chui - <[email protected]> | |
+* kroovy - <[email protected]> | |
diff --git a/st.suckless.org/patches/clickurl-nocontrol/st-clickurl-nocontrol-0… | |
@@ -0,0 +1,215 @@ | |
+From a5ac9200f9146b212c0cd87fcb3fae357f39cc53 Mon Sep 17 00:00:00 2001 | |
+From: kroovy <[email protected]> | |
+Date: Sat, 1 Mar 2025 23:44:55 +0100 | |
+Subject: [PATCH] Underline URLs and follow with click | |
+ | |
+--- | |
+ config.def.h | 11 +++++++ | |
+ st.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
+ st.h | 9 ++++++ | |
+ x.c | 12 ++++++- | |
+ 4 files changed, 119 insertions(+), 1 deletion(-) | |
+ | |
+diff --git a/config.def.h b/config.def.h | |
+index 2cd740a..0eadbce 100644 | |
+--- a/config.def.h | |
++++ b/config.def.h | |
+@@ -472,3 +472,14 @@ static char ascii_printable[] = | |
+ " !\"#$%&'()*+,-./0123456789:;<=>?" | |
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" | |
+ "`abcdefghijklmnopqrstuvwxyz{|}~"; | |
++ | |
++/* | |
++ * Open urls starting with urlprefixes, contatining urlchars | |
++ * by passing as ARG1 to urlhandler. | |
++ */ | |
++char* urlhandler = "xdg-open"; | |
++char urlchars[] = | |
++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
++ "abcdefghijklmnopqrstuvwxyz" | |
++ "0123456789-._~:/?#@!$&'*+,;=%"; | |
++char* urlprefixes[] = {"http://", "https://", NULL}; | |
+diff --git a/st.c b/st.c | |
+index 03b9bc8..75347c6 100644 | |
+--- a/st.c | |
++++ b/st.c | |
+@@ -636,6 +636,92 @@ getsel(void) | |
+ return str; | |
+ } | |
+ | |
++char * | |
++strstrany(char* s, char** strs) { | |
++ char *match; | |
++ for (int i = 0; strs[i]; i++) { | |
++ if ((match = strstr(s, strs[i]))) { | |
++ return match; | |
++ } | |
++ } | |
++ return NULL; | |
++} | |
++ | |
++void | |
++highlighturlsline(int row) | |
++{ | |
++ char *linestr = calloc(sizeof(char), term.col+1); /* assume ascii */ | |
++ char *match; | |
++ for (int j = 0; j < term.col; j++) { | |
++ if (term.line[row][j].u < 127) { | |
++ linestr[j] = term.line[row][j].u; | |
++ } | |
++ linestr[term.col] = '\0'; | |
++ } | |
++ int url_start = -1; | |
++ while ((match = strstrany(linestr + url_start + 1, urlprefixes))) { | |
++ url_start = match - linestr; | |
++ for (int c = url_start; c < term.col && strchr(urlchars, line… | |
++ term.line[row][c].mode |= ATTR_URL; | |
++ tsetdirt(row, c); | |
++ } | |
++ } | |
++ free(linestr); | |
++} | |
++ | |
++void | |
++unhighlighturlsline(int row) | |
++{ | |
++ for (int j = 0; j < term.col; j++) { | |
++ Glyph* g = &term.line[row][j]; | |
++ if (g->mode & ATTR_URL) { | |
++ g->mode &= ~ATTR_URL; | |
++ tsetdirt(row, j); | |
++ } | |
++ } | |
++ return; | |
++} | |
++ | |
++int | |
++followurl(int col, int row) { | |
++ char *linestr = calloc(sizeof(char), term.col+1); /* assume ascii */ | |
++ char *match; | |
++ for (int i = 0; i < term.col; i++) { | |
++ if (term.line[row][i].u < 127) { | |
++ linestr[i] = term.line[row][i].u; | |
++ } | |
++ linestr[term.col] = '\0'; | |
++ } | |
++ int url_start = -1, found_url = 0; | |
++ while ((match = strstrany(linestr + url_start + 1, urlprefixes))) { | |
++ url_start = match - linestr; | |
++ int url_end = url_start; | |
++ for (int c = url_start; c < term.col && strchr(urlchars, line… | |
++ url_end++; | |
++ } | |
++ if (url_start <= col && col < url_end) { | |
++ found_url = 1; | |
++ linestr[url_end] = '\0'; | |
++ break; | |
++ } | |
++ } | |
++ if (!found_url) { | |
++ free(linestr); | |
++ return 0; | |
++ } | |
++ | |
++ pid_t chpid; | |
++ if ((chpid = fork()) == 0) { | |
++ if (fork() == 0) | |
++ execlp(urlhandler, urlhandler, linestr + url_start, N… | |
++ exit(1); | |
++ } | |
++ if (chpid > 0) | |
++ waitpid(chpid, NULL, 0); | |
++ free(linestr); | |
++ return 1; | |
++} | |
++ | |
+ void | |
+ selclear(void) | |
+ { | |
+@@ -2644,6 +2730,8 @@ drawregion(int x1, int y1, int x2, int y2) | |
+ continue; | |
+ | |
+ term.dirty[y] = 0; | |
++ unhighlighturlsline(y); | |
++ highlighturlsline(y); | |
+ xdrawline(term.line[y], x1, y, x2); | |
+ } | |
+ } | |
+diff --git a/st.h b/st.h | |
+index fd3b0d8..ee0db89 100644 | |
+--- a/st.h | |
++++ b/st.h | |
+@@ -33,6 +33,7 @@ enum glyph_attribute { | |
+ ATTR_WRAP = 1 << 8, | |
+ ATTR_WIDE = 1 << 9, | |
+ ATTR_WDUMMY = 1 << 10, | |
++ ATTR_URL = 1 << 11, | |
+ ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, | |
+ }; | |
+ | |
+@@ -105,6 +106,10 @@ void selextend(int, int, int, int); | |
+ int selected(int, int); | |
+ char *getsel(void); | |
+ | |
++void highlighturlsline(int); | |
++void unhighlighturlsline(int); | |
++int followurl(int, int); | |
++ | |
+ size_t utf8encode(Rune, char *); | |
+ | |
+ void *xmalloc(size_t); | |
+@@ -124,3 +129,7 @@ extern unsigned int tabspaces; | |
+ extern unsigned int defaultfg; | |
+ extern unsigned int defaultbg; | |
+ extern unsigned int defaultcs; | |
++extern char *urlhandler; | |
++extern char urlchars[]; | |
++extern char *urlprefixes[]; | |
++extern int nurlprefixes; | |
+diff --git a/x.c b/x.c | |
+index d73152b..e2d4d56 100644 | |
+--- a/x.c | |
++++ b/x.c | |
+@@ -191,6 +191,7 @@ static void usage(void); | |
+ | |
+ static void (*handler[LASTEvent])(XEvent *) = { | |
+ [KeyPress] = kpress, | |
++ [KeyRelease] = kpress, | |
+ [ClientMessage] = cmessage, | |
+ [ConfigureNotify] = resize, | |
+ [VisibilityNotify] = visibility, | |
+@@ -452,6 +453,10 @@ mouseaction(XEvent *e, uint release) | |
+ /* ignore Button<N>mask for Button<N> - it's set on release */ | |
+ uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); | |
+ | |
++ if (release == 0 && e->xbutton.button == Button1) { | |
++ return followurl(evcol(e), evrow(e)); | |
++ } | |
++ | |
+ for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { | |
+ if (ms->release == release && | |
+ ms->button == e->xbutton.button && | |
+@@ -1495,7 +1500,7 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph… | |
+ XftDrawGlyphFontSpec(xw.draw, fg, specs, len); | |
+ | |
+ /* Render underline and strikethrough. */ | |
+- if (base.mode & ATTR_UNDERLINE) { | |
++ if (base.mode & ATTR_UNDERLINE || base.mode & ATTR_URL) { | |
+ XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscal… | |
+ width, 1); | |
+ } | |
+@@ -1859,6 +1864,11 @@ kpress(XEvent *ev) | |
+ } else { | |
+ len = XLookupString(e, buf, sizeof buf, &ksym, NULL); | |
+ } | |
++ | |
++ /* KeyRelease not relevant to shortcuts */ | |
++ if (ev->type == KeyRelease) | |
++ return; | |
++ | |
+ /* 1. shortcuts */ | |
+ for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { | |
+ if (ksym == bp->keysym && match(bp->mod, e->state)) { | |
+-- | |
+2.48.1 | |
+ |