Introduction
Introduction Statistics Contact Development Disclaimer Help
[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
+
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.