Compare commits
24 Commits
0.9
...
patch-clic
Author | SHA1 | Date | |
---|---|---|---|
b1e6c91433 | |||
98610fcd37 | |||
6009e6e25b | |||
a0274bc20e | |||
5dbcca4926 | |||
d63b9eb902 | |||
497a756382 | |||
8c68ec5241 | |||
5ce9716281 | |||
f20e169a20 | |||
95f22c5305 | |||
7473a8d1a5 | |||
a3f7420310 | |||
9846a56bd7 | |||
559fdc2786 | |||
8abe4bcb41 | |||
2fc7e532b2 | |||
a6bbc0c96b | |||
eb3b894f40 | |||
3a6d6d7401 | |||
211964d56e | |||
f17abd25b3 | |||
7e8050cc62 | |||
e5e959835b |
10
Makefile
10
Makefile
@ -7,13 +7,7 @@ include config.mk
|
||||
SRC = st.c x.c
|
||||
OBJ = $(SRC:.c=.o)
|
||||
|
||||
all: options st
|
||||
|
||||
options:
|
||||
@echo st build options:
|
||||
@echo "CFLAGS = $(STCFLAGS)"
|
||||
@echo "LDFLAGS = $(STLDFLAGS)"
|
||||
@echo "CC = $(CC)"
|
||||
all: st
|
||||
|
||||
config.h:
|
||||
cp config.def.h config.h
|
||||
@ -54,4 +48,4 @@ uninstall:
|
||||
rm -f $(DESTDIR)$(PREFIX)/bin/st
|
||||
rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1
|
||||
|
||||
.PHONY: all options clean dist install uninstall
|
||||
.PHONY: all clean dist install uninstall
|
||||
|
13
config.def.h
13
config.def.h
@ -53,7 +53,7 @@ int allowwindowops = 0;
|
||||
* near minlatency, but it waits longer for slow updates to avoid partial draw.
|
||||
* low minlatency will tear/flicker more, as it can "detect" idle too early.
|
||||
*/
|
||||
static double minlatency = 8;
|
||||
static double minlatency = 2;
|
||||
static double maxlatency = 33;
|
||||
|
||||
/*
|
||||
@ -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};
|
||||
|
@ -1,5 +1,5 @@
|
||||
# st version
|
||||
VERSION = 0.9
|
||||
VERSION = 0.9.2
|
||||
|
||||
# Customize below to fit your system
|
||||
|
||||
|
192
patches/st-clickurl-0.8.5.diff
Normal file
192
patches/st-clickurl-0.8.5.diff
Normal file
@ -0,0 +1,192 @@
|
||||
From d5b492049f48dc411b0dd7dc01a403304c20438d Mon Sep 17 00:00:00 2001
|
||||
From: Jishnu Sen <jishnu1@gmail.com>
|
||||
Date: Sun, 7 Apr 2024 22:54:46 -0700
|
||||
Subject: [PATCH] Highlight URLs with control and follow with click
|
||||
|
||||
---
|
||||
config.def.h | 11 +++++++
|
||||
st.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
st.h | 9 ++++++
|
||||
x.c | 24 +++++++++++++-
|
||||
4 files changed, 132 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 91ab8ca..4961830 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 51049ba..8f2156c 100644
|
||||
--- a/st.c
|
||||
+++ b/st.c
|
||||
@@ -643,6 +643,95 @@ 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
|
||||
+highlighturls(void)
|
||||
+{
|
||||
+ char *match;
|
||||
+ char *linestr = calloc(sizeof(char), term.col+1); /* assume ascii */
|
||||
+ for (int i = term.top; i < term.bot; i++) {
|
||||
+ int url_start = -1;
|
||||
+ for (int j = 0; j < term.col; j++) {
|
||||
+ if (term.line[i][j].u < 127) {
|
||||
+ linestr[j] = term.line[i][j].u;
|
||||
+ }
|
||||
+ linestr[term.col] = '\0';
|
||||
+ }
|
||||
+ while ((match = strstrany(linestr + url_start + 1, urlprefixes))) {
|
||||
+ url_start = match - linestr;
|
||||
+ for (int c = url_start; c < term.col && strchr(urlchars, linestr[c]); c++) {
|
||||
+ term.line[i][c].mode |= ATTR_URL;
|
||||
+ tsetdirt(i, c);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ free(linestr);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+unhighlighturls(void)
|
||||
+{
|
||||
+ for (int i = term.top; i < term.bot; i++) {
|
||||
+ for (int j = 0; j < term.col; j++) {
|
||||
+ Glyph* g = &term.line[i][j];
|
||||
+ if (g->mode & ATTR_URL) {
|
||||
+ g->mode &= ~ATTR_URL;
|
||||
+ tsetdirt(i, j);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+followurl(int x, int y) {
|
||||
+ char *linestr = calloc(sizeof(char), term.col+1); /* assume ascii */
|
||||
+ char *match;
|
||||
+ for (int i = 0; i < term.col; i++) {
|
||||
+ if (term.line[x][i].u < 127) {
|
||||
+ linestr[i] = term.line[x][i].u;
|
||||
+ }
|
||||
+ linestr[term.col] = '\0';
|
||||
+ }
|
||||
+ int url_start = -1;
|
||||
+ 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, linestr[c]); c++) {
|
||||
+ url_end++;
|
||||
+ }
|
||||
+ if (url_start <= y && y < url_end) {
|
||||
+ linestr[url_end] = '\0';
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (url_start == -1) {
|
||||
+ free(linestr);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ pid_t chpid;
|
||||
+ if ((chpid = fork()) == 0) {
|
||||
+ if (fork() == 0)
|
||||
+ execlp(urlhandler, urlhandler, linestr + url_start, NULL);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ if (chpid > 0)
|
||||
+ waitpid(chpid, NULL, 0);
|
||||
+ free(linestr);
|
||||
+ unhighlighturls();
|
||||
+}
|
||||
+
|
||||
void
|
||||
selclear(void)
|
||||
{
|
||||
diff --git a/st.h b/st.h
|
||||
index 519b9bd..354e7f9 100644
|
||||
--- a/st.h
|
||||
+++ b/st.h
|
||||
@@ -34,6 +34,7 @@ enum glyph_attribute {
|
||||
ATTR_WIDE = 1 << 9,
|
||||
ATTR_WDUMMY = 1 << 10,
|
||||
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
|
||||
+ ATTR_URL = 1 << 14,
|
||||
};
|
||||
|
||||
enum selection_mode {
|
||||
@@ -105,6 +106,10 @@ void selextend(int, int, int, int);
|
||||
int selected(int, int);
|
||||
char *getsel(void);
|
||||
|
||||
+void highlighturls(void);
|
||||
+void unhighlighturls(void);
|
||||
+void followurl(int, int);
|
||||
+
|
||||
size_t utf8encode(Rune, char *);
|
||||
|
||||
void *xmalloc(size_t);
|
||||
@@ -126,3 +131,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 8a16faa..13f68e4 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,
|
||||
@@ -445,6 +446,15 @@ 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 &&
|
||||
+ (match(ControlMask, state) ||
|
||||
+ match(ControlMask, state & ~forcemousemod))) {
|
||||
+ followurl(evrow(e), evcol(e));
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) {
|
||||
if (ms->release == release &&
|
||||
ms->button == e->xbutton.button &&
|
||||
2.44.0
|
||||
|
137
st.c
137
st.c
@ -636,6 +636,95 @@ 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
|
||||
highlighturls(void)
|
||||
{
|
||||
char *match;
|
||||
char *linestr = calloc(sizeof(char), term.col+1); /* assume ascii */
|
||||
for (int i = term.top; i < term.bot; i++) {
|
||||
int url_start = -1;
|
||||
for (int j = 0; j < term.col; j++) {
|
||||
if (term.line[i][j].u < 127) {
|
||||
linestr[j] = term.line[i][j].u;
|
||||
}
|
||||
linestr[term.col] = '\0';
|
||||
}
|
||||
while ((match = strstrany(linestr + url_start + 1, urlprefixes))) {
|
||||
url_start = match - linestr;
|
||||
for (int c = url_start; c < term.col && strchr(urlchars, linestr[c]); c++) {
|
||||
term.line[i][c].mode |= ATTR_URL;
|
||||
tsetdirt(i, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(linestr);
|
||||
}
|
||||
|
||||
void
|
||||
unhighlighturls(void)
|
||||
{
|
||||
for (int i = term.top; i < term.bot; i++) {
|
||||
for (int j = 0; j < term.col; j++) {
|
||||
Glyph* g = &term.line[i][j];
|
||||
if (g->mode & ATTR_URL) {
|
||||
g->mode &= ~ATTR_URL;
|
||||
tsetdirt(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
followurl(int x, int y) {
|
||||
char *linestr = calloc(sizeof(char), term.col+1); /* assume ascii */
|
||||
char *match;
|
||||
for (int i = 0; i < term.col; i++) {
|
||||
if (term.line[x][i].u < 127) {
|
||||
linestr[i] = term.line[x][i].u;
|
||||
}
|
||||
linestr[term.col] = '\0';
|
||||
}
|
||||
int url_start = -1;
|
||||
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, linestr[c]); c++) {
|
||||
url_end++;
|
||||
}
|
||||
if (url_start <= y && y < url_end) {
|
||||
linestr[url_end] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (url_start == -1) {
|
||||
free(linestr);
|
||||
return;
|
||||
}
|
||||
|
||||
pid_t chpid;
|
||||
if ((chpid = fork()) == 0) {
|
||||
if (fork() == 0)
|
||||
execlp(urlhandler, urlhandler, linestr + url_start, NULL);
|
||||
exit(1);
|
||||
}
|
||||
if (chpid > 0)
|
||||
waitpid(chpid, NULL, 0);
|
||||
free(linestr);
|
||||
unhighlighturls();
|
||||
}
|
||||
|
||||
void
|
||||
selclear(void)
|
||||
{
|
||||
@ -1097,7 +1186,7 @@ tscrollup(int orig, int n)
|
||||
void
|
||||
selscroll(int orig, int n)
|
||||
{
|
||||
if (sel.ob.x == -1)
|
||||
if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN))
|
||||
return;
|
||||
|
||||
if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) {
|
||||
@ -1132,6 +1221,7 @@ csiparse(void)
|
||||
{
|
||||
char *p = csiescseq.buf, *np;
|
||||
long int v;
|
||||
int sep = ';'; /* colon or semi-colon, but not both */
|
||||
|
||||
csiescseq.narg = 0;
|
||||
if (*p == '?') {
|
||||
@ -1149,7 +1239,9 @@ csiparse(void)
|
||||
v = -1;
|
||||
csiescseq.arg[csiescseq.narg++] = v;
|
||||
p = np;
|
||||
if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ)
|
||||
if (sep == ';' && *p == ':')
|
||||
sep = ':'; /* allow override to colon once */
|
||||
if (*p != sep || csiescseq.narg == ESC_ARG_SIZ)
|
||||
break;
|
||||
p++;
|
||||
}
|
||||
@ -1643,7 +1735,7 @@ csihandle(void)
|
||||
ttywrite(vtiden, strlen(vtiden), 0);
|
||||
break;
|
||||
case 'b': /* REP -- if last char is printable print it <n> more times */
|
||||
DEFAULT(csiescseq.arg[0], 1);
|
||||
LIMIT(csiescseq.arg[0], 1, 65535);
|
||||
if (term.lastc)
|
||||
while (csiescseq.arg[0]-- > 0)
|
||||
tputc(term.lastc);
|
||||
@ -1702,7 +1794,7 @@ csihandle(void)
|
||||
}
|
||||
break;
|
||||
case 1: /* above */
|
||||
if (term.c.y > 1)
|
||||
if (term.c.y > 0)
|
||||
tclearregion(0, 0, term.col-1, term.c.y-1);
|
||||
tclearregion(0, term.c.y, term.c.x, term.c.y);
|
||||
break;
|
||||
@ -1728,6 +1820,7 @@ csihandle(void)
|
||||
}
|
||||
break;
|
||||
case 'S': /* SU -- Scroll <n> line up */
|
||||
if (csiescseq.priv) break;
|
||||
DEFAULT(csiescseq.arg[0], 1);
|
||||
tscrollup(term.top, csiescseq.arg[0]);
|
||||
break;
|
||||
@ -1769,11 +1862,18 @@ csihandle(void)
|
||||
case 'm': /* SGR -- Terminal attribute (color) */
|
||||
tsetattr(csiescseq.arg, csiescseq.narg);
|
||||
break;
|
||||
case 'n': /* DSR – Device Status Report (cursor position) */
|
||||
if (csiescseq.arg[0] == 6) {
|
||||
case 'n': /* DSR -- Device Status Report */
|
||||
switch (csiescseq.arg[0]) {
|
||||
case 5: /* Status Report "OK" `0n` */
|
||||
ttywrite("\033[0n", sizeof("\033[0n") - 1, 0);
|
||||
break;
|
||||
case 6: /* Report Cursor Position (CPR) "<row>;<column>R" */
|
||||
len = snprintf(buf, sizeof(buf), "\033[%i;%iR",
|
||||
term.c.y+1, term.c.x+1);
|
||||
term.c.y+1, term.c.x+1);
|
||||
ttywrite(buf, len, 0);
|
||||
break;
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
break;
|
||||
case 'r': /* DECSTBM -- Set Scrolling Region */
|
||||
@ -1790,7 +1890,11 @@ csihandle(void)
|
||||
tcursor(CURSOR_SAVE);
|
||||
break;
|
||||
case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */
|
||||
tcursor(CURSOR_LOAD);
|
||||
if (csiescseq.priv) {
|
||||
goto unknown;
|
||||
} else {
|
||||
tcursor(CURSOR_LOAD);
|
||||
}
|
||||
break;
|
||||
case ' ':
|
||||
switch (csiescseq.mode[1]) {
|
||||
@ -1932,8 +2036,10 @@ strhandle(void)
|
||||
if (p && !strcmp(p, "?")) {
|
||||
osc_color_response(j, 0, 1);
|
||||
} else if (xsetcolorname(j, p)) {
|
||||
if (par == 104 && narg <= 1)
|
||||
if (par == 104 && narg <= 1) {
|
||||
xloadcols();
|
||||
return; /* color reset without parameter */
|
||||
}
|
||||
fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
|
||||
j, p ? p : "(null)");
|
||||
} else {
|
||||
@ -2321,6 +2427,7 @@ eschandle(uchar ascii)
|
||||
treset();
|
||||
resettitle();
|
||||
xloadcols();
|
||||
xsetmode(0, MODE_HIDE);
|
||||
break;
|
||||
case '=': /* DECPAM -- Application keypad */
|
||||
xsetmode(1, MODE_APPKEYPAD);
|
||||
@ -2413,6 +2520,9 @@ check_control_code:
|
||||
* they must not cause conflicts with sequences.
|
||||
*/
|
||||
if (control) {
|
||||
/* in UTF-8 mode ignore handling C1 control characters */
|
||||
if (IS_SET(MODE_UTF8) && ISCONTROLC1(u))
|
||||
return;
|
||||
tcontrolcode(u);
|
||||
/*
|
||||
* control codes are not shown ever
|
||||
@ -2459,11 +2569,16 @@ check_control_code:
|
||||
gp = &term.line[term.c.y][term.c.x];
|
||||
}
|
||||
|
||||
if (IS_SET(MODE_INSERT) && term.c.x+width < term.col)
|
||||
if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) {
|
||||
memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph));
|
||||
gp->mode &= ~ATTR_WIDE;
|
||||
}
|
||||
|
||||
if (term.c.x+width > term.col) {
|
||||
tnewline(1);
|
||||
if (IS_SET(MODE_WRAP))
|
||||
tnewline(1);
|
||||
else
|
||||
tmoveto(term.col - width, term.c.y);
|
||||
gp = &term.line[term.c.y][term.c.x];
|
||||
}
|
||||
|
||||
|
9
st.h
9
st.h
@ -34,6 +34,7 @@ enum glyph_attribute {
|
||||
ATTR_WIDE = 1 << 9,
|
||||
ATTR_WDUMMY = 1 << 10,
|
||||
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
|
||||
ATTR_URL = 1 << 14,
|
||||
};
|
||||
|
||||
enum selection_mode {
|
||||
@ -105,6 +106,10 @@ void selextend(int, int, int, int);
|
||||
int selected(int, int);
|
||||
char *getsel(void);
|
||||
|
||||
void highlighturls(void);
|
||||
void unhighlighturls(void);
|
||||
void 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;
|
||||
|
4
st.info
4
st.info
@ -184,6 +184,10 @@ st-mono| simpleterm monocolor,
|
||||
# XTerm extensions
|
||||
rmxx=\E[29m,
|
||||
smxx=\E[9m,
|
||||
BE=\E[?2004h,
|
||||
BD=\E[?2004l,
|
||||
PS=\E[200~,
|
||||
PE=\E[201~,
|
||||
# disabled rep for now: causes some issues with older ncurses versions.
|
||||
# rep=%p1%c\E[%p2%{1}%-%db,
|
||||
# tmux extensions, see TERMINFO EXTENSIONS in tmux(1)
|
||||
|
54
x.c
54
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,15 @@ 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 &&
|
||||
(match(ControlMask, state) ||
|
||||
match(ControlMask, state & ~forcemousemod))) {
|
||||
followurl(evrow(e), evcol(e));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) {
|
||||
if (ms->release == release &&
|
||||
ms->button == e->xbutton.button &&
|
||||
@ -818,7 +828,7 @@ xloadcols(void)
|
||||
int
|
||||
xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b)
|
||||
{
|
||||
if (!BETWEEN(x, 0, dc.collen))
|
||||
if (!BETWEEN(x, 0, dc.collen - 1))
|
||||
return 1;
|
||||
|
||||
*r = dc.col[x].color.red >> 8;
|
||||
@ -833,7 +843,7 @@ xsetcolorname(int x, const char *name)
|
||||
{
|
||||
Color ncolor;
|
||||
|
||||
if (!BETWEEN(x, 0, dc.collen))
|
||||
if (!BETWEEN(x, 0, dc.collen - 1))
|
||||
return 1;
|
||||
|
||||
if (!xloadcolor(x, name, &ncolor))
|
||||
@ -1131,7 +1141,7 @@ xinit(int cols, int rows)
|
||||
{
|
||||
XGCValues gcvalues;
|
||||
Cursor cursor;
|
||||
Window parent;
|
||||
Window parent, root;
|
||||
pid_t thispid = getpid();
|
||||
XColor xmousefg, xmousebg;
|
||||
|
||||
@ -1168,16 +1178,19 @@ xinit(int cols, int rows)
|
||||
| ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
|
||||
xw.attrs.colormap = xw.cmap;
|
||||
|
||||
root = XRootWindow(xw.dpy, xw.scr);
|
||||
if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0))))
|
||||
parent = XRootWindow(xw.dpy, xw.scr);
|
||||
xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t,
|
||||
parent = root;
|
||||
xw.win = XCreateWindow(xw.dpy, root, xw.l, xw.t,
|
||||
win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput,
|
||||
xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity
|
||||
| CWEventMask | CWColormap, &xw.attrs);
|
||||
if (parent != root)
|
||||
XReparentWindow(xw.dpy, xw.win, parent, xw.l, xw.t);
|
||||
|
||||
memset(&gcvalues, 0, sizeof(gcvalues));
|
||||
gcvalues.graphics_exposures = False;
|
||||
dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures,
|
||||
dc.gc = XCreateGC(xw.dpy, xw.win, GCGraphicsExposures,
|
||||
&gcvalues);
|
||||
xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h,
|
||||
DefaultDepth(xw.dpy, xw.scr));
|
||||
@ -1492,7 +1505,7 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
|
||||
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 * chscale + 1,
|
||||
width, 1);
|
||||
}
|
||||
@ -1617,6 +1630,9 @@ xseticontitle(char *p)
|
||||
XTextProperty prop;
|
||||
DEFAULT(p, opt_title);
|
||||
|
||||
if (p[0] == '\0')
|
||||
p = opt_title;
|
||||
|
||||
if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
|
||||
&prop) != Success)
|
||||
return;
|
||||
@ -1631,6 +1647,9 @@ xsettitle(char *p)
|
||||
XTextProperty prop;
|
||||
DEFAULT(p, opt_title);
|
||||
|
||||
if (p[0] == '\0')
|
||||
p = opt_title;
|
||||
|
||||
if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
|
||||
&prop) != Success)
|
||||
return;
|
||||
@ -1833,7 +1852,7 @@ void
|
||||
kpress(XEvent *ev)
|
||||
{
|
||||
XKeyEvent *e = &ev->xkey;
|
||||
KeySym ksym;
|
||||
KeySym ksym = NoSymbol;
|
||||
char buf[64], *customkey;
|
||||
int len;
|
||||
Rune c;
|
||||
@ -1843,10 +1862,25 @@ kpress(XEvent *ev)
|
||||
if (IS_SET(MODE_KBDLOCK))
|
||||
return;
|
||||
|
||||
if (xw.ime.xic)
|
||||
if (xw.ime.xic) {
|
||||
len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status);
|
||||
else
|
||||
if (status == XBufferOverflow)
|
||||
return;
|
||||
} else {
|
||||
len = XLookupString(e, buf, sizeof buf, &ksym, NULL);
|
||||
}
|
||||
|
||||
/* 0. highlight URLs when control held */
|
||||
if (ksym == XK_Control_L) {
|
||||
highlighturls();
|
||||
} else if (ev->type == KeyRelease && e->keycode == XKeysymToKeycode(e->display, XK_Control_L)) {
|
||||
unhighlighturls();
|
||||
}
|
||||
|
||||
/* 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)) {
|
||||
|
Reference in New Issue
Block a user