clean slate
This commit is contained in:
parent
524b43d249
commit
68605797c9
51 changed files with 697 additions and 4812 deletions
|
@ -8,7 +8,7 @@ MIT/X Consortium License
|
||||||
© 2009 Markus Schnalke <meillo@marmaro.de>
|
© 2009 Markus Schnalke <meillo@marmaro.de>
|
||||||
© 2009 Evan Gates <evan.gates@gmail.com>
|
© 2009 Evan Gates <evan.gates@gmail.com>
|
||||||
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
|
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
|
||||||
© 2014-2020 Hiltjo Posthuma <hiltjo@codemadness.org>
|
© 2014-2022 Hiltjo Posthuma <hiltjo@codemadness.org>
|
||||||
© 2015-2019 Quentin Rameau <quinq@fifth.space>
|
© 2015-2019 Quentin Rameau <quinq@fifth.space>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
|
|
@ -1,31 +1,20 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
/* See LICENSE file for copyright and license details. */
|
||||||
/* Default settings; can be overriden by command line. */
|
/* Default settings; can be overriden by command line. */
|
||||||
|
|
||||||
|
|
||||||
static const char bg1[] = "#1c1e26";
|
|
||||||
static const char bg2[] = "#2e303e";
|
|
||||||
|
|
||||||
static const char fg1[] = "#9da0a2";
|
|
||||||
static const char fg2[] = "#dcdfe4";
|
|
||||||
|
|
||||||
|
|
||||||
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
|
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
|
||||||
/* -fn option overrides fonts[0]; default X11 font or font set */
|
/* -fn option overrides fonts[0]; default X11 font or font set */
|
||||||
static const char *fonts[] = {
|
static const char *fonts[] = {
|
||||||
"JetBrainsMono Nerd Font:size=10:antialias=true:autohint=true"
|
"monospace:size=10"
|
||||||
};
|
};
|
||||||
static const char *prompt = NULL; /* -p option; prompt to the left of input field */
|
static const char *prompt = NULL; /* -p option; prompt to the left of input field */
|
||||||
static const char *colors[SchemeLast][2] = {
|
static const char *colors[SchemeLast][2] = {
|
||||||
/* fg bg */
|
/* fg bg */
|
||||||
[SchemeNorm] = { fg1, bg1 },
|
[SchemeNorm] = { "#bbbbbb", "#222222" },
|
||||||
[SchemeSel] = { fg2, bg2 },
|
[SchemeSel] = { "#eeeeee", "#005577" },
|
||||||
[SchemeOut] = { "#000000", "#00ffff" },
|
[SchemeOut] = { "#000000", "#00ffff" },
|
||||||
};
|
};
|
||||||
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
|
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
|
||||||
static unsigned int lines = 0;
|
static unsigned int lines = 0;
|
||||||
/* -h option; minimum height of a menu line */
|
|
||||||
static unsigned int lineheight = 28;
|
|
||||||
static unsigned int min_lineheight = 8;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Characters not considered part of a word while deleting words
|
* Characters not considered part of a word while deleting words
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
/* Default settings; can be overriden by command line. */
|
|
||||||
|
|
||||||
|
|
||||||
static const char bg1[] = "#1c1e26";
|
|
||||||
static const char bg2[] = "#2e303e";
|
|
||||||
|
|
||||||
static const char fg1[] = "#9da0a2";
|
|
||||||
static const char fg2[] = "#dcdfe4";
|
|
||||||
|
|
||||||
|
|
||||||
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
|
|
||||||
/* -fn option overrides fonts[0]; default X11 font or font set */
|
|
||||||
static const char *fonts[] = {
|
|
||||||
"JetBrainsMono Nerd Font:size=10:antialias=true:autohint=true"
|
|
||||||
};
|
|
||||||
static const char *prompt = NULL; /* -p option; prompt to the left of input field */
|
|
||||||
static const char *colors[SchemeLast][2] = {
|
|
||||||
/* fg bg */
|
|
||||||
[SchemeNorm] = { fg1, bg1 },
|
|
||||||
[SchemeSel] = { fg2, bg2 },
|
|
||||||
[SchemeOut] = { "#000000", "#00ffff" },
|
|
||||||
};
|
|
||||||
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
|
|
||||||
static unsigned int lines = 0;
|
|
||||||
/* -h option; minimum height of a menu line */
|
|
||||||
static unsigned int lineheight = 28;
|
|
||||||
static unsigned int min_lineheight = 8;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Characters not considered part of a word while deleting words
|
|
||||||
* for example: " /?\"&[]"
|
|
||||||
*/
|
|
||||||
static const char worddelimiters[] = " ";
|
|
|
@ -1,5 +1,5 @@
|
||||||
# dmenu version
|
# dmenu version
|
||||||
VERSION = 5.0
|
VERSION = 5.2
|
||||||
|
|
||||||
# paths
|
# paths
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
|
@ -17,6 +17,7 @@ FREETYPELIBS = -lfontconfig -lXft
|
||||||
FREETYPEINC = /usr/include/freetype2
|
FREETYPEINC = /usr/include/freetype2
|
||||||
# OpenBSD (uncomment)
|
# OpenBSD (uncomment)
|
||||||
#FREETYPEINC = $(X11INC)/freetype2
|
#FREETYPEINC = $(X11INC)/freetype2
|
||||||
|
#MANPREFIX = ${PREFIX}/man
|
||||||
|
|
||||||
# includes and libs
|
# includes and libs
|
||||||
INCS = -I$(X11INC) -I$(FREETYPEINC)
|
INCS = -I$(X11INC) -I$(FREETYPEINC)
|
||||||
|
|
|
@ -6,8 +6,6 @@ dmenu \- dynamic menu
|
||||||
.RB [ \-bfiv ]
|
.RB [ \-bfiv ]
|
||||||
.RB [ \-l
|
.RB [ \-l
|
||||||
.IR lines ]
|
.IR lines ]
|
||||||
.RB [ \-h
|
|
||||||
.IR height ]
|
|
||||||
.RB [ \-m
|
.RB [ \-m
|
||||||
.IR monitor ]
|
.IR monitor ]
|
||||||
.RB [ \-p
|
.RB [ \-p
|
||||||
|
@ -52,9 +50,6 @@ dmenu matches menu items case insensitively.
|
||||||
.BI \-l " lines"
|
.BI \-l " lines"
|
||||||
dmenu lists items vertically, with the given number of lines.
|
dmenu lists items vertically, with the given number of lines.
|
||||||
.TP
|
.TP
|
||||||
.BI \-h " height"
|
|
||||||
dmenu uses a menu line of at least 'height' pixels tall, but no less than 8.
|
|
||||||
.TP
|
|
||||||
.BI \-m " monitor"
|
.BI \-m " monitor"
|
||||||
dmenu is displayed on the monitor number supplied. Monitor numbers are starting
|
dmenu is displayed on the monitor number supplied. Monitor numbers are starting
|
||||||
from 0.
|
from 0.
|
||||||
|
|
187
dmenu/dmenu.c
187
dmenu/dmenu.c
|
@ -15,7 +15,6 @@
|
||||||
#include <X11/extensions/Xinerama.h>
|
#include <X11/extensions/Xinerama.h>
|
||||||
#endif
|
#endif
|
||||||
#include <X11/Xft/Xft.h>
|
#include <X11/Xft/Xft.h>
|
||||||
#include <X11/Xresource.h>
|
|
||||||
|
|
||||||
#include "drw.h"
|
#include "drw.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -54,15 +53,18 @@ static XIC xic;
|
||||||
static Drw *drw;
|
static Drw *drw;
|
||||||
static Clr *scheme[SchemeLast];
|
static Clr *scheme[SchemeLast];
|
||||||
|
|
||||||
/* Temporary arrays to allow overriding xresources values */
|
|
||||||
static char *colortemp[4];
|
|
||||||
static char *tempfonts;
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
|
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
|
||||||
static char *(*fstrstr)(const char *, const char *) = strstr;
|
static char *(*fstrstr)(const char *, const char *) = strstr;
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
textw_clamp(const char *str, unsigned int n)
|
||||||
|
{
|
||||||
|
unsigned int w = drw_fontset_getwidth_clamp(drw, str, n) + lrpad;
|
||||||
|
return MIN(w, n);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
appenditem(struct item *item, struct item **list, struct item **last)
|
appenditem(struct item *item, struct item **list, struct item **last)
|
||||||
{
|
{
|
||||||
|
@ -87,10 +89,10 @@ calcoffsets(void)
|
||||||
n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">"));
|
n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">"));
|
||||||
/* calculate which items will begin the next page and previous page */
|
/* calculate which items will begin the next page and previous page */
|
||||||
for (i = 0, next = curr; next; next = next->right)
|
for (i = 0, next = curr; next; next = next->right)
|
||||||
if ((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n)
|
if ((i += (lines > 0) ? bh : textw_clamp(next->text, n)) > n)
|
||||||
break;
|
break;
|
||||||
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
|
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
|
||||||
if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n)
|
if ((i += (lines > 0) ? bh : textw_clamp(prev->left->text, n)) > n)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,19 +104,29 @@ cleanup(void)
|
||||||
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
||||||
for (i = 0; i < SchemeLast; i++)
|
for (i = 0; i < SchemeLast; i++)
|
||||||
free(scheme[i]);
|
free(scheme[i]);
|
||||||
|
for (i = 0; items && items[i].text; ++i)
|
||||||
|
free(items[i].text);
|
||||||
|
free(items);
|
||||||
drw_free(drw);
|
drw_free(drw);
|
||||||
XSync(dpy, False);
|
XSync(dpy, False);
|
||||||
XCloseDisplay(dpy);
|
XCloseDisplay(dpy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
cistrstr(const char *s, const char *sub)
|
cistrstr(const char *h, const char *n)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t i;
|
||||||
|
|
||||||
for (len = strlen(sub); *s; s++)
|
if (!n[0])
|
||||||
if (!strncasecmp(s, sub, len))
|
return (char *)h;
|
||||||
return (char *)s;
|
|
||||||
|
for (; *h; ++h) {
|
||||||
|
for (i = 0; n[i] && tolower((unsigned char)n[i]) ==
|
||||||
|
tolower((unsigned char)h[i]); ++i)
|
||||||
|
;
|
||||||
|
if (n[i] == '\0')
|
||||||
|
return (char *)h;
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +148,7 @@ drawmenu(void)
|
||||||
{
|
{
|
||||||
unsigned int curpos;
|
unsigned int curpos;
|
||||||
struct item *item;
|
struct item *item;
|
||||||
int x = 0, y = 0, fh = drw->fonts->h, w;
|
int x = 0, y = 0, w;
|
||||||
|
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
drw_setscheme(drw, scheme[SchemeNorm]);
|
||||||
drw_rect(drw, 0, 0, mw, mh, 1, 1);
|
drw_rect(drw, 0, 0, mw, mh, 1, 1);
|
||||||
|
@ -153,7 +165,7 @@ drawmenu(void)
|
||||||
curpos = TEXTW(text) - TEXTW(&text[cursor]);
|
curpos = TEXTW(text) - TEXTW(&text[cursor]);
|
||||||
if ((curpos += lrpad / 2 - 1) < w) {
|
if ((curpos += lrpad / 2 - 1) < w) {
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
drw_setscheme(drw, scheme[SchemeNorm]);
|
||||||
drw_rect(drw, x + curpos, 2 + (bh - fh) / 2, 2, fh - 4, 1, 0);
|
drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lines > 0) {
|
if (lines > 0) {
|
||||||
|
@ -170,7 +182,7 @@ drawmenu(void)
|
||||||
}
|
}
|
||||||
x += w;
|
x += w;
|
||||||
for (item = curr; item != next; item = item->right)
|
for (item = curr; item != next; item = item->right)
|
||||||
x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">")));
|
x = drawitem(item, x, 0, textw_clamp(item->text, mw - x - TEXTW(">")));
|
||||||
if (next) {
|
if (next) {
|
||||||
w = TEXTW(">");
|
w = TEXTW(">");
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
drw_setscheme(drw, scheme[SchemeNorm]);
|
||||||
|
@ -230,7 +242,7 @@ match(void)
|
||||||
/* separate input text into tokens to be matched individually */
|
/* separate input text into tokens to be matched individually */
|
||||||
for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
|
for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
|
||||||
if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
|
if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
|
||||||
die("cannot realloc %u bytes:", tokn * sizeof *tokv);
|
die("cannot realloc %zu bytes:", tokn * sizeof *tokv);
|
||||||
len = tokc ? strlen(tokv[0]) : 0;
|
len = tokc ? strlen(tokv[0]) : 0;
|
||||||
|
|
||||||
matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL;
|
matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL;
|
||||||
|
@ -312,19 +324,19 @@ movewordedge(int dir)
|
||||||
static void
|
static void
|
||||||
keypress(XKeyEvent *ev)
|
keypress(XKeyEvent *ev)
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[64];
|
||||||
int len;
|
int len;
|
||||||
KeySym ksym;
|
KeySym ksym = NoSymbol;
|
||||||
Status status;
|
Status status;
|
||||||
|
|
||||||
len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status);
|
len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status);
|
||||||
switch (status) {
|
switch (status) {
|
||||||
default: /* XLookupNone, XBufferOverflow */
|
default: /* XLookupNone, XBufferOverflow */
|
||||||
return;
|
return;
|
||||||
case XLookupChars:
|
case XLookupChars: /* composed string from input method */
|
||||||
goto insert;
|
goto insert;
|
||||||
case XLookupKeySym:
|
case XLookupKeySym:
|
||||||
case XLookupBoth:
|
case XLookupBoth: /* a KeySym and a string are returned: use keysym */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,9 +377,11 @@ keypress(XKeyEvent *ev)
|
||||||
utf8, utf8, win, CurrentTime);
|
utf8, utf8, win, CurrentTime);
|
||||||
return;
|
return;
|
||||||
case XK_Left:
|
case XK_Left:
|
||||||
|
case XK_KP_Left:
|
||||||
movewordedge(-1);
|
movewordedge(-1);
|
||||||
goto draw;
|
goto draw;
|
||||||
case XK_Right:
|
case XK_Right:
|
||||||
|
case XK_KP_Right:
|
||||||
movewordedge(+1);
|
movewordedge(+1);
|
||||||
goto draw;
|
goto draw;
|
||||||
case XK_Return:
|
case XK_Return:
|
||||||
|
@ -401,10 +415,11 @@ keypress(XKeyEvent *ev)
|
||||||
switch(ksym) {
|
switch(ksym) {
|
||||||
default:
|
default:
|
||||||
insert:
|
insert:
|
||||||
if (!iscntrl(*buf))
|
if (!iscntrl((unsigned char)*buf))
|
||||||
insert(buf, len);
|
insert(buf, len);
|
||||||
break;
|
break;
|
||||||
case XK_Delete:
|
case XK_Delete:
|
||||||
|
case XK_KP_Delete:
|
||||||
if (text[cursor] == '\0')
|
if (text[cursor] == '\0')
|
||||||
return;
|
return;
|
||||||
cursor = nextrune(+1);
|
cursor = nextrune(+1);
|
||||||
|
@ -415,6 +430,7 @@ insert:
|
||||||
insert(NULL, nextrune(-1) - cursor);
|
insert(NULL, nextrune(-1) - cursor);
|
||||||
break;
|
break;
|
||||||
case XK_End:
|
case XK_End:
|
||||||
|
case XK_KP_End:
|
||||||
if (text[cursor] != '\0') {
|
if (text[cursor] != '\0') {
|
||||||
cursor = strlen(text);
|
cursor = strlen(text);
|
||||||
break;
|
break;
|
||||||
|
@ -434,6 +450,7 @@ insert:
|
||||||
cleanup();
|
cleanup();
|
||||||
exit(1);
|
exit(1);
|
||||||
case XK_Home:
|
case XK_Home:
|
||||||
|
case XK_KP_Home:
|
||||||
if (sel == matches) {
|
if (sel == matches) {
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -442,6 +459,7 @@ insert:
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
break;
|
break;
|
||||||
case XK_Left:
|
case XK_Left:
|
||||||
|
case XK_KP_Left:
|
||||||
if (cursor > 0 && (!sel || !sel->left || lines > 0)) {
|
if (cursor > 0 && (!sel || !sel->left || lines > 0)) {
|
||||||
cursor = nextrune(-1);
|
cursor = nextrune(-1);
|
||||||
break;
|
break;
|
||||||
|
@ -450,18 +468,21 @@ insert:
|
||||||
return;
|
return;
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case XK_Up:
|
case XK_Up:
|
||||||
|
case XK_KP_Up:
|
||||||
if (sel && sel->left && (sel = sel->left)->right == curr) {
|
if (sel && sel->left && (sel = sel->left)->right == curr) {
|
||||||
curr = prev;
|
curr = prev;
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XK_Next:
|
case XK_Next:
|
||||||
|
case XK_KP_Next:
|
||||||
if (!next)
|
if (!next)
|
||||||
return;
|
return;
|
||||||
sel = curr = next;
|
sel = curr = next;
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
break;
|
break;
|
||||||
case XK_Prior:
|
case XK_Prior:
|
||||||
|
case XK_KP_Prior:
|
||||||
if (!prev)
|
if (!prev)
|
||||||
return;
|
return;
|
||||||
sel = curr = prev;
|
sel = curr = prev;
|
||||||
|
@ -478,6 +499,7 @@ insert:
|
||||||
sel->out = 1;
|
sel->out = 1;
|
||||||
break;
|
break;
|
||||||
case XK_Right:
|
case XK_Right:
|
||||||
|
case XK_KP_Right:
|
||||||
if (text[cursor] != '\0') {
|
if (text[cursor] != '\0') {
|
||||||
cursor = nextrune(+1);
|
cursor = nextrune(+1);
|
||||||
break;
|
break;
|
||||||
|
@ -486,6 +508,7 @@ insert:
|
||||||
return;
|
return;
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case XK_Down:
|
case XK_Down:
|
||||||
|
case XK_KP_Down:
|
||||||
if (sel && sel->right && (sel = sel->right) == next) {
|
if (sel && sel->right && (sel = sel->right) == next) {
|
||||||
curr = next;
|
curr = next;
|
||||||
calcoffsets();
|
calcoffsets();
|
||||||
|
@ -494,9 +517,9 @@ insert:
|
||||||
case XK_Tab:
|
case XK_Tab:
|
||||||
if (!sel)
|
if (!sel)
|
||||||
return;
|
return;
|
||||||
strncpy(text, sel->text, sizeof text - 1);
|
cursor = strnlen(sel->text, sizeof text - 1);
|
||||||
text[sizeof text - 1] = '\0';
|
memcpy(text, sel->text, cursor);
|
||||||
cursor = strlen(text);
|
text[cursor] = '\0';
|
||||||
match();
|
match();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -526,29 +549,26 @@ paste(void)
|
||||||
static void
|
static void
|
||||||
readstdin(void)
|
readstdin(void)
|
||||||
{
|
{
|
||||||
char buf[sizeof text], *p;
|
char *line = NULL;
|
||||||
size_t i, imax = 0, size = 0;
|
size_t i, junk, itemsiz = 0;
|
||||||
unsigned int tmpmax = 0;
|
ssize_t len;
|
||||||
|
|
||||||
/* read each line from stdin and add it to the item list */
|
/* read each line from stdin and add it to the item list */
|
||||||
for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
|
for (i = 0; (len = getline(&line, &junk, stdin)) != -1; i++) {
|
||||||
if (i + 1 >= size / sizeof *items)
|
if (i + 1 >= itemsiz) {
|
||||||
if (!(items = realloc(items, (size += BUFSIZ))))
|
itemsiz += 256;
|
||||||
die("cannot realloc %u bytes:", size);
|
if (!(items = realloc(items, itemsiz * sizeof(*items))))
|
||||||
if ((p = strchr(buf, '\n')))
|
die("cannot realloc %zu bytes:", itemsiz * sizeof(*items));
|
||||||
*p = '\0';
|
|
||||||
if (!(items[i].text = strdup(buf)))
|
|
||||||
die("cannot strdup %u bytes:", strlen(buf) + 1);
|
|
||||||
items[i].out = 0;
|
|
||||||
drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL);
|
|
||||||
if (tmpmax > inputw) {
|
|
||||||
inputw = tmpmax;
|
|
||||||
imax = i;
|
|
||||||
}
|
}
|
||||||
|
if (line[len - 1] == '\n')
|
||||||
|
line[len - 1] = '\0';
|
||||||
|
items[i].text = line;
|
||||||
|
items[i].out = 0;
|
||||||
|
line = NULL; /* next call of getline() allocates a new line */
|
||||||
}
|
}
|
||||||
|
free(line);
|
||||||
if (items)
|
if (items)
|
||||||
items[i].text = NULL;
|
items[i].text = NULL;
|
||||||
inputw = items ? TEXTW(items[imax].text) : 0;
|
|
||||||
lines = MIN(lines, i);
|
lines = MIN(lines, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,20 +626,14 @@ setup(void)
|
||||||
int a, di, n, area = 0;
|
int a, di, n, area = 0;
|
||||||
#endif
|
#endif
|
||||||
/* init appearance */
|
/* init appearance */
|
||||||
for (j = 0; j < SchemeLast; j++) {
|
for (j = 0; j < SchemeLast; j++)
|
||||||
scheme[j] = drw_scm_create(drw, (const char**)colors[j], 2);
|
scheme[j] = drw_scm_create(drw, colors[j], 2);
|
||||||
}
|
|
||||||
for (j = 0; j < SchemeOut; ++j) {
|
|
||||||
for (i = 0; i < 2; ++i)
|
|
||||||
free(colors[j][i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
clip = XInternAtom(dpy, "CLIPBOARD", False);
|
clip = XInternAtom(dpy, "CLIPBOARD", False);
|
||||||
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
|
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
|
||||||
|
|
||||||
/* calculate menu geometry */
|
/* calculate menu geometry */
|
||||||
bh = drw->fonts->h + 2;
|
bh = drw->fonts->h + 2;
|
||||||
bh = MAX(bh,lineheight); /* make a menu line AT LEAST 'lineheight' tall */
|
|
||||||
lines = MAX(lines, 0);
|
lines = MAX(lines, 0);
|
||||||
mh = (lines + 1) * bh;
|
mh = (lines + 1) * bh;
|
||||||
#ifdef XINERAMA
|
#ifdef XINERAMA
|
||||||
|
@ -645,7 +659,7 @@ setup(void)
|
||||||
/* no focused window is on screen, so use pointer location instead */
|
/* no focused window is on screen, so use pointer location instead */
|
||||||
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
|
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
if (INTERSECT(x, y, 1, 1, info[i]))
|
if (INTERSECT(x, y, 1, 1, info[i]) != 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
x = info[i].x_org;
|
x = info[i].x_org;
|
||||||
|
@ -663,7 +677,7 @@ setup(void)
|
||||||
mw = wa.width;
|
mw = wa.width;
|
||||||
}
|
}
|
||||||
promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
|
promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
|
||||||
inputw = MIN(inputw, mw/3);
|
inputw = mw / 3; /* input width: ~33% of monitor width */
|
||||||
match();
|
match();
|
||||||
|
|
||||||
/* create menu window */
|
/* create menu window */
|
||||||
|
@ -700,44 +714,8 @@ setup(void)
|
||||||
static void
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
fputs("usage: dmenu [-bfiv] [-l lines] [-h height] [-p prompt] [-fn font] [-m monitor]\n"
|
die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
|
||||||
" [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
|
" [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]");
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
readxresources(void) {
|
|
||||||
XrmInitialize();
|
|
||||||
|
|
||||||
char* xrm;
|
|
||||||
if ((xrm = XResourceManagerString(drw->dpy))) {
|
|
||||||
char *type;
|
|
||||||
XrmDatabase xdb = XrmGetStringDatabase(xrm);
|
|
||||||
XrmValue xval;
|
|
||||||
|
|
||||||
if (XrmGetResource(xdb, "dmenu.font", "*", &type, &xval))
|
|
||||||
fonts[0] = strdup(xval.addr);
|
|
||||||
else
|
|
||||||
fonts[0] = strdup(fonts[0]);
|
|
||||||
if (XrmGetResource(xdb, "dmenu.background", "*", &type, &xval))
|
|
||||||
colors[SchemeNorm][ColBg] = strdup(xval.addr);
|
|
||||||
else
|
|
||||||
colors[SchemeNorm][ColBg] = strdup(colors[SchemeNorm][ColBg]);
|
|
||||||
if (XrmGetResource(xdb, "dmenu.foreground", "*", &type, &xval))
|
|
||||||
colors[SchemeNorm][ColFg] = strdup(xval.addr);
|
|
||||||
else
|
|
||||||
colors[SchemeNorm][ColFg] = strdup(colors[SchemeNorm][ColFg]);
|
|
||||||
if (XrmGetResource(xdb, "dmenu.selbackground", "*", &type, &xval))
|
|
||||||
colors[SchemeSel][ColBg] = strdup(xval.addr);
|
|
||||||
else
|
|
||||||
colors[SchemeSel][ColBg] = strdup(colors[SchemeSel][ColBg]);
|
|
||||||
if (XrmGetResource(xdb, "dmenu.selforeground", "*", &type, &xval))
|
|
||||||
colors[SchemeSel][ColFg] = strdup(xval.addr);
|
|
||||||
else
|
|
||||||
colors[SchemeSel][ColFg] = strdup(colors[SchemeSel][ColFg]);
|
|
||||||
|
|
||||||
XrmDestroyDatabase(xdb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -763,24 +741,20 @@ main(int argc, char *argv[])
|
||||||
/* these options take one argument */
|
/* these options take one argument */
|
||||||
else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */
|
else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */
|
||||||
lines = atoi(argv[++i]);
|
lines = atoi(argv[++i]);
|
||||||
else if (!strcmp(argv[i], "-h")) { /* minimum height of one menu line */
|
|
||||||
lineheight = atoi(argv[++i]);
|
|
||||||
lineheight = MAX(lineheight, min_lineheight);
|
|
||||||
}
|
|
||||||
else if (!strcmp(argv[i], "-m"))
|
else if (!strcmp(argv[i], "-m"))
|
||||||
mon = atoi(argv[++i]);
|
mon = atoi(argv[++i]);
|
||||||
else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */
|
else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */
|
||||||
prompt = argv[++i];
|
prompt = argv[++i];
|
||||||
else if (!strcmp(argv[i], "-fn")) /* font or font set */
|
else if (!strcmp(argv[i], "-fn")) /* font or font set */
|
||||||
tempfonts = argv[++i];
|
fonts[0] = argv[++i];
|
||||||
else if (!strcmp(argv[i], "-nb")) /* normal background color */
|
else if (!strcmp(argv[i], "-nb")) /* normal background color */
|
||||||
colortemp[0] = argv[++i];
|
colors[SchemeNorm][ColBg] = argv[++i];
|
||||||
else if (!strcmp(argv[i], "-nf")) /* normal foreground color */
|
else if (!strcmp(argv[i], "-nf")) /* normal foreground color */
|
||||||
colortemp[1] = argv[++i];
|
colors[SchemeNorm][ColFg] = argv[++i];
|
||||||
else if (!strcmp(argv[i], "-sb")) /* selected background color */
|
else if (!strcmp(argv[i], "-sb")) /* selected background color */
|
||||||
colortemp[2] = argv[++i];
|
colors[SchemeSel][ColBg] = argv[++i];
|
||||||
else if (!strcmp(argv[i], "-sf")) /* selected foreground color */
|
else if (!strcmp(argv[i], "-sf")) /* selected foreground color */
|
||||||
colortemp[3] = argv[++i];
|
colors[SchemeSel][ColFg] = argv[++i];
|
||||||
else if (!strcmp(argv[i], "-w")) /* embedding window id */
|
else if (!strcmp(argv[i], "-w")) /* embedding window id */
|
||||||
embed = argv[++i];
|
embed = argv[++i];
|
||||||
else
|
else
|
||||||
|
@ -798,23 +772,8 @@ main(int argc, char *argv[])
|
||||||
die("could not get embedding window attributes: 0x%lx",
|
die("could not get embedding window attributes: 0x%lx",
|
||||||
parentwin);
|
parentwin);
|
||||||
drw = drw_create(dpy, screen, root, wa.width, wa.height);
|
drw = drw_create(dpy, screen, root, wa.width, wa.height);
|
||||||
readxresources();
|
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
|
||||||
/* Now we check whether to override xresources with commandline parameters */
|
|
||||||
if ( tempfonts )
|
|
||||||
fonts[0] = strdup(tempfonts);
|
|
||||||
if ( colortemp[0])
|
|
||||||
colors[SchemeNorm][ColBg] = strdup(colortemp[0]);
|
|
||||||
if ( colortemp[1])
|
|
||||||
colors[SchemeNorm][ColFg] = strdup(colortemp[1]);
|
|
||||||
if ( colortemp[2])
|
|
||||||
colors[SchemeSel][ColBg] = strdup(colortemp[2]);
|
|
||||||
if ( colortemp[3])
|
|
||||||
colors[SchemeSel][ColFg] = strdup(colortemp[3]);
|
|
||||||
|
|
||||||
if (!drw_fontset_create(drw, (const char**)fonts, LENGTH(fonts)))
|
|
||||||
die("no fonts could be loaded.");
|
die("no fonts could be loaded.");
|
||||||
|
|
||||||
free(fonts[0]);
|
|
||||||
lrpad = drw->fonts->h;
|
lrpad = drw->fonts->h;
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
|
|
102
dmenu/drw.c
102
dmenu/drw.c
|
@ -133,19 +133,6 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
|
||||||
die("no font specified.");
|
die("no font specified.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do not allow using color fonts. This is a workaround for a BadLength
|
|
||||||
* error from Xft with color glyphs. Modelled on the Xterm workaround. See
|
|
||||||
* https://bugzilla.redhat.com/show_bug.cgi?id=1498269
|
|
||||||
* https://lists.suckless.org/dev/1701/30932.html
|
|
||||||
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349
|
|
||||||
* and lots more all over the internet.
|
|
||||||
*/
|
|
||||||
FcBool iscol;
|
|
||||||
if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
|
|
||||||
XftFontClose(drw->dpy, xfont);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
font = ecalloc(1, sizeof(Fnt));
|
font = ecalloc(1, sizeof(Fnt));
|
||||||
font->xfont = xfont;
|
font->xfont = xfont;
|
||||||
font->pattern = pattern;
|
font->pattern = pattern;
|
||||||
|
@ -251,12 +238,10 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
|
||||||
int
|
int
|
||||||
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
|
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
int i, ty, ellipsis_x = 0;
|
||||||
int ty;
|
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
|
||||||
unsigned int ew;
|
|
||||||
XftDraw *d = NULL;
|
XftDraw *d = NULL;
|
||||||
Fnt *usedfont, *curfont, *nextfont;
|
Fnt *usedfont, *curfont, *nextfont;
|
||||||
size_t i, len;
|
|
||||||
int utf8strlen, utf8charlen, render = x || y || w || h;
|
int utf8strlen, utf8charlen, render = x || y || w || h;
|
||||||
long utf8codepoint = 0;
|
long utf8codepoint = 0;
|
||||||
const char *utf8str;
|
const char *utf8str;
|
||||||
|
@ -264,13 +249,17 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
FcPattern *fcpattern;
|
FcPattern *fcpattern;
|
||||||
FcPattern *match;
|
FcPattern *match;
|
||||||
XftResult result;
|
XftResult result;
|
||||||
int charexists = 0;
|
int charexists = 0, overflow = 0;
|
||||||
|
/* keep track of a couple codepoints for which we have no match. */
|
||||||
|
enum { nomatches_len = 64 };
|
||||||
|
static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
|
||||||
|
static unsigned int ellipsis_width = 0;
|
||||||
|
|
||||||
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
|
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!render) {
|
if (!render) {
|
||||||
w = ~w;
|
w = invert ? invert : ~invert;
|
||||||
} else {
|
} else {
|
||||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||||
|
@ -282,8 +271,10 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
}
|
}
|
||||||
|
|
||||||
usedfont = drw->fonts;
|
usedfont = drw->fonts;
|
||||||
|
if (!ellipsis_width && render)
|
||||||
|
ellipsis_width = drw_fontset_getwidth(drw, "...");
|
||||||
while (1) {
|
while (1) {
|
||||||
utf8strlen = 0;
|
ew = ellipsis_len = utf8strlen = 0;
|
||||||
utf8str = text;
|
utf8str = text;
|
||||||
nextfont = NULL;
|
nextfont = NULL;
|
||||||
while (*text) {
|
while (*text) {
|
||||||
|
@ -291,9 +282,27 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
||||||
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
||||||
if (charexists) {
|
if (charexists) {
|
||||||
if (curfont == usedfont) {
|
drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
|
||||||
|
if (ew + ellipsis_width <= w) {
|
||||||
|
/* keep track where the ellipsis still fits */
|
||||||
|
ellipsis_x = x + ew;
|
||||||
|
ellipsis_w = w - ew;
|
||||||
|
ellipsis_len = utf8strlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ew + tmpw > w) {
|
||||||
|
overflow = 1;
|
||||||
|
/* called from drw_fontset_getwidth_clamp():
|
||||||
|
* it wants the width AFTER the overflow
|
||||||
|
*/
|
||||||
|
if (!render)
|
||||||
|
x += tmpw;
|
||||||
|
else
|
||||||
|
utf8strlen = ellipsis_len;
|
||||||
|
} else if (curfont == usedfont) {
|
||||||
utf8strlen += utf8charlen;
|
utf8strlen += utf8charlen;
|
||||||
text += utf8charlen;
|
text += utf8charlen;
|
||||||
|
ew += tmpw;
|
||||||
} else {
|
} else {
|
||||||
nextfont = curfont;
|
nextfont = curfont;
|
||||||
}
|
}
|
||||||
|
@ -301,36 +310,25 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!charexists || nextfont)
|
if (overflow || !charexists || nextfont)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (utf8strlen) {
|
if (utf8strlen) {
|
||||||
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
|
if (render) {
|
||||||
/* shorten text if necessary */
|
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
||||||
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--)
|
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
||||||
drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
|
usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
|
||||||
|
|
||||||
if (len) {
|
|
||||||
memcpy(buf, utf8str, len);
|
|
||||||
buf[len] = '\0';
|
|
||||||
if (len < utf8strlen)
|
|
||||||
for (i = len; i && i > len - 3; buf[--i] = '.')
|
|
||||||
; /* NOP */
|
|
||||||
|
|
||||||
if (render) {
|
|
||||||
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
|
||||||
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
|
||||||
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
|
|
||||||
}
|
|
||||||
x += ew;
|
|
||||||
w -= ew;
|
|
||||||
}
|
}
|
||||||
|
x += ew;
|
||||||
|
w -= ew;
|
||||||
}
|
}
|
||||||
|
if (render && overflow)
|
||||||
|
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
|
||||||
|
|
||||||
if (!*text) {
|
if (!*text || overflow) {
|
||||||
break;
|
break;
|
||||||
} else if (nextfont) {
|
} else if (nextfont) {
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
|
@ -340,6 +338,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
* character must be drawn. */
|
* character must be drawn. */
|
||||||
charexists = 1;
|
charexists = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < nomatches_len; ++i) {
|
||||||
|
/* avoid calling XftFontMatch if we know we won't find a match */
|
||||||
|
if (utf8codepoint == nomatches.codepoint[i])
|
||||||
|
goto no_match;
|
||||||
|
}
|
||||||
|
|
||||||
fccharset = FcCharSetCreate();
|
fccharset = FcCharSetCreate();
|
||||||
FcCharSetAddChar(fccharset, utf8codepoint);
|
FcCharSetAddChar(fccharset, utf8codepoint);
|
||||||
|
|
||||||
|
@ -351,7 +355,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
||||||
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
||||||
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
||||||
FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
|
|
||||||
|
|
||||||
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
||||||
FcDefaultSubstitute(fcpattern);
|
FcDefaultSubstitute(fcpattern);
|
||||||
|
@ -368,6 +371,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
curfont->next = usedfont;
|
curfont->next = usedfont;
|
||||||
} else {
|
} else {
|
||||||
xfont_free(usedfont);
|
xfont_free(usedfont);
|
||||||
|
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
|
||||||
|
no_match:
|
||||||
usedfont = drw->fonts;
|
usedfont = drw->fonts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,6 +402,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)
|
||||||
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
|
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
|
||||||
|
{
|
||||||
|
unsigned int tmp = 0;
|
||||||
|
if (drw && drw->fonts && text && n)
|
||||||
|
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
|
||||||
|
return MIN(n, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
|
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,7 @@ void drw_free(Drw *drw);
|
||||||
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
||||||
void drw_fontset_free(Fnt* set);
|
void drw_fontset_free(Fnt* set);
|
||||||
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
|
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
|
||||||
|
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
|
||||||
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
|
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
|
||||||
|
|
||||||
/* Colorscheme abstraction */
|
/* Colorscheme abstraction */
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
From ba103e38ea4ab07f9a3ee90627714b9bea17c329 Mon Sep 17 00:00:00 2001
|
|
||||||
From: pskry <peter@skrypalle.dk>
|
|
||||||
Date: Sun, 8 Nov 2020 22:04:22 +0100
|
|
||||||
Subject: [PATCH] Add an option which defines the lineheight
|
|
||||||
|
|
||||||
Despite both the panel and dmenu using the same font (a Terminus 12),
|
|
||||||
dmenu is shorter and the panel is visible from under the dmenu bar.
|
|
||||||
The appearance can be even more distracting when using similar colors
|
|
||||||
for background and selections. With the option added by this patch,
|
|
||||||
dmenu can be launched with a '-h 24', thus completely covering the panel.
|
|
||||||
---
|
|
||||||
config.def.h | 3 +++
|
|
||||||
dmenu.1 | 5 +++++
|
|
||||||
dmenu.c | 11 ++++++++---
|
|
||||||
3 files changed, 16 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 1edb647..4394dec 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -15,6 +15,9 @@ static const char *colors[SchemeLast][2] = {
|
|
||||||
};
|
|
||||||
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
|
|
||||||
static unsigned int lines = 0;
|
|
||||||
+/* -h option; minimum height of a menu line */
|
|
||||||
+static unsigned int lineheight = 0;
|
|
||||||
+static unsigned int min_lineheight = 8;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Characters not considered part of a word while deleting words
|
|
||||||
diff --git a/dmenu.1 b/dmenu.1
|
|
||||||
index 323f93c..f2a82b4 100644
|
|
||||||
--- a/dmenu.1
|
|
||||||
+++ b/dmenu.1
|
|
||||||
@@ -6,6 +6,8 @@ dmenu \- dynamic menu
|
|
||||||
.RB [ \-bfiv ]
|
|
||||||
.RB [ \-l
|
|
||||||
.IR lines ]
|
|
||||||
+.RB [ \-h
|
|
||||||
+.IR height ]
|
|
||||||
.RB [ \-m
|
|
||||||
.IR monitor ]
|
|
||||||
.RB [ \-p
|
|
||||||
@@ -50,6 +52,9 @@ dmenu matches menu items case insensitively.
|
|
||||||
.BI \-l " lines"
|
|
||||||
dmenu lists items vertically, with the given number of lines.
|
|
||||||
.TP
|
|
||||||
+.BI \-h " height"
|
|
||||||
+dmenu uses a menu line of at least 'height' pixels tall, but no less than 8.
|
|
||||||
+.TP
|
|
||||||
.BI \-m " monitor"
|
|
||||||
dmenu is displayed on the monitor number supplied. Monitor numbers are starting
|
|
||||||
from 0.
|
|
||||||
diff --git a/dmenu.c b/dmenu.c
|
|
||||||
index 65f25ce..f2a4047 100644
|
|
||||||
--- a/dmenu.c
|
|
||||||
+++ b/dmenu.c
|
|
||||||
@@ -131,7 +131,7 @@ drawmenu(void)
|
|
||||||
{
|
|
||||||
unsigned int curpos;
|
|
||||||
struct item *item;
|
|
||||||
- int x = 0, y = 0, w;
|
|
||||||
+ int x = 0, y = 0, fh = drw->fonts->h, w;
|
|
||||||
|
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
drw_rect(drw, 0, 0, mw, mh, 1, 1);
|
|
||||||
@@ -148,7 +148,7 @@ drawmenu(void)
|
|
||||||
curpos = TEXTW(text) - TEXTW(&text[cursor]);
|
|
||||||
if ((curpos += lrpad / 2 - 1) < w) {
|
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
- drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
|
|
||||||
+ drw_rect(drw, x + curpos, 2 + (bh - fh) / 2, 2, fh - 4, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lines > 0) {
|
|
||||||
@@ -609,6 +609,7 @@ setup(void)
|
|
||||||
|
|
||||||
/* calculate menu geometry */
|
|
||||||
bh = drw->fonts->h + 2;
|
|
||||||
+ bh = MAX(bh,lineheight); /* make a menu line AT LEAST 'lineheight' tall */
|
|
||||||
lines = MAX(lines, 0);
|
|
||||||
mh = (lines + 1) * bh;
|
|
||||||
#ifdef XINERAMA
|
|
||||||
@@ -689,7 +690,7 @@ setup(void)
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
- fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
|
|
||||||
+ fputs("usage: dmenu [-bfiv] [-l lines] [-h height] [-p prompt] [-fn font] [-m monitor]\n"
|
|
||||||
" [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
@@ -717,6 +718,10 @@ main(int argc, char *argv[])
|
|
||||||
/* these options take one argument */
|
|
||||||
else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */
|
|
||||||
lines = atoi(argv[++i]);
|
|
||||||
+ else if (!strcmp(argv[i], "-h")) { /* minimum height of one menu line */
|
|
||||||
+ lineheight = atoi(argv[++i]);
|
|
||||||
+ lineheight = MAX(lineheight, min_lineheight);
|
|
||||||
+ }
|
|
||||||
else if (!strcmp(argv[i], "-m"))
|
|
||||||
mon = atoi(argv[++i]);
|
|
||||||
else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */
|
|
||||||
--
|
|
||||||
2.29.2
|
|
||||||
|
|
|
@ -1,126 +0,0 @@
|
||||||
diff '--color=auto' -up ../dmenu-4.9/dmenu.c ./dmenu.c
|
|
||||||
--- ../dmenu-4.9/dmenu.c 2019-02-02 13:55:02.000000000 +0100
|
|
||||||
+++ ./dmenu.c 2020-05-24 00:27:58.038586112 +0200
|
|
||||||
@@ -15,6 +15,7 @@
|
|
||||||
#include <X11/extensions/Xinerama.h>
|
|
||||||
#endif
|
|
||||||
#include <X11/Xft/Xft.h>
|
|
||||||
+#include <X11/Xresource.h>
|
|
||||||
|
|
||||||
#include "drw.h"
|
|
||||||
#include "util.h"
|
|
||||||
@@ -53,6 +54,10 @@ static XIC xic;
|
|
||||||
static Drw *drw;
|
|
||||||
static Clr *scheme[SchemeLast];
|
|
||||||
|
|
||||||
+/* Temporary arrays to allow overriding xresources values */
|
|
||||||
+static char *colortemp[4];
|
|
||||||
+static char *tempfonts;
|
|
||||||
+
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
|
|
||||||
@@ -596,8 +601,13 @@ setup(void)
|
|
||||||
int a, di, n, area = 0;
|
|
||||||
#endif
|
|
||||||
/* init appearance */
|
|
||||||
- for (j = 0; j < SchemeLast; j++)
|
|
||||||
- scheme[j] = drw_scm_create(drw, colors[j], 2);
|
|
||||||
+ for (j = 0; j < SchemeLast; j++) {
|
|
||||||
+ scheme[j] = drw_scm_create(drw, (const char**)colors[j], 2);
|
|
||||||
+ }
|
|
||||||
+ for (j = 0; j < SchemeOut; ++j) {
|
|
||||||
+ for (i = 0; i < 2; ++i)
|
|
||||||
+ free(colors[j][i]);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
clip = XInternAtom(dpy, "CLIPBOARD", False);
|
|
||||||
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
|
|
||||||
@@ -687,6 +697,41 @@ usage(void)
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+readxresources(void) {
|
|
||||||
+ XrmInitialize();
|
|
||||||
+
|
|
||||||
+ char* xrm;
|
|
||||||
+ if ((xrm = XResourceManagerString(drw->dpy))) {
|
|
||||||
+ char *type;
|
|
||||||
+ XrmDatabase xdb = XrmGetStringDatabase(xrm);
|
|
||||||
+ XrmValue xval;
|
|
||||||
+
|
|
||||||
+ if (XrmGetResource(xdb, "dmenu.font", "*", &type, &xval))
|
|
||||||
+ fonts[0] = strdup(xval.addr);
|
|
||||||
+ else
|
|
||||||
+ fonts[0] = strdup(fonts[0]);
|
|
||||||
+ if (XrmGetResource(xdb, "dmenu.background", "*", &type, &xval))
|
|
||||||
+ colors[SchemeNorm][ColBg] = strdup(xval.addr);
|
|
||||||
+ else
|
|
||||||
+ colors[SchemeNorm][ColBg] = strdup(colors[SchemeNorm][ColBg]);
|
|
||||||
+ if (XrmGetResource(xdb, "dmenu.foreground", "*", &type, &xval))
|
|
||||||
+ colors[SchemeNorm][ColFg] = strdup(xval.addr);
|
|
||||||
+ else
|
|
||||||
+ colors[SchemeNorm][ColFg] = strdup(colors[SchemeNorm][ColFg]);
|
|
||||||
+ if (XrmGetResource(xdb, "dmenu.selbackground", "*", &type, &xval))
|
|
||||||
+ colors[SchemeSel][ColBg] = strdup(xval.addr);
|
|
||||||
+ else
|
|
||||||
+ colors[SchemeSel][ColBg] = strdup(colors[SchemeSel][ColBg]);
|
|
||||||
+ if (XrmGetResource(xdb, "dmenu.selforeground", "*", &type, &xval))
|
|
||||||
+ colors[SchemeSel][ColFg] = strdup(xval.addr);
|
|
||||||
+ else
|
|
||||||
+ colors[SchemeSel][ColFg] = strdup(colors[SchemeSel][ColFg]);
|
|
||||||
+
|
|
||||||
+ XrmDestroyDatabase(xdb);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
@@ -715,15 +760,15 @@ main(int argc, char *argv[])
|
|
||||||
else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */
|
|
||||||
prompt = argv[++i];
|
|
||||||
else if (!strcmp(argv[i], "-fn")) /* font or font set */
|
|
||||||
- fonts[0] = argv[++i];
|
|
||||||
+ tempfonts = argv[++i];
|
|
||||||
else if (!strcmp(argv[i], "-nb")) /* normal background color */
|
|
||||||
- colors[SchemeNorm][ColBg] = argv[++i];
|
|
||||||
+ colortemp[0] = argv[++i];
|
|
||||||
else if (!strcmp(argv[i], "-nf")) /* normal foreground color */
|
|
||||||
- colors[SchemeNorm][ColFg] = argv[++i];
|
|
||||||
+ colortemp[1] = argv[++i];
|
|
||||||
else if (!strcmp(argv[i], "-sb")) /* selected background color */
|
|
||||||
- colors[SchemeSel][ColBg] = argv[++i];
|
|
||||||
+ colortemp[2] = argv[++i];
|
|
||||||
else if (!strcmp(argv[i], "-sf")) /* selected foreground color */
|
|
||||||
- colors[SchemeSel][ColFg] = argv[++i];
|
|
||||||
+ colortemp[3] = argv[++i];
|
|
||||||
else if (!strcmp(argv[i], "-w")) /* embedding window id */
|
|
||||||
embed = argv[++i];
|
|
||||||
else
|
|
||||||
@@ -743,8 +788,23 @@ main(int argc, char *argv[])
|
|
||||||
die("could not get embedding window attributes: 0x%lx",
|
|
||||||
parentwin);
|
|
||||||
drw = drw_create(dpy, screen, root, wa.width, wa.height);
|
|
||||||
- if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
|
|
||||||
+ readxresources();
|
|
||||||
+ /* Now we check whether to override xresources with commandline parameters */
|
|
||||||
+ if ( tempfonts )
|
|
||||||
+ fonts[0] = strdup(tempfonts);
|
|
||||||
+ if ( colortemp[0])
|
|
||||||
+ colors[SchemeNorm][ColBg] = strdup(colortemp[0]);
|
|
||||||
+ if ( colortemp[1])
|
|
||||||
+ colors[SchemeNorm][ColFg] = strdup(colortemp[1]);
|
|
||||||
+ if ( colortemp[2])
|
|
||||||
+ colors[SchemeSel][ColBg] = strdup(colortemp[2]);
|
|
||||||
+ if ( colortemp[3])
|
|
||||||
+ colors[SchemeSel][ColFg] = strdup(colortemp[3]);
|
|
||||||
+
|
|
||||||
+ if (!drw_fontset_create(drw, (const char**)fonts, LENGTH(fonts)))
|
|
||||||
die("no fonts could be loaded.");
|
|
||||||
+
|
|
||||||
+ free(fonts[0]);
|
|
||||||
lrpad = drw->fonts->h;
|
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
|
|
@ -84,7 +84,7 @@ main(int argc, char *argv[])
|
||||||
if (!argc) {
|
if (!argc) {
|
||||||
/* read list from stdin */
|
/* read list from stdin */
|
||||||
while ((n = getline(&line, &linesiz, stdin)) > 0) {
|
while ((n = getline(&line, &linesiz, stdin)) > 0) {
|
||||||
if (n && line[n - 1] == '\n')
|
if (line[n - 1] == '\n')
|
||||||
line[n - 1] = '\0';
|
line[n - 1] = '\0';
|
||||||
test(line, line);
|
test(line, line);
|
||||||
}
|
}
|
||||||
|
|
23
dmenu/util.c
23
dmenu/util.c
|
@ -6,18 +6,9 @@
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
void *
|
|
||||||
ecalloc(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *p;
|
|
||||||
|
|
||||||
if (!(p = calloc(nmemb, size)))
|
|
||||||
die("calloc:");
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
die(const char *fmt, ...) {
|
die(const char *fmt, ...)
|
||||||
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
@ -33,3 +24,13 @@ die(const char *fmt, ...) {
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
ecalloc(size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
if (!(p = calloc(nmemb, size)))
|
||||||
|
die("calloc:");
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ MIT/X Consortium License
|
||||||
© 2015-2016 Quentin Rameau <quinq@fifth.space>
|
© 2015-2016 Quentin Rameau <quinq@fifth.space>
|
||||||
© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com>
|
© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com>
|
||||||
© 2016-2017 Markus Teich <markus.teich@stusta.mhn.de>
|
© 2016-2017 Markus Teich <markus.teich@stusta.mhn.de>
|
||||||
|
© 2020-2022 Chris Down <chris@chrisdown.name>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
|
|
@ -1,36 +1,26 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
/* appearance */
|
/* appearance */
|
||||||
static unsigned int borderpx = 1; /* border pixel of windows */
|
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||||
static unsigned int snap = 32; /* snap pixel */
|
static const unsigned int snap = 32; /* snap pixel */
|
||||||
static int showbar = 1; /* 0 means no bar */
|
static const int showbar = 1; /* 0 means no bar */
|
||||||
static int topbar = 1; /* 0 means bottom bar */
|
static const int topbar = 1; /* 0 means bottom bar */
|
||||||
static const int startwithgaps = 0; /* 1 means gaps are used by default */
|
|
||||||
static const unsigned int gappx = 10; /* default gap between windows in pixels */
|
|
||||||
static const int user_bh = 0; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */
|
|
||||||
static const char *fonts[] = { "monospace:size=10" };
|
static const char *fonts[] = { "monospace:size=10" };
|
||||||
static const char dmenufont[] = "monospace:size=10";
|
static const char dmenufont[] = "monospace:size=10";
|
||||||
static char normbgcolor[] = "#222222";
|
static const char col_gray1[] = "#222222";
|
||||||
static char normbordercolor[] = "#444444";
|
static const char col_gray2[] = "#444444";
|
||||||
static char normfgcolor[] = "#bbbbbb";
|
static const char col_gray3[] = "#bbbbbb";
|
||||||
static char selfgcolor[] = "#eeeeee";
|
static const char col_gray4[] = "#eeeeee";
|
||||||
static char selbordercolor[] = "#005577";
|
static const char col_cyan[] = "#005577";
|
||||||
static char selbgcolor[] = "#005577";
|
static const char *colors[][3] = {
|
||||||
static char *colors[][3] = {
|
/* fg bg border */
|
||||||
/* fg bg border */
|
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
|
||||||
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
|
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
|
||||||
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
|
|
||||||
[SchemeHid] = { col_cyan, col_gray1, col_cyan },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* tagging */
|
/* tagging */
|
||||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
||||||
|
|
||||||
static const unsigned int ulinepad = 5; /* horizontal padding between the underline and tag */
|
|
||||||
static const unsigned int ulinestroke = 2; /* thickness / height of the underline */
|
|
||||||
static const unsigned int ulinevoffset = 0; /* how far above the bottom of the bar the line should appear */
|
|
||||||
static const int ulineall = 0; /* 1 to show underline on all tags, 0 for just the active ones */
|
|
||||||
|
|
||||||
static const Rule rules[] = {
|
static const Rule rules[] = {
|
||||||
/* xprop(1):
|
/* xprop(1):
|
||||||
* WM_CLASS(STRING) = instance, class
|
* WM_CLASS(STRING) = instance, class
|
||||||
|
@ -42,9 +32,10 @@ static const Rule rules[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* layout(s) */
|
/* layout(s) */
|
||||||
static float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
||||||
static int nmaster = 1; /* number of clients in master area */
|
static const int nmaster = 1; /* number of clients in master area */
|
||||||
static int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
||||||
|
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
|
||||||
|
|
||||||
static const Layout layouts[] = {
|
static const Layout layouts[] = {
|
||||||
/* symbol arrange function */
|
/* symbol arrange function */
|
||||||
|
@ -66,37 +57,16 @@ static const Layout layouts[] = {
|
||||||
|
|
||||||
/* commands */
|
/* commands */
|
||||||
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
||||||
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL };
|
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
|
||||||
static const char *termcmd[] = { "st", NULL };
|
static const char *termcmd[] = { "st", NULL };
|
||||||
|
|
||||||
/*
|
static const Key keys[] = {
|
||||||
* Xresources preferences to load at startup
|
|
||||||
*/
|
|
||||||
ResourcePref resources[] = {
|
|
||||||
{ "normbgcolor", STRING, &normbgcolor },
|
|
||||||
{ "normbordercolor", STRING, &normbordercolor },
|
|
||||||
{ "normfgcolor", STRING, &normfgcolor },
|
|
||||||
{ "selbgcolor", STRING, &selbgcolor },
|
|
||||||
{ "selbordercolor", STRING, &selbordercolor },
|
|
||||||
{ "selfgcolor", STRING, &selfgcolor },
|
|
||||||
{ "borderpx", INTEGER, &borderpx },
|
|
||||||
{ "snap", INTEGER, &snap },
|
|
||||||
{ "showbar", INTEGER, &showbar },
|
|
||||||
{ "topbar", INTEGER, &topbar },
|
|
||||||
{ "nmaster", INTEGER, &nmaster },
|
|
||||||
{ "resizehints", INTEGER, &resizehints },
|
|
||||||
{ "mfact", FLOAT, &mfact },
|
|
||||||
};
|
|
||||||
|
|
||||||
static Key keys[] = {
|
|
||||||
/* modifier key function argument */
|
/* modifier key function argument */
|
||||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
|
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
|
||||||
{ MODKEY, XK_b, togglebar, {0} },
|
{ MODKEY, XK_b, togglebar, {0} },
|
||||||
{ MODKEY, XK_j, focusstackvis, {.i = +1 } },
|
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
||||||
{ MODKEY, XK_k, focusstackvis, {.i = -1 } },
|
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
||||||
{ MODKEY|ShiftMask, XK_j, focusstackhid, {.i = +1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_k, focusstackhid, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
||||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||||
|
@ -109,17 +79,12 @@ static Key keys[] = {
|
||||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||||
{ MODKEY, XK_space, setlayout, {0} },
|
{ MODKEY, XK_space, setlayout, {0} },
|
||||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
||||||
{ MODKEY, XK_minus, setgaps, {.i = -5 } },
|
|
||||||
{ MODKEY, XK_equal, setgaps, {.i = +5 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_minus, setgaps, {.i = GAP_RESET } },
|
|
||||||
{ MODKEY|ShiftMask, XK_equal, setgaps, {.i = GAP_TOGGLE} },
|
|
||||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
||||||
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
||||||
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
|
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
|
||||||
{ MODKEY, XK_period, focusmon, {.i = +1 } },
|
{ MODKEY, XK_period, focusmon, {.i = +1 } },
|
||||||
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
|
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
|
||||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
|
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
|
||||||
{ MODKEY, XK_s, show, {0} },
|
|
||||||
TAGKEYS( XK_1, 0)
|
TAGKEYS( XK_1, 0)
|
||||||
TAGKEYS( XK_2, 1)
|
TAGKEYS( XK_2, 1)
|
||||||
TAGKEYS( XK_3, 2)
|
TAGKEYS( XK_3, 2)
|
||||||
|
@ -134,11 +99,10 @@ static Key keys[] = {
|
||||||
|
|
||||||
/* button definitions */
|
/* button definitions */
|
||||||
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
||||||
static Button buttons[] = {
|
static const Button buttons[] = {
|
||||||
/* click event mask button function argument */
|
/* click event mask button function argument */
|
||||||
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
||||||
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
||||||
{ ClkWinTitle, 0, Button1, togglewin, {0} },
|
|
||||||
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
||||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
||||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
||||||
|
|
156
dwm/config.h
156
dwm/config.h
|
@ -1,156 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
|
|
||||||
/* appearance */
|
|
||||||
static unsigned int borderpx = 1; /* border pixel of windows */
|
|
||||||
static unsigned int snap = 32; /* snap pixel */
|
|
||||||
static int showbar = 1; /* 0 means no bar */
|
|
||||||
static int topbar = 1; /* 0 means bottom bar */
|
|
||||||
static const int startwithgaps = 0; /* 1 means gaps are used by default */
|
|
||||||
static const unsigned int gappx = 10; /* default gap between windows in pixels */
|
|
||||||
static const int user_bh = 28; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */
|
|
||||||
static const char *fonts[] = { "JetBrainsMono Nerd Font:size=10:antialias=true:autohint=true" };
|
|
||||||
static const char dmenufont[] = "JetBrainsMono Nerd Font:size=10:antialias=true:autohint=true";
|
|
||||||
static char normbgcolor[] = "#222222";
|
|
||||||
static char normbordercolor[] = "#444444";
|
|
||||||
static char normfgcolor[] = "#bbbbbb";
|
|
||||||
static char selfgcolor[] = "#eeeeee";
|
|
||||||
static char selbordercolor[] = "#005577";
|
|
||||||
static char selbgcolor[] = "#005577";
|
|
||||||
static char *colors[][3] = {
|
|
||||||
/* fg bg border */
|
|
||||||
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
|
|
||||||
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
|
|
||||||
[SchemeHid] = { normfgcolor, normbgcolor, normbordercolor },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* tagging */
|
|
||||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
|
||||||
|
|
||||||
static const unsigned int ulinepad = 5; /* horizontal padding between the underline and tag */
|
|
||||||
static const unsigned int ulinestroke = 0; /* thickness / height of the underline */
|
|
||||||
static const unsigned int ulinevoffset = 0; /* how far above the bottom of the bar the line should appear */
|
|
||||||
static const int ulineall = 0; /* 1 to show underline on all tags, 0 for just the active ones */
|
|
||||||
|
|
||||||
static const Rule rules[] = {
|
|
||||||
/* xprop(1):
|
|
||||||
* WM_CLASS(STRING) = instance, class
|
|
||||||
* WM_NAME(STRING) = title
|
|
||||||
*/
|
|
||||||
/* class instance title tags mask isfloating monitor */
|
|
||||||
{ "Gimp", NULL, NULL, 0, 1, -1 },
|
|
||||||
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* layout(s) */
|
|
||||||
static float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
|
||||||
static int nmaster = 1; /* number of clients in master area */
|
|
||||||
static int resizehints = 0; /* 1 means respect size hints in tiled resizals */
|
|
||||||
|
|
||||||
static const Layout layouts[] = {
|
|
||||||
/* symbol arrange function */
|
|
||||||
{ "[]=", tile }, /* first entry is default */
|
|
||||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
|
||||||
{ "[M]", monocle },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* key definitions */
|
|
||||||
#define MODKEY Mod1Mask
|
|
||||||
#define TAGKEYS(KEY,TAG) \
|
|
||||||
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
|
||||||
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
|
||||||
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
|
|
||||||
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
|
|
||||||
|
|
||||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
|
||||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
|
||||||
|
|
||||||
/* commands */
|
|
||||||
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
|
||||||
static const char *dmenucmd[] = { "dmenu_run", NULL };
|
|
||||||
static const char *termcmd[] = { "st", NULL };
|
|
||||||
static const char *screenshotscript[] = {"/bin/sh", "-c", "~/.scripts/dwmscreenshot", NULL};
|
|
||||||
static const char *calcscript[] = {"/bin/sh", "-c", "~/.scripts/dmenucalc", NULL};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Xresources preferences to load at startup
|
|
||||||
*/
|
|
||||||
ResourcePref resources[] = {
|
|
||||||
{ "normbgcolor", STRING, &normbgcolor },
|
|
||||||
{ "normbordercolor", STRING, &normbordercolor },
|
|
||||||
{ "normfgcolor", STRING, &normfgcolor },
|
|
||||||
{ "selbgcolor", STRING, &selbgcolor },
|
|
||||||
{ "selbordercolor", STRING, &selbordercolor },
|
|
||||||
{ "selfgcolor", STRING, &selfgcolor },
|
|
||||||
{ "borderpx", INTEGER, &borderpx },
|
|
||||||
{ "snap", INTEGER, &snap },
|
|
||||||
{ "showbar", INTEGER, &showbar },
|
|
||||||
{ "topbar", INTEGER, &topbar },
|
|
||||||
{ "nmaster", INTEGER, &nmaster },
|
|
||||||
{ "resizehints", INTEGER, &resizehints },
|
|
||||||
{ "mfact", FLOAT, &mfact },
|
|
||||||
};
|
|
||||||
|
|
||||||
static Key keys[] = {
|
|
||||||
/* modifier key function argument */
|
|
||||||
{ MODKEY|ShiftMask, XK_o, spawn, {.v = calcscript} },
|
|
||||||
{ MODKEY|ShiftMask, XK_p, spawn, {.v = screenshotscript} },
|
|
||||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
|
||||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
|
|
||||||
{ MODKEY, XK_b, togglebar, {0} },
|
|
||||||
{ MODKEY, XK_j, focusstackvis, {.i = +1 } },
|
|
||||||
{ MODKEY, XK_k, focusstackvis, {.i = -1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_j, focusstackhid, {.i = +1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_k, focusstackhid, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
|
||||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
|
||||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
|
||||||
{ MODKEY, XK_Return, zoom, {0} },
|
|
||||||
{ MODKEY, XK_Tab, view, {0} },
|
|
||||||
{ MODKEY, XK_c, killclient, {0} },
|
|
||||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
|
||||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
|
||||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
|
||||||
{ MODKEY, XK_space, setlayout, {0} },
|
|
||||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
|
||||||
{ MODKEY, XK_minus, setgaps, {.i = -5 } },
|
|
||||||
{ MODKEY, XK_equal, setgaps, {.i = +5 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_minus, setgaps, {.i = GAP_RESET } },
|
|
||||||
{ MODKEY|ShiftMask, XK_equal, setgaps, {.i = GAP_TOGGLE} },
|
|
||||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
|
||||||
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_period, focusmon, {.i = +1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
|
|
||||||
{ MODKEY, XK_s, show, {0} },
|
|
||||||
TAGKEYS( XK_1, 0)
|
|
||||||
TAGKEYS( XK_2, 1)
|
|
||||||
TAGKEYS( XK_3, 2)
|
|
||||||
TAGKEYS( XK_4, 3)
|
|
||||||
TAGKEYS( XK_5, 4)
|
|
||||||
TAGKEYS( XK_6, 5)
|
|
||||||
TAGKEYS( XK_7, 6)
|
|
||||||
TAGKEYS( XK_8, 7)
|
|
||||||
TAGKEYS( XK_9, 8)
|
|
||||||
{ MODKEY|ShiftMask, XK_q, quit, {0} },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* button definitions */
|
|
||||||
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
|
||||||
static Button buttons[] = {
|
|
||||||
/* click event mask button function argument */
|
|
||||||
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
|
||||||
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
|
||||||
{ ClkWinTitle, 0, Button1, togglewin, {0} },
|
|
||||||
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
|
||||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
|
||||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
|
||||||
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
|
||||||
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
|
||||||
{ ClkTagBar, 0, Button1, view, {0} },
|
|
||||||
{ ClkTagBar, 0, Button3, toggleview, {0} },
|
|
||||||
{ ClkTagBar, MODKEY, Button1, tag, {0} },
|
|
||||||
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# dwm version
|
# dwm version
|
||||||
VERSION = 6.2
|
VERSION = 6.4
|
||||||
|
|
||||||
# Customize below to fit your system
|
# Customize below to fit your system
|
||||||
|
|
||||||
|
@ -19,13 +19,14 @@ FREETYPELIBS = -lfontconfig -lXft
|
||||||
FREETYPEINC = /usr/include/freetype2
|
FREETYPEINC = /usr/include/freetype2
|
||||||
# OpenBSD (uncomment)
|
# OpenBSD (uncomment)
|
||||||
#FREETYPEINC = ${X11INC}/freetype2
|
#FREETYPEINC = ${X11INC}/freetype2
|
||||||
|
#MANPREFIX = ${PREFIX}/man
|
||||||
|
|
||||||
# includes and libs
|
# includes and libs
|
||||||
INCS = -I${X11INC} -I${FREETYPEINC}
|
INCS = -I${X11INC} -I${FREETYPEINC}
|
||||||
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
|
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
|
||||||
|
|
||||||
# flags
|
# flags
|
||||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
|
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
|
||||||
#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
|
#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
|
||||||
CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
|
CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
|
||||||
LDFLAGS = ${LIBS}
|
LDFLAGS = ${LIBS}
|
||||||
|
|
106
dwm/drw.c
106
dwm/drw.c
|
@ -95,7 +95,7 @@ drw_free(Drw *drw)
|
||||||
{
|
{
|
||||||
XFreePixmap(drw->dpy, drw->drawable);
|
XFreePixmap(drw->dpy, drw->drawable);
|
||||||
XFreeGC(drw->dpy, drw->gc);
|
XFreeGC(drw->dpy, drw->gc);
|
||||||
drw_fontset_free(drw->fonts); // https://git.suckless.org/dwm/commit/f04cac6d6e39cd9e3fc4fae526e3d1e8df5e34b2.html
|
drw_fontset_free(drw->fonts);
|
||||||
free(drw);
|
free(drw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,19 +133,6 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
|
||||||
die("no font specified.");
|
die("no font specified.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do not allow using color fonts. This is a workaround for a BadLength
|
|
||||||
* error from Xft with color glyphs. Modelled on the Xterm workaround. See
|
|
||||||
* https://bugzilla.redhat.com/show_bug.cgi?id=1498269
|
|
||||||
* https://lists.suckless.org/dev/1701/30932.html
|
|
||||||
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349
|
|
||||||
* and lots more all over the internet.
|
|
||||||
*/
|
|
||||||
FcBool iscol;
|
|
||||||
if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
|
|
||||||
XftFontClose(drw->dpy, xfont);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
font = ecalloc(1, sizeof(Fnt));
|
font = ecalloc(1, sizeof(Fnt));
|
||||||
font->xfont = xfont;
|
font->xfont = xfont;
|
||||||
font->pattern = pattern;
|
font->pattern = pattern;
|
||||||
|
@ -208,7 +195,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
||||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
||||||
* returned color scheme when done using it. */
|
* returned color scheme when done using it. */
|
||||||
Clr *
|
Clr *
|
||||||
drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount)
|
drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
Clr *ret;
|
Clr *ret;
|
||||||
|
@ -251,12 +238,10 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
|
||||||
int
|
int
|
||||||
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
|
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
int i, ty, ellipsis_x = 0;
|
||||||
int ty;
|
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
|
||||||
unsigned int ew;
|
|
||||||
XftDraw *d = NULL;
|
XftDraw *d = NULL;
|
||||||
Fnt *usedfont, *curfont, *nextfont;
|
Fnt *usedfont, *curfont, *nextfont;
|
||||||
size_t i, len;
|
|
||||||
int utf8strlen, utf8charlen, render = x || y || w || h;
|
int utf8strlen, utf8charlen, render = x || y || w || h;
|
||||||
long utf8codepoint = 0;
|
long utf8codepoint = 0;
|
||||||
const char *utf8str;
|
const char *utf8str;
|
||||||
|
@ -264,13 +249,17 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
FcPattern *fcpattern;
|
FcPattern *fcpattern;
|
||||||
FcPattern *match;
|
FcPattern *match;
|
||||||
XftResult result;
|
XftResult result;
|
||||||
int charexists = 0;
|
int charexists = 0, overflow = 0;
|
||||||
|
/* keep track of a couple codepoints for which we have no match. */
|
||||||
|
enum { nomatches_len = 64 };
|
||||||
|
static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
|
||||||
|
static unsigned int ellipsis_width = 0;
|
||||||
|
|
||||||
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
|
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!render) {
|
if (!render) {
|
||||||
w = ~w;
|
w = invert ? invert : ~invert;
|
||||||
} else {
|
} else {
|
||||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||||
|
@ -282,8 +271,10 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
}
|
}
|
||||||
|
|
||||||
usedfont = drw->fonts;
|
usedfont = drw->fonts;
|
||||||
|
if (!ellipsis_width && render)
|
||||||
|
ellipsis_width = drw_fontset_getwidth(drw, "...");
|
||||||
while (1) {
|
while (1) {
|
||||||
utf8strlen = 0;
|
ew = ellipsis_len = utf8strlen = 0;
|
||||||
utf8str = text;
|
utf8str = text;
|
||||||
nextfont = NULL;
|
nextfont = NULL;
|
||||||
while (*text) {
|
while (*text) {
|
||||||
|
@ -291,9 +282,27 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
||||||
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
||||||
if (charexists) {
|
if (charexists) {
|
||||||
if (curfont == usedfont) {
|
drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
|
||||||
|
if (ew + ellipsis_width <= w) {
|
||||||
|
/* keep track where the ellipsis still fits */
|
||||||
|
ellipsis_x = x + ew;
|
||||||
|
ellipsis_w = w - ew;
|
||||||
|
ellipsis_len = utf8strlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ew + tmpw > w) {
|
||||||
|
overflow = 1;
|
||||||
|
/* called from drw_fontset_getwidth_clamp():
|
||||||
|
* it wants the width AFTER the overflow
|
||||||
|
*/
|
||||||
|
if (!render)
|
||||||
|
x += tmpw;
|
||||||
|
else
|
||||||
|
utf8strlen = ellipsis_len;
|
||||||
|
} else if (curfont == usedfont) {
|
||||||
utf8strlen += utf8charlen;
|
utf8strlen += utf8charlen;
|
||||||
text += utf8charlen;
|
text += utf8charlen;
|
||||||
|
ew += tmpw;
|
||||||
} else {
|
} else {
|
||||||
nextfont = curfont;
|
nextfont = curfont;
|
||||||
}
|
}
|
||||||
|
@ -301,36 +310,25 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!charexists || nextfont)
|
if (overflow || !charexists || nextfont)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (utf8strlen) {
|
if (utf8strlen) {
|
||||||
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
|
if (render) {
|
||||||
/* shorten text if necessary */
|
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
||||||
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--)
|
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
||||||
drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
|
usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
|
||||||
|
|
||||||
if (len) {
|
|
||||||
memcpy(buf, utf8str, len);
|
|
||||||
buf[len] = '\0';
|
|
||||||
if (len < utf8strlen)
|
|
||||||
for (i = len; i && i > len - 3; buf[--i] = '.')
|
|
||||||
; /* NOP */
|
|
||||||
|
|
||||||
if (render) {
|
|
||||||
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
|
||||||
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
|
||||||
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
|
|
||||||
}
|
|
||||||
x += ew;
|
|
||||||
w -= ew;
|
|
||||||
}
|
}
|
||||||
|
x += ew;
|
||||||
|
w -= ew;
|
||||||
}
|
}
|
||||||
|
if (render && overflow)
|
||||||
|
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
|
||||||
|
|
||||||
if (!*text) {
|
if (!*text || overflow) {
|
||||||
break;
|
break;
|
||||||
} else if (nextfont) {
|
} else if (nextfont) {
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
|
@ -340,6 +338,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
* character must be drawn. */
|
* character must be drawn. */
|
||||||
charexists = 1;
|
charexists = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < nomatches_len; ++i) {
|
||||||
|
/* avoid calling XftFontMatch if we know we won't find a match */
|
||||||
|
if (utf8codepoint == nomatches.codepoint[i])
|
||||||
|
goto no_match;
|
||||||
|
}
|
||||||
|
|
||||||
fccharset = FcCharSetCreate();
|
fccharset = FcCharSetCreate();
|
||||||
FcCharSetAddChar(fccharset, utf8codepoint);
|
FcCharSetAddChar(fccharset, utf8codepoint);
|
||||||
|
|
||||||
|
@ -351,7 +355,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
||||||
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
||||||
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
||||||
FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
|
|
||||||
|
|
||||||
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
||||||
FcDefaultSubstitute(fcpattern);
|
FcDefaultSubstitute(fcpattern);
|
||||||
|
@ -368,6 +371,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||||
curfont->next = usedfont;
|
curfont->next = usedfont;
|
||||||
} else {
|
} else {
|
||||||
xfont_free(usedfont);
|
xfont_free(usedfont);
|
||||||
|
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
|
||||||
|
no_match:
|
||||||
usedfont = drw->fonts;
|
usedfont = drw->fonts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,6 +402,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)
|
||||||
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
|
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
|
||||||
|
{
|
||||||
|
unsigned int tmp = 0;
|
||||||
|
if (drw && drw->fonts && text && n)
|
||||||
|
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
|
||||||
|
return MIN(n, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
|
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,11 +35,12 @@ void drw_free(Drw *drw);
|
||||||
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
||||||
void drw_fontset_free(Fnt* set);
|
void drw_fontset_free(Fnt* set);
|
||||||
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
|
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
|
||||||
|
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
|
||||||
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
|
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
|
||||||
|
|
||||||
/* Colorscheme abstraction */
|
/* Colorscheme abstraction */
|
||||||
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
|
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
|
||||||
Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount);
|
Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
|
||||||
|
|
||||||
/* Cursor abstraction */
|
/* Cursor abstraction */
|
||||||
Cur *drw_cur_create(Drw *drw, int shape);
|
Cur *drw_cur_create(Drw *drw, int shape);
|
||||||
|
|
|
@ -33,7 +33,7 @@ dwm draws a small border around windows to indicate the focus state.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B \-v
|
.B \-v
|
||||||
prints version information to standard output, then exits.
|
prints version information to stderr, then exits.
|
||||||
.SH USAGE
|
.SH USAGE
|
||||||
.SS Status bar
|
.SS Status bar
|
||||||
.TP
|
.TP
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
diff -up dwm/dwm.c dwmmod/dwm.c
|
|
||||||
--- dwm/dwm.c 2020-06-25 00:21:30.383692180 -0300
|
|
||||||
+++ dwmmod/dwm.c 2020-06-25 00:20:35.643692330 -0300
|
|
||||||
@@ -1057,6 +1057,8 @@ manage(Window w, XWindowAttributes *wa)
|
|
||||||
updatewindowtype(c);
|
|
||||||
updatesizehints(c);
|
|
||||||
updatewmhints(c);
|
|
||||||
+ c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2;
|
|
||||||
+ c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2;
|
|
||||||
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
|
||||||
grabbuttons(c, 0);
|
|
||||||
if (!c->isfloating)
|
|
|
@ -1,431 +0,0 @@
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 1c0b587..bb8f3f7 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -16,6 +16,7 @@ static const char *colors[][3] = {
|
|
||||||
/* fg bg border */
|
|
||||||
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
|
|
||||||
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
|
|
||||||
+ [SchemeHid] = { col_cyan, col_gray1, col_cyan },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* tagging */
|
|
||||||
@@ -64,8 +65,10 @@ static Key keys[] = {
|
|
||||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
|
||||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
|
|
||||||
{ MODKEY, XK_b, togglebar, {0} },
|
|
||||||
- { MODKEY, XK_j, focusstack, {.i = +1 } },
|
|
||||||
- { MODKEY, XK_k, focusstack, {.i = -1 } },
|
|
||||||
+ { MODKEY, XK_j, focusstackvis, {.i = +1 } },
|
|
||||||
+ { MODKEY, XK_k, focusstackvis, {.i = -1 } },
|
|
||||||
+ { MODKEY|ShiftMask, XK_j, focusstackhid, {.i = +1 } },
|
|
||||||
+ { MODKEY|ShiftMask, XK_k, focusstackhid, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
|
||||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
|
||||||
@@ -84,6 +87,8 @@ static Key keys[] = {
|
|
||||||
{ MODKEY, XK_period, focusmon, {.i = +1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
|
|
||||||
+ { MODKEY, XK_s, show, {0} },
|
|
||||||
+ { MODKEY, XK_h, hide, {0} },
|
|
||||||
TAGKEYS( XK_1, 0)
|
|
||||||
TAGKEYS( XK_2, 1)
|
|
||||||
TAGKEYS( XK_3, 2)
|
|
||||||
@@ -102,6 +107,7 @@ static Button buttons[] = {
|
|
||||||
/* click event mask button function argument */
|
|
||||||
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
|
||||||
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
|
||||||
+ { ClkWinTitle, 0, Button1, togglewin, {0} },
|
|
||||||
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
|
||||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
|
||||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 4465af1..e780189 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -50,6 +50,7 @@
|
|
||||||
#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
|
|
||||||
* MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
|
|
||||||
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
|
|
||||||
+#define HIDDEN(C) ((getstate(C->win) == IconicState))
|
|
||||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
|
||||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
|
||||||
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
|
|
||||||
@@ -59,7 +60,7 @@
|
|
||||||
|
|
||||||
/* enums */
|
|
||||||
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
|
|
||||||
-enum { SchemeNorm, SchemeSel }; /* color schemes */
|
|
||||||
+enum { SchemeNorm, SchemeSel, SchemeHid }; /* color schemes */
|
|
||||||
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
|
|
||||||
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
|
|
||||||
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
|
|
||||||
@@ -117,6 +118,8 @@ struct Monitor {
|
|
||||||
int nmaster;
|
|
||||||
int num;
|
|
||||||
int by; /* bar geometry */
|
|
||||||
+ int btw; /* width of tasks portion of bar */
|
|
||||||
+ int bt; /* number of tasks */
|
|
||||||
int mx, my, mw, mh; /* screen size */
|
|
||||||
int wx, wy, ww, wh; /* window area */
|
|
||||||
unsigned int seltags;
|
|
||||||
@@ -124,6 +127,7 @@ struct Monitor {
|
|
||||||
unsigned int tagset[2];
|
|
||||||
int showbar;
|
|
||||||
int topbar;
|
|
||||||
+ int hidsel;
|
|
||||||
Client *clients;
|
|
||||||
Client *sel;
|
|
||||||
Client *stack;
|
|
||||||
@@ -168,12 +172,16 @@ static void expose(XEvent *e);
|
|
||||||
static void focus(Client *c);
|
|
||||||
static void focusin(XEvent *e);
|
|
||||||
static void focusmon(const Arg *arg);
|
|
||||||
-static void focusstack(const Arg *arg);
|
|
||||||
+static void focusstackvis(const Arg *arg);
|
|
||||||
+static void focusstackhid(const Arg *arg);
|
|
||||||
+static void focusstack(int inc, int vis);
|
|
||||||
static int getrootptr(int *x, int *y);
|
|
||||||
static long getstate(Window w);
|
|
||||||
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
|
|
||||||
static void grabbuttons(Client *c, int focused);
|
|
||||||
static void grabkeys(void);
|
|
||||||
+static void hide(const Arg *arg);
|
|
||||||
+static void hidewin(Client *c);
|
|
||||||
static void incnmaster(const Arg *arg);
|
|
||||||
static void keypress(XEvent *e);
|
|
||||||
static void killclient(const Arg *arg);
|
|
||||||
@@ -203,6 +211,8 @@ static void setlayout(const Arg *arg);
|
|
||||||
static void setmfact(const Arg *arg);
|
|
||||||
static void setup(void);
|
|
||||||
static void seturgent(Client *c, int urg);
|
|
||||||
+static void show(const Arg *arg);
|
|
||||||
+static void showwin(Client *c);
|
|
||||||
static void showhide(Client *c);
|
|
||||||
static void sigchld(int unused);
|
|
||||||
static void spawn(const Arg *arg);
|
|
||||||
@@ -213,6 +223,7 @@ static void togglebar(const Arg *arg);
|
|
||||||
static void togglefloating(const Arg *arg);
|
|
||||||
static void toggletag(const Arg *arg);
|
|
||||||
static void toggleview(const Arg *arg);
|
|
||||||
+static void togglewin(const Arg *arg);
|
|
||||||
static void unfocus(Client *c, int setfocus);
|
|
||||||
static void unmanage(Client *c, int destroyed);
|
|
||||||
static void unmapnotify(XEvent *e);
|
|
||||||
@@ -439,10 +450,25 @@ buttonpress(XEvent *e)
|
|
||||||
arg.ui = 1 << i;
|
|
||||||
} else if (ev->x < x + blw)
|
|
||||||
click = ClkLtSymbol;
|
|
||||||
- else if (ev->x > selmon->ww - TEXTW(stext))
|
|
||||||
+ /* 2px right padding */
|
|
||||||
+ else if (ev->x > selmon->ww - TEXTW(stext) + lrpad - 2)
|
|
||||||
click = ClkStatusText;
|
|
||||||
- else
|
|
||||||
- click = ClkWinTitle;
|
|
||||||
+ else {
|
|
||||||
+ x += blw;
|
|
||||||
+ c = m->clients;
|
|
||||||
+
|
|
||||||
+ if (c) {
|
|
||||||
+ do {
|
|
||||||
+ if (!ISVISIBLE(c))
|
|
||||||
+ continue;
|
|
||||||
+ else
|
|
||||||
+ x += (1.0 / (double)m->bt) * m->btw;
|
|
||||||
+ } while (ev->x > x && (c = c->next));
|
|
||||||
+
|
|
||||||
+ click = ClkWinTitle;
|
|
||||||
+ arg.v = c;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
} else if ((c = wintoclient(ev->window))) {
|
|
||||||
focus(c);
|
|
||||||
restack(selmon);
|
|
||||||
@@ -452,7 +478,7 @@ buttonpress(XEvent *e)
|
|
||||||
for (i = 0; i < LENGTH(buttons); i++)
|
|
||||||
if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
|
|
||||||
&& CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
|
|
||||||
- buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
|
|
||||||
+ buttons[i].func((click == ClkTagBar || click == ClkWinTitle) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -695,7 +721,7 @@ dirtomon(int dir)
|
|
||||||
void
|
|
||||||
drawbar(Monitor *m)
|
|
||||||
{
|
|
||||||
- int x, w, sw = 0;
|
|
||||||
+ int x, w, sw = 0, n = 0, scm;
|
|
||||||
int boxs = drw->fonts->h / 9;
|
|
||||||
int boxw = drw->fonts->h / 6 + 2;
|
|
||||||
unsigned int i, occ = 0, urg = 0;
|
|
||||||
@@ -709,6 +735,8 @@ drawbar(Monitor *m)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (c = m->clients; c; c = c->next) {
|
|
||||||
+ if (ISVISIBLE(c))
|
|
||||||
+ n++;
|
|
||||||
occ |= c->tags;
|
|
||||||
if (c->isurgent)
|
|
||||||
urg |= c->tags;
|
|
||||||
@@ -729,16 +757,37 @@ drawbar(Monitor *m)
|
|
||||||
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
|
|
||||||
|
|
||||||
if ((w = m->ww - sw - x) > bh) {
|
|
||||||
- if (m->sel) {
|
|
||||||
- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
|
|
||||||
- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
|
|
||||||
- if (m->sel->isfloating)
|
|
||||||
- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
|
|
||||||
+ if (n > 0) {
|
|
||||||
+ int remainder = w % n;
|
|
||||||
+ int tabw = (1.0 / (double)n) * w + 1;
|
|
||||||
+ for (c = m->clients; c; c = c->next) {
|
|
||||||
+ if (!ISVISIBLE(c))
|
|
||||||
+ continue;
|
|
||||||
+ if (m->sel == c)
|
|
||||||
+ scm = SchemeSel;
|
|
||||||
+ else if (HIDDEN(c))
|
|
||||||
+ scm = SchemeHid;
|
|
||||||
+ else
|
|
||||||
+ scm = SchemeNorm;
|
|
||||||
+ drw_setscheme(drw, scheme[scm]);
|
|
||||||
+
|
|
||||||
+ if (remainder >= 0) {
|
|
||||||
+ if (remainder == 0) {
|
|
||||||
+ tabw--;
|
|
||||||
+ }
|
|
||||||
+ remainder--;
|
|
||||||
+ }
|
|
||||||
+ drw_text(drw, x, 0, tabw, bh, lrpad / 2, c->name, 0);
|
|
||||||
+ x += tabw;
|
|
||||||
+ }
|
|
||||||
} else {
|
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
drw_rect(drw, x, 0, w, bh, 1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ m->bt = n;
|
|
||||||
+ m->btw = w;
|
|
||||||
drw_map(drw, m->barwin, 0, 0, m->ww, bh);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -784,9 +833,17 @@ void
|
|
||||||
focus(Client *c)
|
|
||||||
{
|
|
||||||
if (!c || !ISVISIBLE(c))
|
|
||||||
- for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
|
|
||||||
- if (selmon->sel && selmon->sel != c)
|
|
||||||
+ for (c = selmon->stack; c && (!ISVISIBLE(c) || HIDDEN(c)); c = c->snext);
|
|
||||||
+ if (selmon->sel && selmon->sel != c) {
|
|
||||||
unfocus(selmon->sel, 0);
|
|
||||||
+
|
|
||||||
+ if (selmon->hidsel) {
|
|
||||||
+ hidewin(selmon->sel);
|
|
||||||
+ if (c)
|
|
||||||
+ arrange(c->mon);
|
|
||||||
+ selmon->hidsel = 0;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
if (c) {
|
|
||||||
if (c->mon != selmon)
|
|
||||||
selmon = c->mon;
|
|
||||||
@@ -830,28 +887,57 @@ focusmon(const Arg *arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
-focusstack(const Arg *arg)
|
|
||||||
+focusstackvis(const Arg *arg)
|
|
||||||
+{
|
|
||||||
+ focusstack(arg->i, 0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+focusstackhid(const Arg *arg)
|
|
||||||
+{
|
|
||||||
+ focusstack(arg->i, 1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+focusstack(int inc, int hid)
|
|
||||||
{
|
|
||||||
Client *c = NULL, *i;
|
|
||||||
|
|
||||||
- if (!selmon->sel)
|
|
||||||
+ if (!selmon->sel && !hid)
|
|
||||||
return;
|
|
||||||
- if (arg->i > 0) {
|
|
||||||
- for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
|
|
||||||
+ if (!selmon->clients)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (inc > 0) {
|
|
||||||
+ if (selmon->sel)
|
|
||||||
+ for (c = selmon->sel->next;
|
|
||||||
+ c && (!ISVISIBLE(c) || (!hid && HIDDEN(c)));
|
|
||||||
+ c = c->next);
|
|
||||||
if (!c)
|
|
||||||
- for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
|
|
||||||
+ for (c = selmon->clients;
|
|
||||||
+ c && (!ISVISIBLE(c) || (!hid && HIDDEN(c)));
|
|
||||||
+ c = c->next);
|
|
||||||
} else {
|
|
||||||
- for (i = selmon->clients; i != selmon->sel; i = i->next)
|
|
||||||
- if (ISVISIBLE(i))
|
|
||||||
- c = i;
|
|
||||||
+ if (selmon->sel) {
|
|
||||||
+ for (i = selmon->clients; i != selmon->sel; i = i->next)
|
|
||||||
+ if (ISVISIBLE(i) && !(!hid && HIDDEN(i)))
|
|
||||||
+ c = i;
|
|
||||||
+ } else
|
|
||||||
+ c = selmon->clients;
|
|
||||||
if (!c)
|
|
||||||
for (; i; i = i->next)
|
|
||||||
- if (ISVISIBLE(i))
|
|
||||||
+ if (ISVISIBLE(i) && !(!hid && HIDDEN(i)))
|
|
||||||
c = i;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
if (c) {
|
|
||||||
focus(c);
|
|
||||||
restack(selmon);
|
|
||||||
+
|
|
||||||
+ if (HIDDEN(c)) {
|
|
||||||
+ showwin(c);
|
|
||||||
+ c->mon->hidsel = 1;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -963,6 +1049,36 @@ grabkeys(void)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+hide(const Arg *arg)
|
|
||||||
+{
|
|
||||||
+ hidewin(selmon->sel);
|
|
||||||
+ focus(NULL);
|
|
||||||
+ arrange(selmon);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+hidewin(Client *c) {
|
|
||||||
+ if (!c || HIDDEN(c))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ Window w = c->win;
|
|
||||||
+ static XWindowAttributes ra, ca;
|
|
||||||
+
|
|
||||||
+ // more or less taken directly from blackbox's hide() function
|
|
||||||
+ XGrabServer(dpy);
|
|
||||||
+ XGetWindowAttributes(dpy, root, &ra);
|
|
||||||
+ XGetWindowAttributes(dpy, w, &ca);
|
|
||||||
+ // prevent UnmapNotify events
|
|
||||||
+ XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask);
|
|
||||||
+ XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask);
|
|
||||||
+ XUnmapWindow(dpy, w);
|
|
||||||
+ setclientstate(c, IconicState);
|
|
||||||
+ XSelectInput(dpy, root, ra.your_event_mask);
|
|
||||||
+ XSelectInput(dpy, w, ca.your_event_mask);
|
|
||||||
+ XUngrabServer(dpy);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
incnmaster(const Arg *arg)
|
|
||||||
{
|
|
||||||
@@ -1067,12 +1183,14 @@ manage(Window w, XWindowAttributes *wa)
|
|
||||||
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
|
||||||
(unsigned char *) &(c->win), 1);
|
|
||||||
XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
|
|
||||||
- setclientstate(c, NormalState);
|
|
||||||
+ if (!HIDDEN(c))
|
|
||||||
+ setclientstate(c, NormalState);
|
|
||||||
if (c->mon == selmon)
|
|
||||||
unfocus(selmon->sel, 0);
|
|
||||||
c->mon->sel = c;
|
|
||||||
arrange(c->mon);
|
|
||||||
- XMapWindow(dpy, c->win);
|
|
||||||
+ if (!HIDDEN(c))
|
|
||||||
+ XMapWindow(dpy, c->win);
|
|
||||||
focus(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1195,7 +1313,7 @@ movemouse(const Arg *arg)
|
|
||||||
Client *
|
|
||||||
nexttiled(Client *c)
|
|
||||||
{
|
|
||||||
- for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
|
|
||||||
+ for (; c && (c->isfloating || !ISVISIBLE(c) || HIDDEN(c)); c = c->next);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1248,6 +1366,16 @@ propertynotify(XEvent *e)
|
|
||||||
void
|
|
||||||
quit(const Arg *arg)
|
|
||||||
{
|
|
||||||
+ // fix: reloading dwm keeps all the hidden clients hidden
|
|
||||||
+ Monitor *m;
|
|
||||||
+ Client *c;
|
|
||||||
+ for (m = mons; m; m = m->next) {
|
|
||||||
+ if (m) {
|
|
||||||
+ for (c = m->stack; c; c = c->next)
|
|
||||||
+ if (c && HIDDEN(c)) showwin(c);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1610,6 +1738,25 @@ seturgent(Client *c, int urg)
|
|
||||||
XFree(wmh);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+show(const Arg *arg)
|
|
||||||
+{
|
|
||||||
+ if (selmon->hidsel)
|
|
||||||
+ selmon->hidsel = 0;
|
|
||||||
+ showwin(selmon->sel);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+showwin(Client *c)
|
|
||||||
+{
|
|
||||||
+ if (!c || !HIDDEN(c))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ XMapWindow(dpy, c->win);
|
|
||||||
+ setclientstate(c, NormalState);
|
|
||||||
+ arrange(c->mon);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
showhide(Client *c)
|
|
||||||
{
|
|
||||||
@@ -1746,6 +1893,23 @@ toggleview(const Arg *arg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+togglewin(const Arg *arg)
|
|
||||||
+{
|
|
||||||
+ Client *c = (Client*)arg->v;
|
|
||||||
+
|
|
||||||
+ if (c == selmon->sel) {
|
|
||||||
+ hidewin(c);
|
|
||||||
+ focus(NULL);
|
|
||||||
+ arrange(c->mon);
|
|
||||||
+ } else {
|
|
||||||
+ if (HIDDEN(c))
|
|
||||||
+ showwin(c);
|
|
||||||
+ focus(c);
|
|
||||||
+ restack(selmon);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
unfocus(Client *c, int setfocus)
|
|
||||||
{
|
|
|
@ -1,25 +0,0 @@
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 1c0b587..9814500 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -5,6 +5,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
|
|
||||||
static const unsigned int snap = 32; /* snap pixel */
|
|
||||||
static const int showbar = 1; /* 0 means no bar */
|
|
||||||
static const int topbar = 1; /* 0 means bottom bar */
|
|
||||||
+static const int user_bh = 0; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */
|
|
||||||
static const char *fonts[] = { "monospace:size=10" };
|
|
||||||
static const char dmenufont[] = "monospace:size=10";
|
|
||||||
static const char col_gray1[] = "#222222";
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 4465af1..2c27cb3 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -1545,7 +1545,7 @@ setup(void)
|
|
||||||
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
|
|
||||||
die("no fonts could be loaded.");
|
|
||||||
lrpad = drw->fonts->h;
|
|
||||||
- bh = drw->fonts->h + 2;
|
|
||||||
+ bh = user_bh ? user_bh : drw->fonts->h + 2;
|
|
||||||
updategeom();
|
|
||||||
/* init atoms */
|
|
||||||
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
|
|
|
@ -1,190 +0,0 @@
|
||||||
diff -pur dwm.git/config.def.h dwm.mygaps/config.def.h
|
|
||||||
--- dwm.git/config.def.h 2021-02-27 21:17:53.862314811 -0600
|
|
||||||
+++ dwm.mygaps/config.def.h 2021-02-28 00:06:39.066149441 -0600
|
|
||||||
@@ -2,6 +2,8 @@
|
|
||||||
|
|
||||||
/* appearance */
|
|
||||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
|
||||||
+static const int startwithgaps = 0; /* 1 means gaps are used by default */
|
|
||||||
+static const unsigned int gappx = 10; /* default gap between windows in pixels */
|
|
||||||
static const unsigned int snap = 32; /* snap pixel */
|
|
||||||
static const int showbar = 1; /* 0 means no bar */
|
|
||||||
static const int topbar = 1; /* 0 means bottom bar */
|
|
||||||
@@ -84,6 +86,10 @@ static Key keys[] = {
|
|
||||||
{ MODKEY, XK_period, focusmon, {.i = +1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
|
|
||||||
+ { MODKEY, XK_minus, setgaps, {.i = -5 } },
|
|
||||||
+ { MODKEY, XK_equal, setgaps, {.i = +5 } },
|
|
||||||
+ { MODKEY|ShiftMask, XK_minus, setgaps, {.i = GAP_RESET } },
|
|
||||||
+ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = GAP_TOGGLE} },
|
|
||||||
TAGKEYS( XK_1, 0)
|
|
||||||
TAGKEYS( XK_2, 1)
|
|
||||||
TAGKEYS( XK_3, 2)
|
|
||||||
diff -pur dwm.git/dwm.c dwm.mygaps/dwm.c
|
|
||||||
--- dwm.git/dwm.c 2021-02-27 21:17:53.862314811 -0600
|
|
||||||
+++ dwm.mygaps/dwm.c 2021-02-28 00:23:19.232865766 -0600
|
|
||||||
@@ -57,6 +57,9 @@
|
|
||||||
#define TAGMASK ((1 << LENGTH(tags)) - 1)
|
|
||||||
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
|
|
||||||
|
|
||||||
+#define GAP_TOGGLE 100
|
|
||||||
+#define GAP_RESET 0
|
|
||||||
+
|
|
||||||
/* enums */
|
|
||||||
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
|
|
||||||
enum { SchemeNorm, SchemeSel }; /* color schemes */
|
|
||||||
@@ -119,6 +122,8 @@ struct Monitor {
|
|
||||||
int by; /* bar geometry */
|
|
||||||
int mx, my, mw, mh; /* screen size */
|
|
||||||
int wx, wy, ww, wh; /* window area */
|
|
||||||
+ int gappx; /* gaps between windows */
|
|
||||||
+ int drawwithgaps; /* toggle gaps */
|
|
||||||
unsigned int seltags;
|
|
||||||
unsigned int sellt;
|
|
||||||
unsigned int tagset[2];
|
|
||||||
@@ -200,6 +205,7 @@ static void sendmon(Client *c, Monitor *
|
|
||||||
static void setclientstate(Client *c, long state);
|
|
||||||
static void setfocus(Client *c);
|
|
||||||
static void setfullscreen(Client *c, int fullscreen);
|
|
||||||
+static void setgaps(const Arg *arg);
|
|
||||||
static void setlayout(const Arg *arg);
|
|
||||||
static void setmfact(const Arg *arg);
|
|
||||||
static void setup(void);
|
|
||||||
@@ -639,6 +645,8 @@ createmon(void)
|
|
||||||
m->nmaster = nmaster;
|
|
||||||
m->showbar = showbar;
|
|
||||||
m->topbar = topbar;
|
|
||||||
+ m->gappx = gappx;
|
|
||||||
+ m->drawwithgaps = startwithgaps;
|
|
||||||
m->lt[0] = &layouts[0];
|
|
||||||
m->lt[1] = &layouts[1 % LENGTH(layouts)];
|
|
||||||
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
|
|
||||||
@@ -797,6 +805,12 @@ focus(Client *c)
|
|
||||||
attachstack(c);
|
|
||||||
grabbuttons(c, 1);
|
|
||||||
XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
|
|
||||||
+ if (!selmon->drawwithgaps && !c->isfloating) {
|
|
||||||
+ XWindowChanges wc;
|
|
||||||
+ wc.sibling = selmon->barwin;
|
|
||||||
+ wc.stack_mode = Below;
|
|
||||||
+ XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc);
|
|
||||||
+ }
|
|
||||||
setfocus(c);
|
|
||||||
} else {
|
|
||||||
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
|
|
||||||
@@ -1113,7 +1127,10 @@ monocle(Monitor *m)
|
|
||||||
if (n > 0) /* override layout symbol */
|
|
||||||
snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
|
|
||||||
for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
|
|
||||||
- resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
|
|
||||||
+ if (selmon->drawwithgaps)
|
|
||||||
+ resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
|
|
||||||
+ else
|
|
||||||
+ resize(c, m->wx - c->bw, m->wy, m->ww, m->wh, False);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -1283,6 +1300,15 @@ resizeclient(Client *c, int x, int y, in
|
|
||||||
c->oldw = c->w; c->w = wc.width = w;
|
|
||||||
c->oldh = c->h; c->h = wc.height = h;
|
|
||||||
wc.border_width = c->bw;
|
|
||||||
+ if (!selmon->drawwithgaps && /* this is the noborderfloatingfix patch, slightly modified so that it will work if, and only if, gaps are disabled. */
|
|
||||||
+ (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) /* these two first lines are the only ones changed. if you are manually patching and have noborder installed already, just change these lines; or conversely, just remove this section if the noborder patch is not desired ;) */
|
|
||||||
+ || &monocle == c->mon->lt[c->mon->sellt]->arrange))
|
|
||||||
+ && !c->isfullscreen && !c->isfloating
|
|
||||||
+ && NULL != c->mon->lt[c->mon->sellt]->arrange) {
|
|
||||||
+ c->w = wc.width += c->bw * 2;
|
|
||||||
+ c->h = wc.height += c->bw * 2;
|
|
||||||
+ wc.border_width = 0;
|
|
||||||
+ }
|
|
||||||
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
|
|
||||||
configure(c);
|
|
||||||
XSync(dpy, False);
|
|
||||||
@@ -1499,6 +1525,26 @@ setfullscreen(Client *c, int fullscreen)
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
+setgaps(const Arg *arg)
|
|
||||||
+{
|
|
||||||
+ switch(arg->i)
|
|
||||||
+ {
|
|
||||||
+ case GAP_TOGGLE:
|
|
||||||
+ selmon->drawwithgaps = !selmon->drawwithgaps;
|
|
||||||
+ break;
|
|
||||||
+ case GAP_RESET:
|
|
||||||
+ selmon->gappx = gappx;
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ if (selmon->gappx + arg->i < 0)
|
|
||||||
+ selmon->gappx = 0;
|
|
||||||
+ else
|
|
||||||
+ selmon->gappx += arg->i;
|
|
||||||
+ }
|
|
||||||
+ arrange(selmon);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
setlayout(const Arg *arg)
|
|
||||||
{
|
|
||||||
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
|
|
||||||
@@ -1680,23 +1726,42 @@ tile(Monitor *m)
|
|
||||||
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
|
||||||
if (n == 0)
|
|
||||||
return;
|
|
||||||
-
|
|
||||||
- if (n > m->nmaster)
|
|
||||||
- mw = m->nmaster ? m->ww * m->mfact : 0;
|
|
||||||
- else
|
|
||||||
- mw = m->ww;
|
|
||||||
- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
|
||||||
- if (i < m->nmaster) {
|
|
||||||
- h = (m->wh - my) / (MIN(n, m->nmaster) - i);
|
|
||||||
- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
|
|
||||||
- if (my + HEIGHT(c) < m->wh)
|
|
||||||
- my += HEIGHT(c);
|
|
||||||
- } else {
|
|
||||||
- h = (m->wh - ty) / (n - i);
|
|
||||||
- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
|
|
||||||
- if (ty + HEIGHT(c) < m->wh)
|
|
||||||
- ty += HEIGHT(c);
|
|
||||||
- }
|
|
||||||
+ if (m->drawwithgaps) { /* draw with fullgaps logic */
|
|
||||||
+ if (n > m->nmaster)
|
|
||||||
+ mw = m->nmaster ? m->ww * m->mfact : 0;
|
|
||||||
+ else
|
|
||||||
+ mw = m->ww - m->gappx;
|
|
||||||
+ for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
|
||||||
+ if (i < m->nmaster) {
|
|
||||||
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;
|
|
||||||
+ resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0);
|
|
||||||
+ if (my + HEIGHT(c) + m->gappx < m->wh)
|
|
||||||
+ my += HEIGHT(c) + m->gappx;
|
|
||||||
+ } else {
|
|
||||||
+ h = (m->wh - ty) / (n - i) - m->gappx;
|
|
||||||
+ resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0);
|
|
||||||
+ if (ty + HEIGHT(c) + m->gappx < m->wh)
|
|
||||||
+ ty += HEIGHT(c) + m->gappx;
|
|
||||||
+ }
|
|
||||||
+ } else { /* draw with singularborders logic */
|
|
||||||
+ if (n > m->nmaster)
|
|
||||||
+ mw = m->nmaster ? m->ww * m->mfact : 0;
|
|
||||||
+ else
|
|
||||||
+ mw = m->ww;
|
|
||||||
+ for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
|
||||||
+ if (i < m->nmaster) {
|
|
||||||
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i);
|
|
||||||
+ if (n == 1)
|
|
||||||
+ resize(c, m->wx - c->bw, m->wy, m->ww, m->wh, False);
|
|
||||||
+ else
|
|
||||||
+ resize(c, m->wx - c->bw, m->wy + my, mw - c->bw, h - c->bw, False);
|
|
||||||
+ my += HEIGHT(c) - c->bw;
|
|
||||||
+ } else {
|
|
||||||
+ h = (m->wh - ty) / (n - i);
|
|
||||||
+ resize(c, m->wx + mw - c->bw, m->wy + ty, m->ww - mw, h - c->bw, False);
|
|
||||||
+ ty += HEIGHT(c) - c->bw;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
|
@ -1,166 +0,0 @@
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index d27cb67..464c9d6 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -163,6 +163,7 @@ static void detach(Client *c);
|
|
||||||
static Monitor *dirtomon(int dir);
|
|
||||||
static void drawbar(Monitor *m);
|
|
||||||
static void drawbars(void);
|
|
||||||
+static int drawstatusbar(Monitor *m, int bh, char* text);
|
|
||||||
static void enternotify(XEvent *e);
|
|
||||||
static void expose(XEvent *e);
|
|
||||||
static void focus(Client *c);
|
|
||||||
@@ -237,7 +238,7 @@ static void zoom(const Arg *arg);
|
|
||||||
|
|
||||||
/* variables */
|
|
||||||
static const char broken[] = "broken";
|
|
||||||
-static char stext[256];
|
|
||||||
+static char stext[1024];
|
|
||||||
static int screen;
|
|
||||||
static int sw, sh; /* X display screen geometry width, height */
|
|
||||||
static int bh, blw = 0; /* bar geometry */
|
|
||||||
@@ -483,7 +484,7 @@ cleanup(void)
|
|
||||||
cleanupmon(mons);
|
|
||||||
for (i = 0; i < CurLast; i++)
|
|
||||||
drw_cur_free(drw, cursor[i]);
|
|
||||||
- for (i = 0; i < LENGTH(colors); i++)
|
|
||||||
+ for (i = 0; i < LENGTH(colors) + 1; i++)
|
|
||||||
free(scheme[i]);
|
|
||||||
XDestroyWindow(dpy, wmcheckwin);
|
|
||||||
drw_free(drw);
|
|
||||||
@@ -690,6 +691,114 @@ dirtomon(int dir)
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
+int
|
|
||||||
+drawstatusbar(Monitor *m, int bh, char* stext) {
|
|
||||||
+ int ret, i, w, x, len;
|
|
||||||
+ short isCode = 0;
|
|
||||||
+ char *text;
|
|
||||||
+ char *p;
|
|
||||||
+
|
|
||||||
+ len = strlen(stext) + 1 ;
|
|
||||||
+ if (!(text = (char*) malloc(sizeof(char)*len)))
|
|
||||||
+ die("malloc");
|
|
||||||
+ p = text;
|
|
||||||
+ memcpy(text, stext, len);
|
|
||||||
+
|
|
||||||
+ /* compute width of the status text */
|
|
||||||
+ w = 0;
|
|
||||||
+ i = -1;
|
|
||||||
+ while (text[++i]) {
|
|
||||||
+ if (text[i] == '^') {
|
|
||||||
+ if (!isCode) {
|
|
||||||
+ isCode = 1;
|
|
||||||
+ text[i] = '\0';
|
|
||||||
+ w += TEXTW(text) - lrpad;
|
|
||||||
+ text[i] = '^';
|
|
||||||
+ if (text[++i] == 'f')
|
|
||||||
+ w += atoi(text + ++i);
|
|
||||||
+ } else {
|
|
||||||
+ isCode = 0;
|
|
||||||
+ text = text + i + 1;
|
|
||||||
+ i = -1;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ if (!isCode)
|
|
||||||
+ w += TEXTW(text) - lrpad;
|
|
||||||
+ else
|
|
||||||
+ isCode = 0;
|
|
||||||
+ text = p;
|
|
||||||
+
|
|
||||||
+ w += 2; /* 1px padding on both sides */
|
|
||||||
+ ret = x = m->ww - w;
|
|
||||||
+
|
|
||||||
+ drw_setscheme(drw, scheme[LENGTH(colors)]);
|
|
||||||
+ drw->scheme[ColFg] = scheme[SchemeNorm][ColFg];
|
|
||||||
+ drw->scheme[ColBg] = scheme[SchemeNorm][ColBg];
|
|
||||||
+ drw_rect(drw, x, 0, w, bh, 1, 1);
|
|
||||||
+ x++;
|
|
||||||
+
|
|
||||||
+ /* process status text */
|
|
||||||
+ i = -1;
|
|
||||||
+ while (text[++i]) {
|
|
||||||
+ if (text[i] == '^' && !isCode) {
|
|
||||||
+ isCode = 1;
|
|
||||||
+
|
|
||||||
+ text[i] = '\0';
|
|
||||||
+ w = TEXTW(text) - lrpad;
|
|
||||||
+ drw_text(drw, x, 0, w, bh, 0, text, 0);
|
|
||||||
+
|
|
||||||
+ x += w;
|
|
||||||
+
|
|
||||||
+ /* process code */
|
|
||||||
+ while (text[++i] != '^') {
|
|
||||||
+ if (text[i] == 'c') {
|
|
||||||
+ char buf[8];
|
|
||||||
+ memcpy(buf, (char*)text+i+1, 7);
|
|
||||||
+ buf[7] = '\0';
|
|
||||||
+ drw_clr_create(drw, &drw->scheme[ColFg], buf);
|
|
||||||
+ i += 7;
|
|
||||||
+ } else if (text[i] == 'b') {
|
|
||||||
+ char buf[8];
|
|
||||||
+ memcpy(buf, (char*)text+i+1, 7);
|
|
||||||
+ buf[7] = '\0';
|
|
||||||
+ drw_clr_create(drw, &drw->scheme[ColBg], buf);
|
|
||||||
+ i += 7;
|
|
||||||
+ } else if (text[i] == 'd') {
|
|
||||||
+ drw->scheme[ColFg] = scheme[SchemeNorm][ColFg];
|
|
||||||
+ drw->scheme[ColBg] = scheme[SchemeNorm][ColBg];
|
|
||||||
+ } else if (text[i] == 'r') {
|
|
||||||
+ int rx = atoi(text + ++i);
|
|
||||||
+ while (text[++i] != ',');
|
|
||||||
+ int ry = atoi(text + ++i);
|
|
||||||
+ while (text[++i] != ',');
|
|
||||||
+ int rw = atoi(text + ++i);
|
|
||||||
+ while (text[++i] != ',');
|
|
||||||
+ int rh = atoi(text + ++i);
|
|
||||||
+
|
|
||||||
+ drw_rect(drw, rx + x, ry, rw, rh, 1, 0);
|
|
||||||
+ } else if (text[i] == 'f') {
|
|
||||||
+ x += atoi(text + ++i);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ text = text + i + 1;
|
|
||||||
+ i=-1;
|
|
||||||
+ isCode = 0;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!isCode) {
|
|
||||||
+ w = TEXTW(text) - lrpad;
|
|
||||||
+ drw_text(drw, x, 0, w, bh, 0, text, 0);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
+ free(p);
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
drawbar(Monitor *m)
|
|
||||||
{
|
|
||||||
@@ -701,9 +802,7 @@ drawbar(Monitor *m)
|
|
||||||
|
|
||||||
/* draw status first so it can be overdrawn by tags later */
|
|
||||||
if (m == selmon) { /* status is only drawn on selected monitor */
|
|
||||||
- drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
- sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
|
|
||||||
- drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0);
|
|
||||||
+ sw = m->ww - drawstatusbar(m, bh, stext);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (c = m->clients; c; c = c->next) {
|
|
||||||
@@ -1572,7 +1671,8 @@ setup(void)
|
|
||||||
cursor[CurResize] = drw_cur_create(drw, XC_sizing);
|
|
||||||
cursor[CurMove] = drw_cur_create(drw, XC_fleur);
|
|
||||||
/* init appearance */
|
|
||||||
- scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
|
|
||||||
+ scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *));
|
|
||||||
+ scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], 3);
|
|
||||||
for (i = 0; i < LENGTH(colors); i++)
|
|
||||||
scheme[i] = drw_scm_create(drw, colors[i], 3);
|
|
||||||
/* init bars */
|
|
|
@ -1,27 +0,0 @@
|
||||||
diff -pu dwm.git/config.def.h dwm.underlinetags/config.def.h
|
|
||||||
--- dwm.git/config.def.h 2021-02-27 20:04:32.030570909 -0600
|
|
||||||
+++ dwm.underlinetags/config.def.h 2021-03-16 16:42:26.278703624 -0500
|
|
||||||
@@ -21,6 +21,11 @@ static const char *colors[][3] = {
|
|
||||||
/* tagging */
|
|
||||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
|
||||||
|
|
||||||
+static const unsigned int ulinepad = 5; /* horizontal padding between the underline and tag */
|
|
||||||
+static const unsigned int ulinestroke = 2; /* thickness / height of the underline */
|
|
||||||
+static const unsigned int ulinevoffset = 0; /* how far above the bottom of the bar the line should appear */
|
|
||||||
+static const int ulineall = 0; /* 1 to show underline on all tags, 0 for just the active ones */
|
|
||||||
+
|
|
||||||
static const Rule rules[] = {
|
|
||||||
/* xprop(1):
|
|
||||||
* WM_CLASS(STRING) = instance, class
|
|
||||||
diff -pu dwm.git/dwm.c dwm.underlinetags/dwm.c
|
|
||||||
--- dwm.git/dwm.c 2021-02-27 20:04:32.030570909 -0600
|
|
||||||
+++ dwm.underlinetags/dwm.c 2021-03-16 16:41:21.468077151 -0500
|
|
||||||
@@ -719,6 +719,8 @@ drawbar(Monitor *m)
|
|
||||||
w = TEXTW(tags[i]);
|
|
||||||
drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
|
|
||||||
drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
|
|
||||||
+ if (ulineall || m->tagset[m->seltags] & 1 << i) /* if there are conflicts, just move these lines directly underneath both 'drw_setscheme' and 'drw_text' :) */
|
|
||||||
+ drw_rect(drw, x + ulinepad, bh - ulinestroke - ulinevoffset, w - (ulinepad * 2), ulinestroke, 1, 0);
|
|
||||||
if (occ & 1 << i)
|
|
||||||
drw_rect(drw, x + boxs, boxs, boxw, boxw,
|
|
||||||
m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
|
|
|
@ -1,235 +0,0 @@
|
||||||
From 2832bd78a690606a48a7e1d370cd60fd92ee4988 Mon Sep 17 00:00:00 2001
|
|
||||||
From: MLquest8 <miskuzius@gmail.com>
|
|
||||||
Date: Fri, 12 Jun 2020 15:43:31 +0400
|
|
||||||
Subject: [PATCH] handle various setting of various types from Xresources
|
|
||||||
|
|
||||||
---
|
|
||||||
config.def.h | 54 ++++++++++++++++++++++++++-------------
|
|
||||||
drw.c | 2 +-
|
|
||||||
drw.h | 2 +-
|
|
||||||
dwm.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
4 files changed, 111 insertions(+), 19 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 1c0b587..e69f288 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -1,21 +1,22 @@
|
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
|
|
||||||
/* appearance */
|
|
||||||
-static const unsigned int borderpx = 1; /* border pixel of windows */
|
|
||||||
-static const unsigned int snap = 32; /* snap pixel */
|
|
||||||
-static const int showbar = 1; /* 0 means no bar */
|
|
||||||
-static const int topbar = 1; /* 0 means bottom bar */
|
|
||||||
+static unsigned int borderpx = 1; /* border pixel of windows */
|
|
||||||
+static unsigned int snap = 32; /* snap pixel */
|
|
||||||
+static int showbar = 1; /* 0 means no bar */
|
|
||||||
+static int topbar = 1; /* 0 means bottom bar */
|
|
||||||
static const char *fonts[] = { "monospace:size=10" };
|
|
||||||
static const char dmenufont[] = "monospace:size=10";
|
|
||||||
-static const char col_gray1[] = "#222222";
|
|
||||||
-static const char col_gray2[] = "#444444";
|
|
||||||
-static const char col_gray3[] = "#bbbbbb";
|
|
||||||
-static const char col_gray4[] = "#eeeeee";
|
|
||||||
-static const char col_cyan[] = "#005577";
|
|
||||||
-static const char *colors[][3] = {
|
|
||||||
- /* fg bg border */
|
|
||||||
- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
|
|
||||||
- [SchemeSel] = { col_gray4, col_cyan, col_cyan },
|
|
||||||
+static char normbgcolor[] = "#222222";
|
|
||||||
+static char normbordercolor[] = "#444444";
|
|
||||||
+static char normfgcolor[] = "#bbbbbb";
|
|
||||||
+static char selfgcolor[] = "#eeeeee";
|
|
||||||
+static char selbordercolor[] = "#005577";
|
|
||||||
+static char selbgcolor[] = "#005577";
|
|
||||||
+static char *colors[][3] = {
|
|
||||||
+ /* fg bg border */
|
|
||||||
+ [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
|
|
||||||
+ [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* tagging */
|
|
||||||
@@ -32,9 +33,9 @@ static const Rule rules[] = {
|
|
||||||
};
|
|
||||||
|
|
||||||
/* layout(s) */
|
|
||||||
-static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
|
||||||
-static const int nmaster = 1; /* number of clients in master area */
|
|
||||||
-static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
|
||||||
+static float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
|
||||||
+static int nmaster = 1; /* number of clients in master area */
|
|
||||||
+static int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
|
||||||
|
|
||||||
static const Layout layouts[] = {
|
|
||||||
/* symbol arrange function */
|
|
||||||
@@ -56,9 +57,28 @@ static const Layout layouts[] = {
|
|
||||||
|
|
||||||
/* commands */
|
|
||||||
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
|
||||||
-static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
|
|
||||||
+static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL };
|
|
||||||
static const char *termcmd[] = { "st", NULL };
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * Xresources preferences to load at startup
|
|
||||||
+ */
|
|
||||||
+ResourcePref resources[] = {
|
|
||||||
+ { "normbgcolor", STRING, &normbgcolor },
|
|
||||||
+ { "normbordercolor", STRING, &normbordercolor },
|
|
||||||
+ { "normfgcolor", STRING, &normfgcolor },
|
|
||||||
+ { "selbgcolor", STRING, &selbgcolor },
|
|
||||||
+ { "selbordercolor", STRING, &selbordercolor },
|
|
||||||
+ { "selfgcolor", STRING, &selfgcolor },
|
|
||||||
+ { "borderpx", INTEGER, &borderpx },
|
|
||||||
+ { "snap", INTEGER, &snap },
|
|
||||||
+ { "showbar", INTEGER, &showbar },
|
|
||||||
+ { "topbar", INTEGER, &topbar },
|
|
||||||
+ { "nmaster", INTEGER, &nmaster },
|
|
||||||
+ { "resizehints", INTEGER, &resizehints },
|
|
||||||
+ { "mfact", FLOAT, &mfact },
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
static Key keys[] = {
|
|
||||||
/* modifier key function argument */
|
|
||||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
|
||||||
diff --git a/drw.c b/drw.c
|
|
||||||
index 4cdbcbe..8f1059e 100644
|
|
||||||
--- a/drw.c
|
|
||||||
+++ b/drw.c
|
|
||||||
@@ -208,7 +208,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
|
||||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
|
||||||
* returned color scheme when done using it. */
|
|
||||||
Clr *
|
|
||||||
-drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
|
|
||||||
+drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
Clr *ret;
|
|
||||||
diff --git a/drw.h b/drw.h
|
|
||||||
index 4bcd5ad..42b04ce 100644
|
|
||||||
--- a/drw.h
|
|
||||||
+++ b/drw.h
|
|
||||||
@@ -39,7 +39,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in
|
|
||||||
|
|
||||||
/* Colorscheme abstraction */
|
|
||||||
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
|
|
||||||
-Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
|
|
||||||
+Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount);
|
|
||||||
|
|
||||||
/* Cursor abstraction */
|
|
||||||
Cur *drw_cur_create(Drw *drw, int shape);
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 9fd0286..dc0d219 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -36,6 +36,7 @@
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/Xproto.h>
|
|
||||||
#include <X11/Xutil.h>
|
|
||||||
+#include <X11/Xresource.h>
|
|
||||||
#ifdef XINERAMA
|
|
||||||
#include <X11/extensions/Xinerama.h>
|
|
||||||
#endif /* XINERAMA */
|
|
||||||
@@ -141,6 +142,19 @@ typedef struct {
|
|
||||||
int monitor;
|
|
||||||
} Rule;
|
|
||||||
|
|
||||||
+/* Xresources preferences */
|
|
||||||
+enum resource_type {
|
|
||||||
+ STRING = 0,
|
|
||||||
+ INTEGER = 1,
|
|
||||||
+ FLOAT = 2
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+typedef struct {
|
|
||||||
+ char *name;
|
|
||||||
+ enum resource_type type;
|
|
||||||
+ void *dst;
|
|
||||||
+} ResourcePref;
|
|
||||||
+
|
|
||||||
/* function declarations */
|
|
||||||
static void applyrules(Client *c);
|
|
||||||
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
|
|
||||||
@@ -234,6 +248,8 @@ static int xerror(Display *dpy, XErrorEvent *ee);
|
|
||||||
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
|
||||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
|
||||||
static void zoom(const Arg *arg);
|
|
||||||
+static void load_xresources(void);
|
|
||||||
+static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
|
|
||||||
|
|
||||||
/* variables */
|
|
||||||
static const char broken[] = "broken";
|
|
||||||
@@ -2127,6 +2143,60 @@ zoom(const Arg *arg)
|
|
||||||
pop(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
|
|
||||||
+{
|
|
||||||
+ char *sdst = NULL;
|
|
||||||
+ int *idst = NULL;
|
|
||||||
+ float *fdst = NULL;
|
|
||||||
+
|
|
||||||
+ sdst = dst;
|
|
||||||
+ idst = dst;
|
|
||||||
+ fdst = dst;
|
|
||||||
+
|
|
||||||
+ char fullname[256];
|
|
||||||
+ char *type;
|
|
||||||
+ XrmValue ret;
|
|
||||||
+
|
|
||||||
+ snprintf(fullname, sizeof(fullname), "%s.%s", "dwm", name);
|
|
||||||
+ fullname[sizeof(fullname) - 1] = '\0';
|
|
||||||
+
|
|
||||||
+ XrmGetResource(db, fullname, "*", &type, &ret);
|
|
||||||
+ if (!(ret.addr == NULL || strncmp("String", type, 64)))
|
|
||||||
+ {
|
|
||||||
+ switch (rtype) {
|
|
||||||
+ case STRING:
|
|
||||||
+ strcpy(sdst, ret.addr);
|
|
||||||
+ break;
|
|
||||||
+ case INTEGER:
|
|
||||||
+ *idst = strtoul(ret.addr, NULL, 10);
|
|
||||||
+ break;
|
|
||||||
+ case FLOAT:
|
|
||||||
+ *fdst = strtof(ret.addr, NULL);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+load_xresources(void)
|
|
||||||
+{
|
|
||||||
+ Display *display;
|
|
||||||
+ char *resm;
|
|
||||||
+ XrmDatabase db;
|
|
||||||
+ ResourcePref *p;
|
|
||||||
+
|
|
||||||
+ display = XOpenDisplay(NULL);
|
|
||||||
+ resm = XResourceManagerString(display);
|
|
||||||
+ if (!resm)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ db = XrmGetStringDatabase(resm);
|
|
||||||
+ for (p = resources; p < resources + LENGTH(resources); p++)
|
|
||||||
+ resource_load(db, p->name, p->type, p->dst);
|
|
||||||
+ XCloseDisplay(display);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
@@ -2139,6 +2209,8 @@ main(int argc, char *argv[])
|
|
||||||
if (!(dpy = XOpenDisplay(NULL)))
|
|
||||||
die("dwm: cannot open display");
|
|
||||||
checkotherwm();
|
|
||||||
+ XrmInitialize();
|
|
||||||
+ load_xresources();
|
|
||||||
setup();
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
if (pledge("stdio rpath proc exec", NULL) == -1)
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
23
dwm/util.c
23
dwm/util.c
|
@ -6,18 +6,9 @@
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
void *
|
|
||||||
ecalloc(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *p;
|
|
||||||
|
|
||||||
if (!(p = calloc(nmemb, size)))
|
|
||||||
die("calloc:");
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
die(const char *fmt, ...) {
|
die(const char *fmt, ...)
|
||||||
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
@ -33,3 +24,13 @@ die(const char *fmt, ...) {
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
ecalloc(size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
if (!(p = calloc(nmemb, size)))
|
||||||
|
die("calloc:");
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
7
st/FAQ
7
st/FAQ
|
@ -29,8 +29,8 @@ you can manually run `tic -sx st.info`.
|
||||||
|
|
||||||
## I would like to have utmp and/or scroll functionality by default
|
## I would like to have utmp and/or scroll functionality by default
|
||||||
|
|
||||||
You can add the absolute patch of both programs in your config.h
|
You can add the absolute path of both programs in your config.h file. You only
|
||||||
file. You only have to modify the value of utmp and scroll variables.
|
have to modify the value of utmp and scroll variables.
|
||||||
|
|
||||||
|
|
||||||
## Why doesn't the Del key work in some programs?
|
## Why doesn't the Del key work in some programs?
|
||||||
|
@ -248,3 +248,6 @@ fonts:
|
||||||
|
|
||||||
Please don't bother reporting this bug to st, but notify the upstream Xft
|
Please don't bother reporting this bug to st, but notify the upstream Xft
|
||||||
developers about fixing this bug.
|
developers about fixing this bug.
|
||||||
|
|
||||||
|
As of 2022-09-05 this now seems to be finally fixed in libXft 2.3.5:
|
||||||
|
https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
MIT/X Consortium License
|
MIT/X Consortium License
|
||||||
|
|
||||||
© 2014-2020 Hiltjo Posthuma <hiltjo at codemadness dot org>
|
© 2014-2022 Hiltjo Posthuma <hiltjo at codemadness dot org>
|
||||||
© 2018 Devin J. Pohly <djpohly at gmail dot com>
|
© 2018 Devin J. Pohly <djpohly at gmail dot com>
|
||||||
© 2014-2017 Quentin Rameau <quinq at fifth dot space>
|
© 2014-2017 Quentin Rameau <quinq at fifth dot space>
|
||||||
© 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com>
|
© 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
include config.mk
|
include config.mk
|
||||||
|
|
||||||
SRC = st.c x.c hb.c
|
SRC = st.c x.c
|
||||||
OBJ = $(SRC:.c=.o)
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
all: options st
|
all: options st
|
||||||
|
@ -22,8 +22,7 @@ config.h:
|
||||||
$(CC) $(STCFLAGS) -c $<
|
$(CC) $(STCFLAGS) -c $<
|
||||||
|
|
||||||
st.o: config.h st.h win.h
|
st.o: config.h st.h win.h
|
||||||
x.o: arg.h config.h st.h win.h hb.h
|
x.o: arg.h config.h st.h win.h
|
||||||
hb.o: st.h
|
|
||||||
|
|
||||||
$(OBJ): config.h config.mk
|
$(OBJ): config.h config.mk
|
||||||
|
|
||||||
|
|
12
st/README
12
st/README
|
@ -32,15 +32,3 @@ Credits
|
||||||
-------
|
-------
|
||||||
Based on Aurélien APTEL <aurelien dot aptel at gmail dot com> bt source code.
|
Based on Aurélien APTEL <aurelien dot aptel at gmail dot com> bt source code.
|
||||||
|
|
||||||
|
|
||||||
Rice-specific info
|
|
||||||
------------------
|
|
||||||
This is a custom rice.
|
|
||||||
I have modified the config and also added the following patches:
|
|
||||||
- st-blinking_cursor (https://st.suckless.org/patches/blinking_cursor/)
|
|
||||||
- st-clipboard (https://st.suckless.org/patches/clipboard/)
|
|
||||||
- st-nordtheme (https://st.suckless.org/patches/nordtheme/)
|
|
||||||
- st-scrollback (https://st.suckless.org/patches/scrollback/)
|
|
||||||
- st-scrollback-mouse (https://st.suckless.org/patches/scrollback/)
|
|
||||||
- st-delkey (https://st.suckless.org/patches/delkey/)
|
|
||||||
- st-anysize (https://st.suckless.org/patches/anysize/)
|
|
||||||
|
|
130
st/config.def.h
130
st/config.def.h
|
@ -5,8 +5,8 @@
|
||||||
*
|
*
|
||||||
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
|
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
|
||||||
*/
|
*/
|
||||||
static char *font = "JetBrainsMono Nerd Font:size=12:antialias=true:autohint=true";
|
static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
|
||||||
static int borderpx = 4;
|
static int borderpx = 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* What program is execed by st depends of these precedence rules:
|
* What program is execed by st depends of these precedence rules:
|
||||||
|
@ -16,7 +16,7 @@ static int borderpx = 4;
|
||||||
* 4: value of shell in /etc/passwd
|
* 4: value of shell in /etc/passwd
|
||||||
* 5: value of shell in config.h
|
* 5: value of shell in config.h
|
||||||
*/
|
*/
|
||||||
static char *shell = "/bin/bash";
|
static char *shell = "/bin/sh";
|
||||||
char *utmp = NULL;
|
char *utmp = NULL;
|
||||||
/* scroll program: to enable use a string like "scroll" */
|
/* scroll program: to enable use a string like "scroll" */
|
||||||
char *scroll = NULL;
|
char *scroll = NULL;
|
||||||
|
@ -95,46 +95,53 @@ unsigned int tabspaces = 8;
|
||||||
|
|
||||||
/* Terminal colors (16 first used in escape sequence) */
|
/* Terminal colors (16 first used in escape sequence) */
|
||||||
static const char *colorname[] = {
|
static const char *colorname[] = {
|
||||||
"#1C1E26",
|
/* 8 normal colors */
|
||||||
"#232530",
|
"black",
|
||||||
"#2E303E",
|
"red3",
|
||||||
"#6F6F70",
|
"green3",
|
||||||
"#9DA0A2",
|
"yellow3",
|
||||||
"#CBCED0",
|
"blue2",
|
||||||
"#DCDFE4",
|
"magenta3",
|
||||||
"#E3E6EE",
|
"cyan3",
|
||||||
"#E95678",
|
"gray90",
|
||||||
"#FAB795",
|
|
||||||
"#FAC29A",
|
/* 8 bright colors */
|
||||||
"#29D398",
|
"gray50",
|
||||||
"#59E1E3",
|
"red",
|
||||||
"#26BBD9",
|
"green",
|
||||||
"#EE64AC",
|
"yellow",
|
||||||
"#F09383"
|
"#5c5cff",
|
||||||
|
"magenta",
|
||||||
|
"cyan",
|
||||||
|
"white",
|
||||||
|
|
||||||
|
[255] = 0,
|
||||||
|
|
||||||
|
/* more colors can be added after 255 to use with DefaultXX */
|
||||||
|
"#cccccc",
|
||||||
|
"#555555",
|
||||||
|
"gray90", /* default foreground colour */
|
||||||
|
"black", /* default background colour */
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned int defaultfg = 7;
|
|
||||||
unsigned int defaultbg = 0;
|
|
||||||
static unsigned int defaultcs = 13;
|
|
||||||
static unsigned int defaultrcs = 0;
|
|
||||||
|
|
||||||
static const int resizehints = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-SP-q.1D81
|
* Default colors (colorname index)
|
||||||
* Default style of cursor
|
* foreground, background, cursor, reverse cursor
|
||||||
* 0: Blinking block
|
|
||||||
* 1: Blinking block (default)
|
|
||||||
* 2: Steady block ("█")
|
|
||||||
* 3: Blinking underline
|
|
||||||
* 4: Steady underline ("_")
|
|
||||||
* 5: Blinking bar
|
|
||||||
* 6: Steady bar ("|")
|
|
||||||
* 7: Blinking st cursor
|
|
||||||
* 8: Steady st cursor
|
|
||||||
*/
|
*/
|
||||||
static unsigned int cursorstyle = 1;
|
unsigned int defaultfg = 258;
|
||||||
static Rune stcursor = 0x2603; /* snowman (U+2603) */
|
unsigned int defaultbg = 259;
|
||||||
|
unsigned int defaultcs = 256;
|
||||||
|
static unsigned int defaultrcs = 257;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default shape of cursor
|
||||||
|
* 2: Block ("█")
|
||||||
|
* 4: Underline ("_")
|
||||||
|
* 6: Bar ("|")
|
||||||
|
* 7: Snowman ("☃")
|
||||||
|
*/
|
||||||
|
static unsigned int cursorshape = 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default columns and rows numbers
|
* Default columns and rows numbers
|
||||||
|
@ -163,53 +170,12 @@ static unsigned int defaultattr = 11;
|
||||||
*/
|
*/
|
||||||
static uint forcemousemod = ShiftMask;
|
static uint forcemousemod = ShiftMask;
|
||||||
|
|
||||||
/*
|
|
||||||
* Xresources preferences to load at startup
|
|
||||||
*/
|
|
||||||
ResourcePref resources[] = {
|
|
||||||
{ "font", STRING, &font },
|
|
||||||
{ "color0", STRING, &colorname[0] },
|
|
||||||
{ "color1", STRING, &colorname[1] },
|
|
||||||
{ "color2", STRING, &colorname[2] },
|
|
||||||
{ "color3", STRING, &colorname[3] },
|
|
||||||
{ "color4", STRING, &colorname[4] },
|
|
||||||
{ "color5", STRING, &colorname[5] },
|
|
||||||
{ "color6", STRING, &colorname[6] },
|
|
||||||
{ "color7", STRING, &colorname[7] },
|
|
||||||
{ "color8", STRING, &colorname[8] },
|
|
||||||
{ "color9", STRING, &colorname[9] },
|
|
||||||
{ "color10", STRING, &colorname[10] },
|
|
||||||
{ "color11", STRING, &colorname[11] },
|
|
||||||
{ "color12", STRING, &colorname[12] },
|
|
||||||
{ "color13", STRING, &colorname[13] },
|
|
||||||
{ "color14", STRING, &colorname[14] },
|
|
||||||
{ "color15", STRING, &colorname[15] },
|
|
||||||
{ "background", STRING, &colorname[256] },
|
|
||||||
{ "foreground", STRING, &colorname[257] },
|
|
||||||
{ "cursorColor", STRING, &colorname[258] },
|
|
||||||
{ "termname", STRING, &termname },
|
|
||||||
{ "shell", STRING, &shell },
|
|
||||||
{ "minlatency", INTEGER, &minlatency },
|
|
||||||
{ "maxlatency", INTEGER, &maxlatency },
|
|
||||||
{ "blinktimeout", INTEGER, &blinktimeout },
|
|
||||||
{ "bellvolume", INTEGER, &bellvolume },
|
|
||||||
{ "tabspaces", INTEGER, &tabspaces },
|
|
||||||
{ "borderpx", INTEGER, &borderpx },
|
|
||||||
{ "cwscale", FLOAT, &cwscale },
|
|
||||||
{ "chscale", FLOAT, &chscale },
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal mouse shortcuts.
|
* Internal mouse shortcuts.
|
||||||
* Beware that overloading Button1 will disable the selection.
|
* Beware that overloading Button1 will disable the selection.
|
||||||
*/
|
*/
|
||||||
static MouseShortcut mshortcuts[] = {
|
static MouseShortcut mshortcuts[] = {
|
||||||
/* mask button function argument release */
|
/* mask button function argument release */
|
||||||
|
|
||||||
// Scrollback mouse added manually
|
|
||||||
{ ShiftMask, Button4, kscrollup, {.i = 1} },
|
|
||||||
{ ShiftMask, Button5, kscrolldown, {.i = 1} },
|
|
||||||
|
|
||||||
{ XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
|
{ XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
|
||||||
{ ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} },
|
{ ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} },
|
||||||
{ XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
|
{ XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
|
||||||
|
@ -235,8 +201,6 @@ static Shortcut shortcuts[] = {
|
||||||
{ TERMMOD, XK_Y, selpaste, {.i = 0} },
|
{ TERMMOD, XK_Y, selpaste, {.i = 0} },
|
||||||
{ ShiftMask, XK_Insert, selpaste, {.i = 0} },
|
{ ShiftMask, XK_Insert, selpaste, {.i = 0} },
|
||||||
{ TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
|
{ TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
|
||||||
{ ShiftMask, XK_Page_Up, kscrollup, {.i = -1} },
|
|
||||||
{ ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -314,7 +278,7 @@ static Key key[] = {
|
||||||
{ XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0},
|
{ XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0},
|
||||||
{ XK_KP_Delete, ShiftMask, "\033[2K", -1, 0},
|
{ XK_KP_Delete, ShiftMask, "\033[2K", -1, 0},
|
||||||
{ XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0},
|
{ XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0},
|
||||||
{ XK_KP_Delete, XK_ANY_MOD, "\033[3~", -1, 0},
|
{ XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0},
|
||||||
{ XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
|
{ XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
|
||||||
{ XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0},
|
{ XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0},
|
||||||
{ XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0},
|
{ XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0},
|
||||||
|
@ -382,7 +346,7 @@ static Key key[] = {
|
||||||
{ XK_Delete, ControlMask, "\033[3;5~", +1, 0},
|
{ XK_Delete, ControlMask, "\033[3;5~", +1, 0},
|
||||||
{ XK_Delete, ShiftMask, "\033[2K", -1, 0},
|
{ XK_Delete, ShiftMask, "\033[2K", -1, 0},
|
||||||
{ XK_Delete, ShiftMask, "\033[3;2~", +1, 0},
|
{ XK_Delete, ShiftMask, "\033[3;2~", +1, 0},
|
||||||
{ XK_Delete, XK_ANY_MOD, "\033[3~", -1, 0},
|
{ XK_Delete, XK_ANY_MOD, "\033[P", -1, 0},
|
||||||
{ XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
|
{ XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
|
||||||
{ XK_BackSpace, XK_NO_MOD, "\177", 0, 0},
|
{ XK_BackSpace, XK_NO_MOD, "\177", 0, 0},
|
||||||
{ XK_BackSpace, Mod1Mask, "\033\177", 0, 0},
|
{ XK_BackSpace, Mod1Mask, "\033\177", 0, 0},
|
||||||
|
|
510
st/config.h
510
st/config.h
|
@ -1,510 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* appearance
|
|
||||||
*
|
|
||||||
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
|
|
||||||
*/
|
|
||||||
static char *font = "JetBrainsMono Nerd Font:size=12:antialias=true:autohint=true";
|
|
||||||
static int borderpx = 4;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* What program is execed by st depends of these precedence rules:
|
|
||||||
* 1: program passed with -e
|
|
||||||
* 2: scroll and/or utmp
|
|
||||||
* 3: SHELL environment variable
|
|
||||||
* 4: value of shell in /etc/passwd
|
|
||||||
* 5: value of shell in config.h
|
|
||||||
*/
|
|
||||||
static char *shell = "/bin/bash";
|
|
||||||
char *utmp = NULL;
|
|
||||||
/* scroll program: to enable use a string like "scroll" */
|
|
||||||
char *scroll = NULL;
|
|
||||||
char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400";
|
|
||||||
|
|
||||||
/* identification sequence returned in DA and DECID */
|
|
||||||
char *vtiden = "\033[?6c";
|
|
||||||
|
|
||||||
/* Kerning / character bounding-box multipliers */
|
|
||||||
static float cwscale = 1.0;
|
|
||||||
static float chscale = 1.0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* word delimiter string
|
|
||||||
*
|
|
||||||
* More advanced example: L" `'\"()[]{}"
|
|
||||||
*/
|
|
||||||
wchar_t *worddelimiters = L" ";
|
|
||||||
|
|
||||||
/* selection timeouts (in milliseconds) */
|
|
||||||
static unsigned int doubleclicktimeout = 300;
|
|
||||||
static unsigned int tripleclicktimeout = 600;
|
|
||||||
|
|
||||||
/* alt screens */
|
|
||||||
int allowaltscreen = 1;
|
|
||||||
|
|
||||||
/* allow certain non-interactive (insecure) window operations such as:
|
|
||||||
setting the clipboard text */
|
|
||||||
int allowwindowops = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* draw latency range in ms - from new content/keypress/etc until drawing.
|
|
||||||
* within this range, st draws when content stops arriving (idle). mostly it's
|
|
||||||
* 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 maxlatency = 33;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* blinking timeout (set to 0 to disable blinking) for the terminal blinking
|
|
||||||
* attribute.
|
|
||||||
*/
|
|
||||||
static unsigned int blinktimeout = 800;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* thickness of underline and bar cursors
|
|
||||||
*/
|
|
||||||
static unsigned int cursorthickness = 2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* bell volume. It must be a value between -100 and 100. Use 0 for disabling
|
|
||||||
* it
|
|
||||||
*/
|
|
||||||
static int bellvolume = 0;
|
|
||||||
|
|
||||||
/* default TERM value */
|
|
||||||
char *termname = "st-256color";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* spaces per tab
|
|
||||||
*
|
|
||||||
* When you are changing this value, don't forget to adapt the »it« value in
|
|
||||||
* the st.info and appropriately install the st.info in the environment where
|
|
||||||
* you use this st version.
|
|
||||||
*
|
|
||||||
* it#$tabspaces,
|
|
||||||
*
|
|
||||||
* Secondly make sure your kernel is not expanding tabs. When running `stty
|
|
||||||
* -a` »tab0« should appear. You can tell the terminal to not expand tabs by
|
|
||||||
* running following command:
|
|
||||||
*
|
|
||||||
* stty tabs
|
|
||||||
*/
|
|
||||||
unsigned int tabspaces = 8;
|
|
||||||
|
|
||||||
/* Terminal colors (16 first used in escape sequence) */
|
|
||||||
static const char *colorname[] = {
|
|
||||||
"#1C1E26",
|
|
||||||
"#232530",
|
|
||||||
"#2E303E",
|
|
||||||
"#6F6F70",
|
|
||||||
"#9DA0A2",
|
|
||||||
"#CBCED0",
|
|
||||||
"#DCDFE4",
|
|
||||||
"#E3E6EE",
|
|
||||||
"#E95678",
|
|
||||||
"#FAB795",
|
|
||||||
"#FAC29A",
|
|
||||||
"#29D398",
|
|
||||||
"#59E1E3",
|
|
||||||
"#26BBD9",
|
|
||||||
"#EE64AC",
|
|
||||||
"#F09383"
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned int defaultfg = 7;
|
|
||||||
unsigned int defaultbg = 0;
|
|
||||||
static unsigned int defaultcs = 13;
|
|
||||||
static unsigned int defaultrcs = 0;
|
|
||||||
|
|
||||||
static const int resizehints = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-SP-q.1D81
|
|
||||||
* Default style of cursor
|
|
||||||
* 0: Blinking block
|
|
||||||
* 1: Blinking block (default)
|
|
||||||
* 2: Steady block ("█")
|
|
||||||
* 3: Blinking underline
|
|
||||||
* 4: Steady underline ("_")
|
|
||||||
* 5: Blinking bar
|
|
||||||
* 6: Steady bar ("|")
|
|
||||||
* 7: Blinking st cursor
|
|
||||||
* 8: Steady st cursor
|
|
||||||
*/
|
|
||||||
static unsigned int cursorstyle = 1;
|
|
||||||
static Rune stcursor = 0x2603; /* snowman (U+2603) */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Default columns and rows numbers
|
|
||||||
*/
|
|
||||||
|
|
||||||
static unsigned int cols = 80;
|
|
||||||
static unsigned int rows = 24;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Default colour and shape of the mouse cursor
|
|
||||||
*/
|
|
||||||
static unsigned int mouseshape = XC_xterm;
|
|
||||||
static unsigned int mousefg = 7;
|
|
||||||
static unsigned int mousebg = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Color used to display font attributes when fontconfig selected a font which
|
|
||||||
* doesn't match the ones requested.
|
|
||||||
*/
|
|
||||||
static unsigned int defaultattr = 11;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set).
|
|
||||||
* Note that if you want to use ShiftMask with selmasks, set this to an other
|
|
||||||
* modifier, set to 0 to not use it.
|
|
||||||
*/
|
|
||||||
static uint forcemousemod = ShiftMask;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Xresources preferences to load at startup
|
|
||||||
*/
|
|
||||||
ResourcePref resources[] = {
|
|
||||||
{ "font", STRING, &font },
|
|
||||||
{ "color0", STRING, &colorname[0] },
|
|
||||||
{ "color1", STRING, &colorname[1] },
|
|
||||||
{ "color2", STRING, &colorname[2] },
|
|
||||||
{ "color3", STRING, &colorname[3] },
|
|
||||||
{ "color4", STRING, &colorname[4] },
|
|
||||||
{ "color5", STRING, &colorname[5] },
|
|
||||||
{ "color6", STRING, &colorname[6] },
|
|
||||||
{ "color7", STRING, &colorname[7] },
|
|
||||||
{ "color8", STRING, &colorname[8] },
|
|
||||||
{ "color9", STRING, &colorname[9] },
|
|
||||||
{ "color10", STRING, &colorname[10] },
|
|
||||||
{ "color11", STRING, &colorname[11] },
|
|
||||||
{ "color12", STRING, &colorname[12] },
|
|
||||||
{ "color13", STRING, &colorname[13] },
|
|
||||||
{ "color14", STRING, &colorname[14] },
|
|
||||||
{ "color15", STRING, &colorname[15] },
|
|
||||||
{ "background", STRING, &colorname[256] },
|
|
||||||
{ "foreground", STRING, &colorname[257] },
|
|
||||||
{ "cursorColor", STRING, &colorname[258] },
|
|
||||||
{ "termname", STRING, &termname },
|
|
||||||
{ "shell", STRING, &shell },
|
|
||||||
{ "minlatency", INTEGER, &minlatency },
|
|
||||||
{ "maxlatency", INTEGER, &maxlatency },
|
|
||||||
{ "blinktimeout", INTEGER, &blinktimeout },
|
|
||||||
{ "bellvolume", INTEGER, &bellvolume },
|
|
||||||
{ "tabspaces", INTEGER, &tabspaces },
|
|
||||||
{ "borderpx", INTEGER, &borderpx },
|
|
||||||
{ "cwscale", FLOAT, &cwscale },
|
|
||||||
{ "chscale", FLOAT, &chscale },
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Internal mouse shortcuts.
|
|
||||||
* Beware that overloading Button1 will disable the selection.
|
|
||||||
*/
|
|
||||||
static MouseShortcut mshortcuts[] = {
|
|
||||||
/* mask button function argument release */
|
|
||||||
|
|
||||||
// Scrollback mouse added manually
|
|
||||||
{ ShiftMask, Button4, kscrollup, {.i = 1} },
|
|
||||||
{ ShiftMask, Button5, kscrolldown, {.i = 1} },
|
|
||||||
|
|
||||||
{ XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
|
|
||||||
{ ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} },
|
|
||||||
{ XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
|
|
||||||
{ ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} },
|
|
||||||
{ XK_ANY_MOD, Button5, ttysend, {.s = "\005"} },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Internal keyboard shortcuts. */
|
|
||||||
#define MODKEY Mod1Mask
|
|
||||||
#define TERMMOD (ControlMask|ShiftMask)
|
|
||||||
|
|
||||||
static Shortcut shortcuts[] = {
|
|
||||||
/* mask keysym function argument */
|
|
||||||
{ XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} },
|
|
||||||
{ ControlMask, XK_Print, toggleprinter, {.i = 0} },
|
|
||||||
{ ShiftMask, XK_Print, printscreen, {.i = 0} },
|
|
||||||
{ XK_ANY_MOD, XK_Print, printsel, {.i = 0} },
|
|
||||||
{ TERMMOD, XK_Prior, zoom, {.f = +1} },
|
|
||||||
{ TERMMOD, XK_Next, zoom, {.f = -1} },
|
|
||||||
{ TERMMOD, XK_Home, zoomreset, {.f = 0} },
|
|
||||||
{ TERMMOD, XK_C, clipcopy, {.i = 0} },
|
|
||||||
{ TERMMOD, XK_V, clippaste, {.i = 0} },
|
|
||||||
{ TERMMOD, XK_Y, selpaste, {.i = 0} },
|
|
||||||
{ ShiftMask, XK_Insert, selpaste, {.i = 0} },
|
|
||||||
{ TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
|
|
||||||
{ ShiftMask, XK_Page_Up, kscrollup, {.i = -1} },
|
|
||||||
{ ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} },
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Special keys (change & recompile st.info accordingly)
|
|
||||||
*
|
|
||||||
* Mask value:
|
|
||||||
* * Use XK_ANY_MOD to match the key no matter modifiers state
|
|
||||||
* * Use XK_NO_MOD to match the key alone (no modifiers)
|
|
||||||
* appkey value:
|
|
||||||
* * 0: no value
|
|
||||||
* * > 0: keypad application mode enabled
|
|
||||||
* * = 2: term.numlock = 1
|
|
||||||
* * < 0: keypad application mode disabled
|
|
||||||
* appcursor value:
|
|
||||||
* * 0: no value
|
|
||||||
* * > 0: cursor application mode enabled
|
|
||||||
* * < 0: cursor application mode disabled
|
|
||||||
*
|
|
||||||
* Be careful with the order of the definitions because st searches in
|
|
||||||
* this table sequentially, so any XK_ANY_MOD must be in the last
|
|
||||||
* position for a key.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If you want keys other than the X11 function keys (0xFD00 - 0xFFFF)
|
|
||||||
* to be mapped below, add them to this array.
|
|
||||||
*/
|
|
||||||
static KeySym mappedkeys[] = { -1 };
|
|
||||||
|
|
||||||
/*
|
|
||||||
* State bits to ignore when matching key or button events. By default,
|
|
||||||
* numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored.
|
|
||||||
*/
|
|
||||||
static uint ignoremod = Mod2Mask|XK_SWITCH_MOD;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the huge key array which defines all compatibility to the Linux
|
|
||||||
* world. Please decide about changes wisely.
|
|
||||||
*/
|
|
||||||
static Key key[] = {
|
|
||||||
/* keysym mask string appkey appcursor */
|
|
||||||
{ XK_KP_Home, ShiftMask, "\033[2J", 0, -1},
|
|
||||||
{ XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1},
|
|
||||||
{ XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1},
|
|
||||||
{ XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1},
|
|
||||||
{ XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0},
|
|
||||||
{ XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1},
|
|
||||||
{ XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1},
|
|
||||||
{ XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0},
|
|
||||||
{ XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1},
|
|
||||||
{ XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1},
|
|
||||||
{ XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0},
|
|
||||||
{ XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1},
|
|
||||||
{ XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1},
|
|
||||||
{ XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0},
|
|
||||||
{ XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1},
|
|
||||||
{ XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1},
|
|
||||||
{ XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0},
|
|
||||||
{ XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0},
|
|
||||||
{ XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0},
|
|
||||||
{ XK_KP_End, ControlMask, "\033[J", -1, 0},
|
|
||||||
{ XK_KP_End, ControlMask, "\033[1;5F", +1, 0},
|
|
||||||
{ XK_KP_End, ShiftMask, "\033[K", -1, 0},
|
|
||||||
{ XK_KP_End, ShiftMask, "\033[1;2F", +1, 0},
|
|
||||||
{ XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0},
|
|
||||||
{ XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0},
|
|
||||||
{ XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0},
|
|
||||||
{ XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0},
|
|
||||||
{ XK_KP_Insert, ShiftMask, "\033[4l", -1, 0},
|
|
||||||
{ XK_KP_Insert, ControlMask, "\033[L", -1, 0},
|
|
||||||
{ XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0},
|
|
||||||
{ XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0},
|
|
||||||
{ XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0},
|
|
||||||
{ XK_KP_Delete, ControlMask, "\033[M", -1, 0},
|
|
||||||
{ XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0},
|
|
||||||
{ XK_KP_Delete, ShiftMask, "\033[2K", -1, 0},
|
|
||||||
{ XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0},
|
|
||||||
{ XK_KP_Delete, XK_ANY_MOD, "\033[3~", -1, 0},
|
|
||||||
{ XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
|
|
||||||
{ XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0},
|
|
||||||
{ XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0},
|
|
||||||
{ XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0},
|
|
||||||
{ XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0},
|
|
||||||
{ XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0},
|
|
||||||
{ XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0},
|
|
||||||
{ XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0},
|
|
||||||
{ XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0},
|
|
||||||
{ XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0},
|
|
||||||
{ XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0},
|
|
||||||
{ XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0},
|
|
||||||
{ XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0},
|
|
||||||
{ XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0},
|
|
||||||
{ XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0},
|
|
||||||
{ XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0},
|
|
||||||
{ XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0},
|
|
||||||
{ XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0},
|
|
||||||
{ XK_Up, ShiftMask, "\033[1;2A", 0, 0},
|
|
||||||
{ XK_Up, Mod1Mask, "\033[1;3A", 0, 0},
|
|
||||||
{ XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0},
|
|
||||||
{ XK_Up, ControlMask, "\033[1;5A", 0, 0},
|
|
||||||
{ XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0},
|
|
||||||
{ XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0},
|
|
||||||
{ XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0},
|
|
||||||
{ XK_Up, XK_ANY_MOD, "\033[A", 0, -1},
|
|
||||||
{ XK_Up, XK_ANY_MOD, "\033OA", 0, +1},
|
|
||||||
{ XK_Down, ShiftMask, "\033[1;2B", 0, 0},
|
|
||||||
{ XK_Down, Mod1Mask, "\033[1;3B", 0, 0},
|
|
||||||
{ XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0},
|
|
||||||
{ XK_Down, ControlMask, "\033[1;5B", 0, 0},
|
|
||||||
{ XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0},
|
|
||||||
{ XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0},
|
|
||||||
{ XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0},
|
|
||||||
{ XK_Down, XK_ANY_MOD, "\033[B", 0, -1},
|
|
||||||
{ XK_Down, XK_ANY_MOD, "\033OB", 0, +1},
|
|
||||||
{ XK_Left, ShiftMask, "\033[1;2D", 0, 0},
|
|
||||||
{ XK_Left, Mod1Mask, "\033[1;3D", 0, 0},
|
|
||||||
{ XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0},
|
|
||||||
{ XK_Left, ControlMask, "\033[1;5D", 0, 0},
|
|
||||||
{ XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0},
|
|
||||||
{ XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0},
|
|
||||||
{ XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0},
|
|
||||||
{ XK_Left, XK_ANY_MOD, "\033[D", 0, -1},
|
|
||||||
{ XK_Left, XK_ANY_MOD, "\033OD", 0, +1},
|
|
||||||
{ XK_Right, ShiftMask, "\033[1;2C", 0, 0},
|
|
||||||
{ XK_Right, Mod1Mask, "\033[1;3C", 0, 0},
|
|
||||||
{ XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0},
|
|
||||||
{ XK_Right, ControlMask, "\033[1;5C", 0, 0},
|
|
||||||
{ XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0},
|
|
||||||
{ XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0},
|
|
||||||
{ XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0},
|
|
||||||
{ XK_Right, XK_ANY_MOD, "\033[C", 0, -1},
|
|
||||||
{ XK_Right, XK_ANY_MOD, "\033OC", 0, +1},
|
|
||||||
{ XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0},
|
|
||||||
{ XK_Return, Mod1Mask, "\033\r", 0, 0},
|
|
||||||
{ XK_Return, XK_ANY_MOD, "\r", 0, 0},
|
|
||||||
{ XK_Insert, ShiftMask, "\033[4l", -1, 0},
|
|
||||||
{ XK_Insert, ShiftMask, "\033[2;2~", +1, 0},
|
|
||||||
{ XK_Insert, ControlMask, "\033[L", -1, 0},
|
|
||||||
{ XK_Insert, ControlMask, "\033[2;5~", +1, 0},
|
|
||||||
{ XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0},
|
|
||||||
{ XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0},
|
|
||||||
{ XK_Delete, ControlMask, "\033[M", -1, 0},
|
|
||||||
{ XK_Delete, ControlMask, "\033[3;5~", +1, 0},
|
|
||||||
{ XK_Delete, ShiftMask, "\033[2K", -1, 0},
|
|
||||||
{ XK_Delete, ShiftMask, "\033[3;2~", +1, 0},
|
|
||||||
{ XK_Delete, XK_ANY_MOD, "\033[3~", -1, 0},
|
|
||||||
{ XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
|
|
||||||
{ XK_BackSpace, XK_NO_MOD, "\177", 0, 0},
|
|
||||||
{ XK_BackSpace, Mod1Mask, "\033\177", 0, 0},
|
|
||||||
{ XK_Home, ShiftMask, "\033[2J", 0, -1},
|
|
||||||
{ XK_Home, ShiftMask, "\033[1;2H", 0, +1},
|
|
||||||
{ XK_Home, XK_ANY_MOD, "\033[H", 0, -1},
|
|
||||||
{ XK_Home, XK_ANY_MOD, "\033[1~", 0, +1},
|
|
||||||
{ XK_End, ControlMask, "\033[J", -1, 0},
|
|
||||||
{ XK_End, ControlMask, "\033[1;5F", +1, 0},
|
|
||||||
{ XK_End, ShiftMask, "\033[K", -1, 0},
|
|
||||||
{ XK_End, ShiftMask, "\033[1;2F", +1, 0},
|
|
||||||
{ XK_End, XK_ANY_MOD, "\033[4~", 0, 0},
|
|
||||||
{ XK_Prior, ControlMask, "\033[5;5~", 0, 0},
|
|
||||||
{ XK_Prior, ShiftMask, "\033[5;2~", 0, 0},
|
|
||||||
{ XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0},
|
|
||||||
{ XK_Next, ControlMask, "\033[6;5~", 0, 0},
|
|
||||||
{ XK_Next, ShiftMask, "\033[6;2~", 0, 0},
|
|
||||||
{ XK_Next, XK_ANY_MOD, "\033[6~", 0, 0},
|
|
||||||
{ XK_F1, XK_NO_MOD, "\033OP" , 0, 0},
|
|
||||||
{ XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0},
|
|
||||||
{ XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0},
|
|
||||||
{ XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0},
|
|
||||||
{ XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0},
|
|
||||||
{ XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0},
|
|
||||||
{ XK_F2, XK_NO_MOD, "\033OQ" , 0, 0},
|
|
||||||
{ XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0},
|
|
||||||
{ XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0},
|
|
||||||
{ XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0},
|
|
||||||
{ XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0},
|
|
||||||
{ XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0},
|
|
||||||
{ XK_F3, XK_NO_MOD, "\033OR" , 0, 0},
|
|
||||||
{ XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0},
|
|
||||||
{ XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0},
|
|
||||||
{ XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0},
|
|
||||||
{ XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0},
|
|
||||||
{ XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0},
|
|
||||||
{ XK_F4, XK_NO_MOD, "\033OS" , 0, 0},
|
|
||||||
{ XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0},
|
|
||||||
{ XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0},
|
|
||||||
{ XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0},
|
|
||||||
{ XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0},
|
|
||||||
{ XK_F5, XK_NO_MOD, "\033[15~", 0, 0},
|
|
||||||
{ XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0},
|
|
||||||
{ XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0},
|
|
||||||
{ XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0},
|
|
||||||
{ XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0},
|
|
||||||
{ XK_F6, XK_NO_MOD, "\033[17~", 0, 0},
|
|
||||||
{ XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0},
|
|
||||||
{ XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0},
|
|
||||||
{ XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0},
|
|
||||||
{ XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0},
|
|
||||||
{ XK_F7, XK_NO_MOD, "\033[18~", 0, 0},
|
|
||||||
{ XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0},
|
|
||||||
{ XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0},
|
|
||||||
{ XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0},
|
|
||||||
{ XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0},
|
|
||||||
{ XK_F8, XK_NO_MOD, "\033[19~", 0, 0},
|
|
||||||
{ XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0},
|
|
||||||
{ XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0},
|
|
||||||
{ XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0},
|
|
||||||
{ XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0},
|
|
||||||
{ XK_F9, XK_NO_MOD, "\033[20~", 0, 0},
|
|
||||||
{ XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0},
|
|
||||||
{ XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0},
|
|
||||||
{ XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0},
|
|
||||||
{ XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0},
|
|
||||||
{ XK_F10, XK_NO_MOD, "\033[21~", 0, 0},
|
|
||||||
{ XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0},
|
|
||||||
{ XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0},
|
|
||||||
{ XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0},
|
|
||||||
{ XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0},
|
|
||||||
{ XK_F11, XK_NO_MOD, "\033[23~", 0, 0},
|
|
||||||
{ XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0},
|
|
||||||
{ XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0},
|
|
||||||
{ XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0},
|
|
||||||
{ XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0},
|
|
||||||
{ XK_F12, XK_NO_MOD, "\033[24~", 0, 0},
|
|
||||||
{ XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0},
|
|
||||||
{ XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0},
|
|
||||||
{ XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0},
|
|
||||||
{ XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0},
|
|
||||||
{ XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0},
|
|
||||||
{ XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0},
|
|
||||||
{ XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0},
|
|
||||||
{ XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0},
|
|
||||||
{ XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0},
|
|
||||||
{ XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0},
|
|
||||||
{ XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0},
|
|
||||||
{ XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0},
|
|
||||||
{ XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0},
|
|
||||||
{ XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0},
|
|
||||||
{ XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0},
|
|
||||||
{ XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0},
|
|
||||||
{ XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0},
|
|
||||||
{ XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0},
|
|
||||||
{ XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0},
|
|
||||||
{ XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0},
|
|
||||||
{ XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0},
|
|
||||||
{ XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0},
|
|
||||||
{ XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0},
|
|
||||||
{ XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0},
|
|
||||||
{ XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0},
|
|
||||||
{ XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0},
|
|
||||||
{ XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Selection types' masks.
|
|
||||||
* Use the same masks as usual.
|
|
||||||
* Button1Mask is always unset, to make masks match between ButtonPress.
|
|
||||||
* ButtonRelease and MotionNotify.
|
|
||||||
* If no match is found, regular selection is used.
|
|
||||||
*/
|
|
||||||
static uint selmasks[] = {
|
|
||||||
[SEL_RECTANGULAR] = Mod1Mask,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Printable characters in ASCII, used to estimate the advance width
|
|
||||||
* of single wide characters.
|
|
||||||
*/
|
|
||||||
static char ascii_printable[] =
|
|
||||||
" !\"#$%&'()*+,-./0123456789:;<=>?"
|
|
||||||
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
|
|
||||||
"`abcdefghijklmnopqrstuvwxyz{|}~";
|
|
|
@ -1,5 +1,5 @@
|
||||||
# st version
|
# st version
|
||||||
VERSION = 0.8.4
|
VERSION = 0.9
|
||||||
|
|
||||||
# Customize below to fit your system
|
# Customize below to fit your system
|
||||||
|
|
||||||
|
@ -15,12 +15,10 @@ PKG_CONFIG = pkg-config
|
||||||
# includes and libs
|
# includes and libs
|
||||||
INCS = -I$(X11INC) \
|
INCS = -I$(X11INC) \
|
||||||
`$(PKG_CONFIG) --cflags fontconfig` \
|
`$(PKG_CONFIG) --cflags fontconfig` \
|
||||||
`$(PKG_CONFIG) --cflags freetype2` \
|
`$(PKG_CONFIG) --cflags freetype2`
|
||||||
`$(PKG_CONFIG) --cflags harfbuzz`
|
|
||||||
LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \
|
LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \
|
||||||
`$(PKG_CONFIG) --libs fontconfig` \
|
`$(PKG_CONFIG) --libs fontconfig` \
|
||||||
`$(PKG_CONFIG) --libs freetype2` \
|
`$(PKG_CONFIG) --libs freetype2`
|
||||||
`$(PKG_CONFIG) --libs harfbuzz`
|
|
||||||
|
|
||||||
# flags
|
# flags
|
||||||
STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
|
STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
|
||||||
|
@ -32,6 +30,7 @@ STLDFLAGS = $(LIBS) $(LDFLAGS)
|
||||||
#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \
|
#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \
|
||||||
# `$(PKG_CONFIG) --libs fontconfig` \
|
# `$(PKG_CONFIG) --libs fontconfig` \
|
||||||
# `$(PKG_CONFIG) --libs freetype2`
|
# `$(PKG_CONFIG) --libs freetype2`
|
||||||
|
#MANPREFIX = ${PREFIX}/man
|
||||||
|
|
||||||
# compiler and linker
|
# compiler and linker
|
||||||
# CC = c99
|
# CC = c99
|
||||||
|
|
136
st/hb.c
136
st/hb.c
|
@ -1,136 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <X11/Xft/Xft.h>
|
|
||||||
#include <hb.h>
|
|
||||||
#include <hb-ft.h>
|
|
||||||
|
|
||||||
#include "st.h"
|
|
||||||
|
|
||||||
void hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length);
|
|
||||||
hb_font_t *hbfindfont(XftFont *match);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
XftFont *match;
|
|
||||||
hb_font_t *font;
|
|
||||||
} HbFontMatch;
|
|
||||||
|
|
||||||
static int hbfontslen = 0;
|
|
||||||
static HbFontMatch *hbfontcache = NULL;
|
|
||||||
|
|
||||||
void
|
|
||||||
hbunloadfonts()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < hbfontslen; i++) {
|
|
||||||
hb_font_destroy(hbfontcache[i].font);
|
|
||||||
XftUnlockFace(hbfontcache[i].match);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hbfontcache != NULL) {
|
|
||||||
free(hbfontcache);
|
|
||||||
hbfontcache = NULL;
|
|
||||||
}
|
|
||||||
hbfontslen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_font_t *
|
|
||||||
hbfindfont(XftFont *match)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < hbfontslen; i++) {
|
|
||||||
if (hbfontcache[i].match == match)
|
|
||||||
return hbfontcache[i].font;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Font not found in cache, caching it now. */
|
|
||||||
hbfontcache = realloc(hbfontcache, sizeof(HbFontMatch) * (hbfontslen + 1));
|
|
||||||
FT_Face face = XftLockFace(match);
|
|
||||||
hb_font_t *font = hb_ft_font_create(face, NULL);
|
|
||||||
if (font == NULL)
|
|
||||||
die("Failed to load Harfbuzz font.");
|
|
||||||
|
|
||||||
hbfontcache[hbfontslen].match = match;
|
|
||||||
hbfontcache[hbfontslen].font = font;
|
|
||||||
hbfontslen += 1;
|
|
||||||
|
|
||||||
return font;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
hbtransform(XftGlyphFontSpec *specs, const Glyph *glyphs, size_t len, int x, int y)
|
|
||||||
{
|
|
||||||
int start = 0, length = 1, gstart = 0;
|
|
||||||
hb_codepoint_t *codepoints = calloc(len, sizeof(hb_codepoint_t));
|
|
||||||
|
|
||||||
for (int idx = 1, specidx = 1; idx < len; idx++) {
|
|
||||||
if (glyphs[idx].mode & ATTR_WDUMMY) {
|
|
||||||
length += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (specs[specidx].font != specs[start].font || ATTRCMP(glyphs[gstart], glyphs[idx]) || selected(x + idx, y) != selected(x + gstart, y)) {
|
|
||||||
hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length);
|
|
||||||
|
|
||||||
/* Reset the sequence. */
|
|
||||||
length = 1;
|
|
||||||
start = specidx;
|
|
||||||
gstart = idx;
|
|
||||||
} else {
|
|
||||||
length += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
specidx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOL. */
|
|
||||||
hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length);
|
|
||||||
|
|
||||||
/* Apply the transformation to glyph specs. */
|
|
||||||
for (int i = 0, specidx = 0; i < len; i++) {
|
|
||||||
if (glyphs[i].mode & ATTR_WDUMMY)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (codepoints[i] != specs[specidx].glyph)
|
|
||||||
((Glyph *)glyphs)[i].mode |= ATTR_LIGA;
|
|
||||||
|
|
||||||
specs[specidx++].glyph = codepoints[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
free(codepoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length)
|
|
||||||
{
|
|
||||||
hb_font_t *font = hbfindfont(xfont);
|
|
||||||
if (font == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Rune rune;
|
|
||||||
ushort mode = USHRT_MAX;
|
|
||||||
hb_buffer_t *buffer = hb_buffer_create();
|
|
||||||
hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
|
|
||||||
|
|
||||||
/* Fill buffer with codepoints. */
|
|
||||||
for (int i = start; i < (start+length); i++) {
|
|
||||||
rune = string[i].u;
|
|
||||||
mode = string[i].mode;
|
|
||||||
if (mode & ATTR_WDUMMY)
|
|
||||||
rune = 0x0020;
|
|
||||||
hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shape the segment. */
|
|
||||||
hb_shape(font, buffer, NULL, 0);
|
|
||||||
|
|
||||||
/* Get new glyph info. */
|
|
||||||
hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, NULL);
|
|
||||||
|
|
||||||
/* Write new codepoints. */
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
hb_codepoint_t gid = info[i].codepoint;
|
|
||||||
codepoints[start+i] = gid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cleanup. */
|
|
||||||
hb_buffer_destroy(buffer);
|
|
||||||
}
|
|
7
st/hb.h
7
st/hb.h
|
@ -1,7 +0,0 @@
|
||||||
#include <X11/Xft/Xft.h>
|
|
||||||
#include <hb.h>
|
|
||||||
#include <hb-ft.h>
|
|
||||||
|
|
||||||
void hbunloadfonts();
|
|
||||||
void hbtransform(XftGlyphFontSpec *, const Glyph *, size_t, int, int);
|
|
||||||
|
|
|
@ -1,153 +0,0 @@
|
||||||
From 407a3d065645ee814e04a6c62a2d2dea04a1c18c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Finn Rayment <finn@rayment.fr>
|
|
||||||
Date: Sat, 3 Oct 2020 14:47:04 +0200
|
|
||||||
Subject: [PATCH] Applied anysize patch fix
|
|
||||||
|
|
||||||
---
|
|
||||||
x.c | 52 ++++++++++++++++++++++++++++------------------------
|
|
||||||
1 file changed, 28 insertions(+), 24 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/x.c b/x.c
|
|
||||||
index 210f184..a11a992 100644
|
|
||||||
--- a/x.c
|
|
||||||
+++ b/x.c
|
|
||||||
@@ -81,6 +81,7 @@ typedef XftGlyphFontSpec GlyphFontSpec;
|
|
||||||
typedef struct {
|
|
||||||
int tw, th; /* tty width and height */
|
|
||||||
int w, h; /* window width and height */
|
|
||||||
+ int hborderpx, vborderpx;
|
|
||||||
int ch; /* char height */
|
|
||||||
int cw; /* char width */
|
|
||||||
int mode; /* window state/mode flags */
|
|
||||||
@@ -331,7 +332,7 @@ ttysend(const Arg *arg)
|
|
||||||
int
|
|
||||||
evcol(XEvent *e)
|
|
||||||
{
|
|
||||||
- int x = e->xbutton.x - borderpx;
|
|
||||||
+ int x = e->xbutton.x - win.hborderpx;
|
|
||||||
LIMIT(x, 0, win.tw - 1);
|
|
||||||
return x / win.cw;
|
|
||||||
}
|
|
||||||
@@ -339,7 +340,7 @@ evcol(XEvent *e)
|
|
||||||
int
|
|
||||||
evrow(XEvent *e)
|
|
||||||
{
|
|
||||||
- int y = e->xbutton.y - borderpx;
|
|
||||||
+ int y = e->xbutton.y - win.vborderpx;
|
|
||||||
LIMIT(y, 0, win.th - 1);
|
|
||||||
return y / win.ch;
|
|
||||||
}
|
|
||||||
@@ -721,6 +722,9 @@ cresize(int width, int height)
|
|
||||||
col = MAX(1, col);
|
|
||||||
row = MAX(1, row);
|
|
||||||
|
|
||||||
+ win.hborderpx = (win.w - col * win.cw) / 2;
|
|
||||||
+ win.vborderpx = (win.h - row * win.ch) / 2;
|
|
||||||
+
|
|
||||||
tresize(col, row);
|
|
||||||
xresize(col, row);
|
|
||||||
ttyresize(win.tw, win.th);
|
|
||||||
@@ -1121,8 +1125,8 @@ xinit(int cols, int rows)
|
|
||||||
xloadcols();
|
|
||||||
|
|
||||||
/* adjust fixed window geometry */
|
|
||||||
- win.w = 2 * borderpx + cols * win.cw;
|
|
||||||
- win.h = 2 * borderpx + rows * win.ch;
|
|
||||||
+ win.w = 2 * win.hborderpx + cols * win.cw;
|
|
||||||
+ win.h = 2 * win.vborderpx + rows * win.ch;
|
|
||||||
if (xw.gm & XNegative)
|
|
||||||
xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2;
|
|
||||||
if (xw.gm & YNegative)
|
|
||||||
@@ -1210,7 +1214,7 @@ xinit(int cols, int rows)
|
|
||||||
int
|
|
||||||
xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y)
|
|
||||||
{
|
|
||||||
- float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp;
|
|
||||||
+ float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp;
|
|
||||||
ushort mode, prevmode = USHRT_MAX;
|
|
||||||
Font *font = &dc.font;
|
|
||||||
int frcflags = FRC_NORMAL;
|
|
||||||
@@ -1343,7 +1347,7 @@ void
|
|
||||||
xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
|
|
||||||
{
|
|
||||||
int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
|
|
||||||
- int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
|
|
||||||
+ int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch,
|
|
||||||
width = charlen * win.cw;
|
|
||||||
Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
|
|
||||||
XRenderColor colfg, colbg;
|
|
||||||
@@ -1433,17 +1437,17 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
|
|
||||||
|
|
||||||
/* Intelligent cleaning up of the borders. */
|
|
||||||
if (x == 0) {
|
|
||||||
- xclear(0, (y == 0)? 0 : winy, borderpx,
|
|
||||||
+ xclear(0, (y == 0)? 0 : winy, win.vborderpx,
|
|
||||||
winy + win.ch +
|
|
||||||
- ((winy + win.ch >= borderpx + win.th)? win.h : 0));
|
|
||||||
+ ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0));
|
|
||||||
}
|
|
||||||
- if (winx + width >= borderpx + win.tw) {
|
|
||||||
+ if (winx + width >= win.hborderpx + win.tw) {
|
|
||||||
xclear(winx + width, (y == 0)? 0 : winy, win.w,
|
|
||||||
- ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
|
|
||||||
+ ((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch)));
|
|
||||||
}
|
|
||||||
if (y == 0)
|
|
||||||
- xclear(winx, 0, winx + width, borderpx);
|
|
||||||
- if (winy + win.ch >= borderpx + win.th)
|
|
||||||
+ xclear(winx, 0, winx + width, win.hborderpx);
|
|
||||||
+ if (winy + win.ch >= win.vborderpx + win.th)
|
|
||||||
xclear(winx, winy + win.ch, winx + width, win.h);
|
|
||||||
|
|
||||||
/* Clean up the region we want to draw to. */
|
|
||||||
@@ -1537,35 +1541,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
|
|
||||||
case 3: /* Blinking Underline */
|
|
||||||
case 4: /* Steady Underline */
|
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
|
||||||
- borderpx + cx * win.cw,
|
|
||||||
- borderpx + (cy + 1) * win.ch - \
|
|
||||||
+ win.hborderpx + cx * win.cw,
|
|
||||||
+ win.vborderpx + (cy + 1) * win.ch - \
|
|
||||||
cursorthickness,
|
|
||||||
win.cw, cursorthickness);
|
|
||||||
break;
|
|
||||||
case 5: /* Blinking bar */
|
|
||||||
case 6: /* Steady bar */
|
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
|
||||||
- borderpx + cx * win.cw,
|
|
||||||
- borderpx + cy * win.ch,
|
|
||||||
+ win.hborderpx + cx * win.cw,
|
|
||||||
+ win.vborderpx + cy * win.ch,
|
|
||||||
cursorthickness, win.ch);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
|
||||||
- borderpx + cx * win.cw,
|
|
||||||
- borderpx + cy * win.ch,
|
|
||||||
+ win.hborderpx + cx * win.cw,
|
|
||||||
+ win.vborderpx + cy * win.ch,
|
|
||||||
win.cw - 1, 1);
|
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
|
||||||
- borderpx + cx * win.cw,
|
|
||||||
- borderpx + cy * win.ch,
|
|
||||||
+ win.hborderpx + cx * win.cw,
|
|
||||||
+ win.vborderpx + cy * win.ch,
|
|
||||||
1, win.ch - 1);
|
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
|
||||||
- borderpx + (cx + 1) * win.cw - 1,
|
|
||||||
- borderpx + cy * win.ch,
|
|
||||||
+ win.hborderpx + (cx + 1) * win.cw - 1,
|
|
||||||
+ win.vborderpx + cy * win.ch,
|
|
||||||
1, win.ch - 1);
|
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
|
||||||
- borderpx + cx * win.cw,
|
|
||||||
- borderpx + (cy + 1) * win.ch - 1,
|
|
||||||
+ win.hborderpx + cx * win.cw,
|
|
||||||
+ win.vborderpx + (cy + 1) * win.ch - 1,
|
|
||||||
win.cw, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.28.0
|
|
||||||
|
|
|
@ -1,150 +0,0 @@
|
||||||
From bff176133618854676bbdc74c0099f184d3da365 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Steve Ward <planet36@gmail.com>
|
|
||||||
Date: Sun, 31 May 2020 22:48:25 -0400
|
|
||||||
Subject: [PATCH] Allow blinking cursor
|
|
||||||
|
|
||||||
---
|
|
||||||
config.def.h | 19 +++++++++++++------
|
|
||||||
x.c | 42 ++++++++++++++++++++++++++++++++----------
|
|
||||||
2 files changed, 45 insertions(+), 16 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 6f05dce..3dbe915 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -133,13 +133,20 @@ static unsigned int defaultcs = 256;
|
|
||||||
static unsigned int defaultrcs = 257;
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Default shape of cursor
|
|
||||||
- * 2: Block ("█")
|
|
||||||
- * 4: Underline ("_")
|
|
||||||
- * 6: Bar ("|")
|
|
||||||
- * 7: Snowman ("☃")
|
|
||||||
+ * https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-SP-q.1D81
|
|
||||||
+ * Default style of cursor
|
|
||||||
+ * 0: Blinking block
|
|
||||||
+ * 1: Blinking block (default)
|
|
||||||
+ * 2: Steady block ("█")
|
|
||||||
+ * 3: Blinking underline
|
|
||||||
+ * 4: Steady underline ("_")
|
|
||||||
+ * 5: Blinking bar
|
|
||||||
+ * 6: Steady bar ("|")
|
|
||||||
+ * 7: Blinking st cursor
|
|
||||||
+ * 8: Steady st cursor
|
|
||||||
*/
|
|
||||||
-static unsigned int cursorshape = 2;
|
|
||||||
+static unsigned int cursorstyle = 1;
|
|
||||||
+static Rune stcursor = 0x2603; /* snowman (U+2603) */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Default columns and rows numbers
|
|
||||||
diff --git a/x.c b/x.c
|
|
||||||
index 210f184..bd80a5e 100644
|
|
||||||
--- a/x.c
|
|
||||||
+++ b/x.c
|
|
||||||
@@ -253,6 +253,7 @@ static char *opt_name = NULL;
|
|
||||||
static char *opt_title = NULL;
|
|
||||||
|
|
||||||
static int oldbutton = 3; /* button event on startup: 3 = release */
|
|
||||||
+static int cursorblinks = 0;
|
|
||||||
|
|
||||||
void
|
|
||||||
clipcopy(const Arg *dummy)
|
|
||||||
@@ -1526,16 +1527,19 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
|
|
||||||
/* draw the new one */
|
|
||||||
if (IS_SET(MODE_FOCUSED)) {
|
|
||||||
switch (win.cursor) {
|
|
||||||
- case 7: /* st extension */
|
|
||||||
- g.u = 0x2603; /* snowman (U+2603) */
|
|
||||||
+ case 0: /* Blinking block */
|
|
||||||
+ case 1: /* Blinking block (default) */
|
|
||||||
+ if (IS_SET(MODE_BLINK))
|
|
||||||
+ break;
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
- case 0: /* Blinking Block */
|
|
||||||
- case 1: /* Blinking Block (Default) */
|
|
||||||
- case 2: /* Steady Block */
|
|
||||||
+ case 2: /* Steady block */
|
|
||||||
xdrawglyph(g, cx, cy);
|
|
||||||
break;
|
|
||||||
- case 3: /* Blinking Underline */
|
|
||||||
- case 4: /* Steady Underline */
|
|
||||||
+ case 3: /* Blinking underline */
|
|
||||||
+ if (IS_SET(MODE_BLINK))
|
|
||||||
+ break;
|
|
||||||
+ /* FALLTHROUGH */
|
|
||||||
+ case 4: /* Steady underline */
|
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
|
||||||
borderpx + cx * win.cw,
|
|
||||||
borderpx + (cy + 1) * win.ch - \
|
|
||||||
@@ -1543,12 +1547,23 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
|
|
||||||
win.cw, cursorthickness);
|
|
||||||
break;
|
|
||||||
case 5: /* Blinking bar */
|
|
||||||
+ if (IS_SET(MODE_BLINK))
|
|
||||||
+ break;
|
|
||||||
+ /* FALLTHROUGH */
|
|
||||||
case 6: /* Steady bar */
|
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
|
||||||
borderpx + cx * win.cw,
|
|
||||||
borderpx + cy * win.ch,
|
|
||||||
cursorthickness, win.ch);
|
|
||||||
break;
|
|
||||||
+ case 7: /* Blinking st cursor */
|
|
||||||
+ if (IS_SET(MODE_BLINK))
|
|
||||||
+ break;
|
|
||||||
+ /* FALLTHROUGH */
|
|
||||||
+ case 8: /* Steady st cursor */
|
|
||||||
+ g.u = stcursor;
|
|
||||||
+ xdrawglyph(g, cx, cy);
|
|
||||||
+ break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
|
||||||
@@ -1690,9 +1705,12 @@ xsetmode(int set, unsigned int flags)
|
|
||||||
int
|
|
||||||
xsetcursor(int cursor)
|
|
||||||
{
|
|
||||||
- if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */
|
|
||||||
+ if (!BETWEEN(cursor, 0, 8)) /* 7-8: st extensions */
|
|
||||||
return 1;
|
|
||||||
win.cursor = cursor;
|
|
||||||
+ cursorblinks = win.cursor == 0 || win.cursor == 1 ||
|
|
||||||
+ win.cursor == 3 || win.cursor == 5 ||
|
|
||||||
+ win.cursor == 7;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1936,6 +1954,10 @@ run(void)
|
|
||||||
if (FD_ISSET(ttyfd, &rfd) || xev) {
|
|
||||||
if (!drawing) {
|
|
||||||
trigger = now;
|
|
||||||
+ if (IS_SET(MODE_BLINK)) {
|
|
||||||
+ win.mode ^= MODE_BLINK;
|
|
||||||
+ }
|
|
||||||
+ lastblink = now;
|
|
||||||
drawing = 1;
|
|
||||||
}
|
|
||||||
timeout = (maxlatency - TIMEDIFF(now, trigger)) \
|
|
||||||
@@ -1946,7 +1968,7 @@ run(void)
|
|
||||||
|
|
||||||
/* idle detected or maxlatency exhausted -> draw */
|
|
||||||
timeout = -1;
|
|
||||||
- if (blinktimeout && tattrset(ATTR_BLINK)) {
|
|
||||||
+ if (blinktimeout && (cursorblinks || tattrset(ATTR_BLINK))) {
|
|
||||||
timeout = blinktimeout - TIMEDIFF(now, lastblink);
|
|
||||||
if (timeout <= 0) {
|
|
||||||
if (-timeout > blinktimeout) /* start visible */
|
|
||||||
@@ -1982,7 +2004,7 @@ main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
xw.l = xw.t = 0;
|
|
||||||
xw.isfixed = False;
|
|
||||||
- xsetcursor(cursorshape);
|
|
||||||
+ xsetcursor(cursorstyle);
|
|
||||||
|
|
||||||
ARGBEGIN {
|
|
||||||
case 'a':
|
|
||||||
--
|
|
||||||
2.20.1
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
diff --git a/x.c b/x.c
|
|
||||||
index 13fa9f4..88fd341 100644
|
|
||||||
--- a/x.c
|
|
||||||
+++ b/x.c
|
|
||||||
@@ -624,6 +624,8 @@ setsel(char *str, Time t)
|
|
||||||
XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
|
|
||||||
if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
|
|
||||||
selclear();
|
|
||||||
+
|
|
||||||
+ xclipcopy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
|
@ -1,20 +0,0 @@
|
||||||
--- config.def.h.orig 2020-11-12 20:23:48.867954750 +0100
|
|
||||||
+++ config.def.h 2020-11-12 20:21:15.055922720 +0100
|
|
||||||
@@ -276,7 +276,7 @@
|
|
||||||
{ XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0},
|
|
||||||
{ XK_KP_Delete, ShiftMask, "\033[2K", -1, 0},
|
|
||||||
{ XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0},
|
|
||||||
- { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0},
|
|
||||||
+ { XK_KP_Delete, XK_ANY_MOD, "\033[3~", -1, 0},
|
|
||||||
{ XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
|
|
||||||
{ XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0},
|
|
||||||
{ XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0},
|
|
||||||
@@ -344,7 +344,7 @@
|
|
||||||
{ XK_Delete, ControlMask, "\033[3;5~", +1, 0},
|
|
||||||
{ XK_Delete, ShiftMask, "\033[2K", -1, 0},
|
|
||||||
{ XK_Delete, ShiftMask, "\033[3;2~", +1, 0},
|
|
||||||
- { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0},
|
|
||||||
+ { XK_Delete, XK_ANY_MOD, "\033[3~", -1, 0},
|
|
||||||
{ XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0},
|
|
||||||
{ XK_BackSpace, XK_NO_MOD, "\177", 0, 0},
|
|
||||||
{ XK_BackSpace, Mod1Mask, "\033\177", 0, 0},
|
|
|
@ -1,70 +0,0 @@
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 877afab..6a1699f 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -84,41 +84,35 @@ static unsigned int tabspaces = 8;
|
|
||||||
|
|
||||||
/* Terminal colors (16 first used in escape sequence) */
|
|
||||||
static const char *colorname[] = {
|
|
||||||
- /* 8 normal colors */
|
|
||||||
- "black",
|
|
||||||
- "red3",
|
|
||||||
- "green3",
|
|
||||||
- "yellow3",
|
|
||||||
- "blue2",
|
|
||||||
- "magenta3",
|
|
||||||
- "cyan3",
|
|
||||||
- "gray90",
|
|
||||||
-
|
|
||||||
- /* 8 bright colors */
|
|
||||||
- "gray50",
|
|
||||||
- "red",
|
|
||||||
- "green",
|
|
||||||
- "yellow",
|
|
||||||
- "#5c5cff",
|
|
||||||
- "magenta",
|
|
||||||
- "cyan",
|
|
||||||
- "white",
|
|
||||||
-
|
|
||||||
- [255] = 0,
|
|
||||||
-
|
|
||||||
- /* more colors can be added after 255 to use with DefaultXX */
|
|
||||||
- "#cccccc",
|
|
||||||
- "#555555",
|
|
||||||
-};
|
|
||||||
|
|
||||||
+ /* 8 normal colors */
|
|
||||||
+ [0] = "#282828", /* hard contrast: #1d2021 / soft contrast: #32302f */
|
|
||||||
+ [1] = "#cc241d", /* red */
|
|
||||||
+ [2] = "#98971a", /* green */
|
|
||||||
+ [3] = "#d79921", /* yellow */
|
|
||||||
+ [4] = "#458588", /* blue */
|
|
||||||
+ [5] = "#b16286", /* magenta */
|
|
||||||
+ [6] = "#689d6a", /* cyan */
|
|
||||||
+ [7] = "#a89984", /* white */
|
|
||||||
+
|
|
||||||
+ /* 8 bright colors */
|
|
||||||
+ [8] = "#928374", /* black */
|
|
||||||
+ [9] = "#fb4934", /* red */
|
|
||||||
+ [10] = "#b8bb26", /* green */
|
|
||||||
+ [11] = "#fabd2f", /* yellow */
|
|
||||||
+ [12] = "#83a598", /* blue */
|
|
||||||
+ [13] = "#d3869b", /* magenta */
|
|
||||||
+ [14] = "#8ec07c", /* cyan */
|
|
||||||
+ [15] = "#ebdbb2", /* white */
|
|
||||||
+};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Default colors (colorname index)
|
|
||||||
- * foreground, background, cursor, reverse cursor
|
|
||||||
+ * foreground, background, cursor
|
|
||||||
*/
|
|
||||||
-unsigned int defaultfg = 7;
|
|
||||||
-unsigned int defaultbg = 0;
|
|
||||||
-static unsigned int defaultcs = 256;
|
|
||||||
+unsigned int defaultfg = 15;
|
|
||||||
+unsigned int defaultbg = 0;
|
|
||||||
+static unsigned int defaultcs = 15;
|
|
||||||
static unsigned int defaultrcs = 257;
|
|
||||||
|
|
||||||
/*
|
|
|
@ -1,100 +0,0 @@
|
||||||
From 3e8f83d40c6fdd89653ef547aa16cffe1f3c1793 Mon Sep 17 00:00:00 2001
|
|
||||||
From: aleks <aleks.stier@icloud.com>
|
|
||||||
Date: Sun, 4 Aug 2019 13:23:10 +0200
|
|
||||||
Subject: [PATCH] Apply nord-theme
|
|
||||||
|
|
||||||
*"Inspired by the beauty of the arctic, the colors reflect the cold, yet
|
|
||||||
harmonious world of ice and the colorfulness of the Aurora Borealis."* - [Nord
|
|
||||||
Theme](https://www.nordtheme.com/)
|
|
||||||
|
|
||||||
There are also many [ports](https://www.nordtheme.com/ports) for other programs
|
|
||||||
like [vim](https://www.nordtheme.com/ports/vim) and
|
|
||||||
[tmux](https://www.nordtheme.com/ports/tmux) to make the overall appearance
|
|
||||||
coherent. I would recommend to use it in combination with the arc-theme for gtk
|
|
||||||
(fits perfectly).
|
|
||||||
|
|
||||||
The default behaviour of st is to reverse the fore- and background colors of
|
|
||||||
each selected cell. If you want that the selection-colors are not reveresed but
|
|
||||||
instead have fixed fore- and background colors apply on top of this patch the
|
|
||||||
[selectioncolors](../selectioncolors/)-patch. Then set the following settings
|
|
||||||
in your config.h:
|
|
||||||
|
|
||||||
static unsigned int defaultcs = 257;
|
|
||||||
static unsigned int defaultrcs = 257;
|
|
||||||
unsigned int selectionfg = 257;
|
|
||||||
unsigned int selectionbg = 0;
|
|
||||||
---
|
|
||||||
config.def.h | 44 ++++++++++++++++++++++----------------------
|
|
||||||
1 file changed, 22 insertions(+), 22 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 0e01717..fb504d4 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -85,30 +85,30 @@ unsigned int tabspaces = 8;
|
|
||||||
/* Terminal colors (16 first used in escape sequence) */
|
|
||||||
static const char *colorname[] = {
|
|
||||||
/* 8 normal colors */
|
|
||||||
- "black",
|
|
||||||
- "red3",
|
|
||||||
- "green3",
|
|
||||||
- "yellow3",
|
|
||||||
- "blue2",
|
|
||||||
- "magenta3",
|
|
||||||
- "cyan3",
|
|
||||||
- "gray90",
|
|
||||||
+ "#3b4252", /* black */
|
|
||||||
+ "#bf616a", /* red */
|
|
||||||
+ "#a3be8c", /* green */
|
|
||||||
+ "#ebcb8b", /* yellow */
|
|
||||||
+ "#81a1c1", /* blue */
|
|
||||||
+ "#b48ead", /* magenta */
|
|
||||||
+ "#88c0d0", /* cyan */
|
|
||||||
+ "#e5e9f0", /* white */
|
|
||||||
|
|
||||||
/* 8 bright colors */
|
|
||||||
- "gray50",
|
|
||||||
- "red",
|
|
||||||
- "green",
|
|
||||||
- "yellow",
|
|
||||||
- "#5c5cff",
|
|
||||||
- "magenta",
|
|
||||||
- "cyan",
|
|
||||||
- "white",
|
|
||||||
+ "#4c566a", /* black */
|
|
||||||
+ "#bf616a", /* red */
|
|
||||||
+ "#a3be8c", /* green */
|
|
||||||
+ "#ebcb8b", /* yellow */
|
|
||||||
+ "#81a1c1", /* blue */
|
|
||||||
+ "#b48ead", /* magenta */
|
|
||||||
+ "#8fbcbb", /* cyan */
|
|
||||||
+ "#eceff4", /* white */
|
|
||||||
|
|
||||||
[255] = 0,
|
|
||||||
|
|
||||||
/* more colors can be added after 255 to use with DefaultXX */
|
|
||||||
- "#cccccc",
|
|
||||||
- "#555555",
|
|
||||||
+ "#2e3440", /* background */
|
|
||||||
+ "#d8dee9", /* foreground */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -116,10 +116,10 @@ static const char *colorname[] = {
|
|
||||||
* Default colors (colorname index)
|
|
||||||
* foreground, background, cursor, reverse cursor
|
|
||||||
*/
|
|
||||||
-unsigned int defaultfg = 7;
|
|
||||||
-unsigned int defaultbg = 0;
|
|
||||||
-static unsigned int defaultcs = 256;
|
|
||||||
-static unsigned int defaultrcs = 257;
|
|
||||||
+unsigned int defaultfg = 257;
|
|
||||||
+unsigned int defaultbg = 256;
|
|
||||||
+static unsigned int defaultcs = 257;
|
|
||||||
+static unsigned int defaultrcs = 256;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Default shape of cursor
|
|
||||||
--
|
|
||||||
2.22.0
|
|
||||||
|
|
|
@ -1,351 +0,0 @@
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 6f05dce..93cbcc0 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -199,6 +199,8 @@ static Shortcut shortcuts[] = {
|
|
||||||
{ TERMMOD, XK_Y, selpaste, {.i = 0} },
|
|
||||||
{ ShiftMask, XK_Insert, selpaste, {.i = 0} },
|
|
||||||
{ TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
|
|
||||||
+ { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} },
|
|
||||||
+ { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} },
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
diff --git a/st.c b/st.c
|
|
||||||
index abbbe4b..e2dd722 100644
|
|
||||||
--- a/st.c
|
|
||||||
+++ b/st.c
|
|
||||||
@@ -35,6 +35,7 @@
|
|
||||||
#define ESC_ARG_SIZ 16
|
|
||||||
#define STR_BUF_SIZ ESC_BUF_SIZ
|
|
||||||
#define STR_ARG_SIZ ESC_ARG_SIZ
|
|
||||||
+#define HISTSIZE 2000
|
|
||||||
|
|
||||||
/* macros */
|
|
||||||
#define IS_SET(flag) ((term.mode & (flag)) != 0)
|
|
||||||
@@ -42,6 +43,9 @@
|
|
||||||
#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f))
|
|
||||||
#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
|
|
||||||
#define ISDELIM(u) (u && wcschr(worddelimiters, u))
|
|
||||||
+#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \
|
|
||||||
+ term.scr + HISTSIZE + 1) % HISTSIZE] : \
|
|
||||||
+ term.line[(y) - term.scr])
|
|
||||||
|
|
||||||
enum term_mode {
|
|
||||||
MODE_WRAP = 1 << 0,
|
|
||||||
@@ -115,6 +119,9 @@ typedef struct {
|
|
||||||
int col; /* nb col */
|
|
||||||
Line *line; /* screen */
|
|
||||||
Line *alt; /* alternate screen */
|
|
||||||
+ Line hist[HISTSIZE]; /* history buffer */
|
|
||||||
+ int histi; /* history index */
|
|
||||||
+ int scr; /* scroll back */
|
|
||||||
int *dirty; /* dirtyness of lines */
|
|
||||||
TCursor c; /* cursor */
|
|
||||||
int ocx; /* old cursor col */
|
|
||||||
@@ -184,8 +191,8 @@ static void tnewline(int);
|
|
||||||
static void tputtab(int);
|
|
||||||
static void tputc(Rune);
|
|
||||||
static void treset(void);
|
|
||||||
-static void tscrollup(int, int);
|
|
||||||
-static void tscrolldown(int, int);
|
|
||||||
+static void tscrollup(int, int, int);
|
|
||||||
+static void tscrolldown(int, int, int);
|
|
||||||
static void tsetattr(int *, int);
|
|
||||||
static void tsetchar(Rune, Glyph *, int, int);
|
|
||||||
static void tsetdirt(int, int);
|
|
||||||
@@ -414,10 +421,10 @@ tlinelen(int y)
|
|
||||||
{
|
|
||||||
int i = term.col;
|
|
||||||
|
|
||||||
- if (term.line[y][i - 1].mode & ATTR_WRAP)
|
|
||||||
+ if (TLINE(y)[i - 1].mode & ATTR_WRAP)
|
|
||||||
return i;
|
|
||||||
|
|
||||||
- while (i > 0 && term.line[y][i - 1].u == ' ')
|
|
||||||
+ while (i > 0 && TLINE(y)[i - 1].u == ' ')
|
|
||||||
--i;
|
|
||||||
|
|
||||||
return i;
|
|
||||||
@@ -526,7 +533,7 @@ selsnap(int *x, int *y, int direction)
|
|
||||||
* Snap around if the word wraps around at the end or
|
|
||||||
* beginning of a line.
|
|
||||||
*/
|
|
||||||
- prevgp = &term.line[*y][*x];
|
|
||||||
+ prevgp = &TLINE(*y)[*x];
|
|
||||||
prevdelim = ISDELIM(prevgp->u);
|
|
||||||
for (;;) {
|
|
||||||
newx = *x + direction;
|
|
||||||
@@ -541,14 +548,14 @@ selsnap(int *x, int *y, int direction)
|
|
||||||
yt = *y, xt = *x;
|
|
||||||
else
|
|
||||||
yt = newy, xt = newx;
|
|
||||||
- if (!(term.line[yt][xt].mode & ATTR_WRAP))
|
|
||||||
+ if (!(TLINE(yt)[xt].mode & ATTR_WRAP))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newx >= tlinelen(newy))
|
|
||||||
break;
|
|
||||||
|
|
||||||
- gp = &term.line[newy][newx];
|
|
||||||
+ gp = &TLINE(newy)[newx];
|
|
||||||
delim = ISDELIM(gp->u);
|
|
||||||
if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
|
|
||||||
|| (delim && gp->u != prevgp->u)))
|
|
||||||
@@ -569,14 +576,14 @@ selsnap(int *x, int *y, int direction)
|
|
||||||
*x = (direction < 0) ? 0 : term.col - 1;
|
|
||||||
if (direction < 0) {
|
|
||||||
for (; *y > 0; *y += direction) {
|
|
||||||
- if (!(term.line[*y-1][term.col-1].mode
|
|
||||||
+ if (!(TLINE(*y-1)[term.col-1].mode
|
|
||||||
& ATTR_WRAP)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (direction > 0) {
|
|
||||||
for (; *y < term.row-1; *y += direction) {
|
|
||||||
- if (!(term.line[*y][term.col-1].mode
|
|
||||||
+ if (!(TLINE(*y)[term.col-1].mode
|
|
||||||
& ATTR_WRAP)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
@@ -607,13 +614,13 @@ getsel(void)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sel.type == SEL_RECTANGULAR) {
|
|
||||||
- gp = &term.line[y][sel.nb.x];
|
|
||||||
+ gp = &TLINE(y)[sel.nb.x];
|
|
||||||
lastx = sel.ne.x;
|
|
||||||
} else {
|
|
||||||
- gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
|
|
||||||
+ gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
|
|
||||||
lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
|
|
||||||
}
|
|
||||||
- last = &term.line[y][MIN(lastx, linelen-1)];
|
|
||||||
+ last = &TLINE(y)[MIN(lastx, linelen-1)];
|
|
||||||
while (last >= gp && last->u == ' ')
|
|
||||||
--last;
|
|
||||||
|
|
||||||
@@ -848,6 +855,9 @@ void
|
|
||||||
ttywrite(const char *s, size_t n, int may_echo)
|
|
||||||
{
|
|
||||||
const char *next;
|
|
||||||
+ Arg arg = (Arg) { .i = term.scr };
|
|
||||||
+
|
|
||||||
+ kscrolldown(&arg);
|
|
||||||
|
|
||||||
if (may_echo && IS_SET(MODE_ECHO))
|
|
||||||
twrite(s, n, 1);
|
|
||||||
@@ -1059,13 +1069,53 @@ tswapscreen(void)
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
-tscrolldown(int orig, int n)
|
|
||||||
+kscrolldown(const Arg* a)
|
|
||||||
+{
|
|
||||||
+ int n = a->i;
|
|
||||||
+
|
|
||||||
+ if (n < 0)
|
|
||||||
+ n = term.row + n;
|
|
||||||
+
|
|
||||||
+ if (n > term.scr)
|
|
||||||
+ n = term.scr;
|
|
||||||
+
|
|
||||||
+ if (term.scr > 0) {
|
|
||||||
+ term.scr -= n;
|
|
||||||
+ selscroll(0, -n);
|
|
||||||
+ tfulldirt();
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+kscrollup(const Arg* a)
|
|
||||||
+{
|
|
||||||
+ int n = a->i;
|
|
||||||
+
|
|
||||||
+ if (n < 0)
|
|
||||||
+ n = term.row + n;
|
|
||||||
+
|
|
||||||
+ if (term.scr <= HISTSIZE-n) {
|
|
||||||
+ term.scr += n;
|
|
||||||
+ selscroll(0, n);
|
|
||||||
+ tfulldirt();
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+tscrolldown(int orig, int n, int copyhist)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
Line temp;
|
|
||||||
|
|
||||||
LIMIT(n, 0, term.bot-orig+1);
|
|
||||||
|
|
||||||
+ if (copyhist) {
|
|
||||||
+ term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE;
|
|
||||||
+ temp = term.hist[term.histi];
|
|
||||||
+ term.hist[term.histi] = term.line[term.bot];
|
|
||||||
+ term.line[term.bot] = temp;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
tsetdirt(orig, term.bot-n);
|
|
||||||
tclearregion(0, term.bot-n+1, term.col-1, term.bot);
|
|
||||||
|
|
||||||
@@ -1075,17 +1125,28 @@ tscrolldown(int orig, int n)
|
|
||||||
term.line[i-n] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
- selscroll(orig, n);
|
|
||||||
+ if (term.scr == 0)
|
|
||||||
+ selscroll(orig, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
-tscrollup(int orig, int n)
|
|
||||||
+tscrollup(int orig, int n, int copyhist)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
Line temp;
|
|
||||||
|
|
||||||
LIMIT(n, 0, term.bot-orig+1);
|
|
||||||
|
|
||||||
+ if (copyhist) {
|
|
||||||
+ term.histi = (term.histi + 1) % HISTSIZE;
|
|
||||||
+ temp = term.hist[term.histi];
|
|
||||||
+ term.hist[term.histi] = term.line[orig];
|
|
||||||
+ term.line[orig] = temp;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (term.scr > 0 && term.scr < HISTSIZE)
|
|
||||||
+ term.scr = MIN(term.scr + n, HISTSIZE-1);
|
|
||||||
+
|
|
||||||
tclearregion(0, orig, term.col-1, orig+n-1);
|
|
||||||
tsetdirt(orig+n, term.bot);
|
|
||||||
|
|
||||||
@@ -1095,7 +1156,8 @@ tscrollup(int orig, int n)
|
|
||||||
term.line[i+n] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
- selscroll(orig, -n);
|
|
||||||
+ if (term.scr == 0)
|
|
||||||
+ selscroll(orig, -n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -1124,7 +1186,7 @@ tnewline(int first_col)
|
|
||||||
int y = term.c.y;
|
|
||||||
|
|
||||||
if (y == term.bot) {
|
|
||||||
- tscrollup(term.top, 1);
|
|
||||||
+ tscrollup(term.top, 1, 1);
|
|
||||||
} else {
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
@@ -1289,14 +1351,14 @@ void
|
|
||||||
tinsertblankline(int n)
|
|
||||||
{
|
|
||||||
if (BETWEEN(term.c.y, term.top, term.bot))
|
|
||||||
- tscrolldown(term.c.y, n);
|
|
||||||
+ tscrolldown(term.c.y, n, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
tdeleteline(int n)
|
|
||||||
{
|
|
||||||
if (BETWEEN(term.c.y, term.top, term.bot))
|
|
||||||
- tscrollup(term.c.y, n);
|
|
||||||
+ tscrollup(term.c.y, n, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t
|
|
||||||
@@ -1733,11 +1795,11 @@ csihandle(void)
|
|
||||||
break;
|
|
||||||
case 'S': /* SU -- Scroll <n> line up */
|
|
||||||
DEFAULT(csiescseq.arg[0], 1);
|
|
||||||
- tscrollup(term.top, csiescseq.arg[0]);
|
|
||||||
+ tscrollup(term.top, csiescseq.arg[0], 0);
|
|
||||||
break;
|
|
||||||
case 'T': /* SD -- Scroll <n> line down */
|
|
||||||
DEFAULT(csiescseq.arg[0], 1);
|
|
||||||
- tscrolldown(term.top, csiescseq.arg[0]);
|
|
||||||
+ tscrolldown(term.top, csiescseq.arg[0], 0);
|
|
||||||
break;
|
|
||||||
case 'L': /* IL -- Insert <n> blank lines */
|
|
||||||
DEFAULT(csiescseq.arg[0], 1);
|
|
||||||
@@ -2249,7 +2311,7 @@ eschandle(uchar ascii)
|
|
||||||
return 0;
|
|
||||||
case 'D': /* IND -- Linefeed */
|
|
||||||
if (term.c.y == term.bot) {
|
|
||||||
- tscrollup(term.top, 1);
|
|
||||||
+ tscrollup(term.top, 1, 1);
|
|
||||||
} else {
|
|
||||||
tmoveto(term.c.x, term.c.y+1);
|
|
||||||
}
|
|
||||||
@@ -2262,7 +2324,7 @@ eschandle(uchar ascii)
|
|
||||||
break;
|
|
||||||
case 'M': /* RI -- Reverse index */
|
|
||||||
if (term.c.y == term.top) {
|
|
||||||
- tscrolldown(term.top, 1);
|
|
||||||
+ tscrolldown(term.top, 1, 1);
|
|
||||||
} else {
|
|
||||||
tmoveto(term.c.x, term.c.y-1);
|
|
||||||
}
|
|
||||||
@@ -2472,7 +2534,7 @@ twrite(const char *buf, int buflen, int show_ctrl)
|
|
||||||
void
|
|
||||||
tresize(int col, int row)
|
|
||||||
{
|
|
||||||
- int i;
|
|
||||||
+ int i, j;
|
|
||||||
int minrow = MIN(row, term.row);
|
|
||||||
int mincol = MIN(col, term.col);
|
|
||||||
int *bp;
|
|
||||||
@@ -2509,6 +2571,14 @@ tresize(int col, int row)
|
|
||||||
term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
|
|
||||||
term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
|
|
||||||
|
|
||||||
+ for (i = 0; i < HISTSIZE; i++) {
|
|
||||||
+ term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
|
|
||||||
+ for (j = mincol; j < col; j++) {
|
|
||||||
+ term.hist[i][j] = term.c.attr;
|
|
||||||
+ term.hist[i][j].u = ' ';
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* resize each row to new width, zero-pad if needed */
|
|
||||||
for (i = 0; i < minrow; i++) {
|
|
||||||
term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
|
|
||||||
@@ -2567,7 +2637,7 @@ drawregion(int x1, int y1, int x2, int y2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
term.dirty[y] = 0;
|
|
||||||
- xdrawline(term.line[y], x1, y, x2);
|
|
||||||
+ xdrawline(TLINE(y), x1, y, x2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2588,8 +2658,9 @@ draw(void)
|
|
||||||
cx--;
|
|
||||||
|
|
||||||
drawregion(0, 0, term.col, term.row);
|
|
||||||
- xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
|
|
||||||
- term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
|
|
||||||
+ if (term.scr == 0)
|
|
||||||
+ xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
|
|
||||||
+ term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
|
|
||||||
term.ocx = cx;
|
|
||||||
term.ocy = term.c.y;
|
|
||||||
xfinishdraw();
|
|
||||||
diff --git a/st.h b/st.h
|
|
||||||
index 3d351b6..f44e1d3 100644
|
|
||||||
--- a/st.h
|
|
||||||
+++ b/st.h
|
|
||||||
@@ -81,6 +81,8 @@ void die(const char *, ...);
|
|
||||||
void redraw(void);
|
|
||||||
void draw(void);
|
|
||||||
|
|
||||||
+void kscrolldown(const Arg *);
|
|
||||||
+void kscrollup(const Arg *);
|
|
||||||
void printscreen(const Arg *);
|
|
||||||
void printsel(const Arg *);
|
|
||||||
void sendbreak(const Arg *);
|
|
|
@ -1,13 +0,0 @@
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index ec1b576..4b3bf15 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -163,6 +163,8 @@ static uint forcemousemod = ShiftMask;
|
|
||||||
*/
|
|
||||||
static MouseShortcut mshortcuts[] = {
|
|
||||||
/* mask button function argument release */
|
|
||||||
+ { ShiftMask, Button4, kscrollup, {.i = 1} },
|
|
||||||
+ { ShiftMask, Button5, kscrolldown, {.i = 1} },
|
|
||||||
{ XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
|
|
||||||
{ XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
|
|
||||||
{ XK_ANY_MOD, Button5, ttysend, {.s = "\005"} },
|
|
|
@ -1,184 +0,0 @@
|
||||||
From 2752a599ee01305a435729bfacf43b1dde7cf0ef Mon Sep 17 00:00:00 2001
|
|
||||||
From: Benji Encalada Mora <benji@encalada.dev>
|
|
||||||
Date: Thu, 4 Jun 2020 00:41:10 -0500
|
|
||||||
Subject: [PATCH] fix: replace xfps and actionfps variables
|
|
||||||
|
|
||||||
---
|
|
||||||
config.def.h | 36 ++++++++++++++++++++++++
|
|
||||||
x.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++---
|
|
||||||
2 files changed, 110 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 6f05dce..9b99782 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -168,6 +168,42 @@ static unsigned int defaultattr = 11;
|
|
||||||
*/
|
|
||||||
static uint forcemousemod = ShiftMask;
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * Xresources preferences to load at startup
|
|
||||||
+ */
|
|
||||||
+ResourcePref resources[] = {
|
|
||||||
+ { "font", STRING, &font },
|
|
||||||
+ { "color0", STRING, &colorname[0] },
|
|
||||||
+ { "color1", STRING, &colorname[1] },
|
|
||||||
+ { "color2", STRING, &colorname[2] },
|
|
||||||
+ { "color3", STRING, &colorname[3] },
|
|
||||||
+ { "color4", STRING, &colorname[4] },
|
|
||||||
+ { "color5", STRING, &colorname[5] },
|
|
||||||
+ { "color6", STRING, &colorname[6] },
|
|
||||||
+ { "color7", STRING, &colorname[7] },
|
|
||||||
+ { "color8", STRING, &colorname[8] },
|
|
||||||
+ { "color9", STRING, &colorname[9] },
|
|
||||||
+ { "color10", STRING, &colorname[10] },
|
|
||||||
+ { "color11", STRING, &colorname[11] },
|
|
||||||
+ { "color12", STRING, &colorname[12] },
|
|
||||||
+ { "color13", STRING, &colorname[13] },
|
|
||||||
+ { "color14", STRING, &colorname[14] },
|
|
||||||
+ { "color15", STRING, &colorname[15] },
|
|
||||||
+ { "background", STRING, &colorname[256] },
|
|
||||||
+ { "foreground", STRING, &colorname[257] },
|
|
||||||
+ { "cursorColor", STRING, &colorname[258] },
|
|
||||||
+ { "termname", STRING, &termname },
|
|
||||||
+ { "shell", STRING, &shell },
|
|
||||||
+ { "minlatency", INTEGER, &minlatency },
|
|
||||||
+ { "maxlatency", INTEGER, &maxlatency },
|
|
||||||
+ { "blinktimeout", INTEGER, &blinktimeout },
|
|
||||||
+ { "bellvolume", INTEGER, &bellvolume },
|
|
||||||
+ { "tabspaces", INTEGER, &tabspaces },
|
|
||||||
+ { "borderpx", INTEGER, &borderpx },
|
|
||||||
+ { "cwscale", FLOAT, &cwscale },
|
|
||||||
+ { "chscale", FLOAT, &chscale },
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Internal mouse shortcuts.
|
|
||||||
* Beware that overloading Button1 will disable the selection.
|
|
||||||
diff --git a/x.c b/x.c
|
|
||||||
index 210f184..76f167f 100644
|
|
||||||
--- a/x.c
|
|
||||||
+++ b/x.c
|
|
||||||
@@ -14,6 +14,7 @@
|
|
||||||
#include <X11/keysym.h>
|
|
||||||
#include <X11/Xft/Xft.h>
|
|
||||||
#include <X11/XKBlib.h>
|
|
||||||
+#include <X11/Xresource.h>
|
|
||||||
|
|
||||||
char *argv0;
|
|
||||||
#include "arg.h"
|
|
||||||
@@ -45,6 +46,19 @@ typedef struct {
|
|
||||||
signed char appcursor; /* application cursor */
|
|
||||||
} Key;
|
|
||||||
|
|
||||||
+/* Xresources preferences */
|
|
||||||
+enum resource_type {
|
|
||||||
+ STRING = 0,
|
|
||||||
+ INTEGER = 1,
|
|
||||||
+ FLOAT = 2
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+typedef struct {
|
|
||||||
+ char *name;
|
|
||||||
+ enum resource_type type;
|
|
||||||
+ void *dst;
|
|
||||||
+} ResourcePref;
|
|
||||||
+
|
|
||||||
/* X modifiers */
|
|
||||||
#define XK_ANY_MOD UINT_MAX
|
|
||||||
#define XK_NO_MOD 0
|
|
||||||
@@ -828,8 +842,8 @@ xclear(int x1, int y1, int x2, int y2)
|
|
||||||
void
|
|
||||||
xhints(void)
|
|
||||||
{
|
|
||||||
- XClassHint class = {opt_name ? opt_name : termname,
|
|
||||||
- opt_class ? opt_class : termname};
|
|
||||||
+ XClassHint class = {opt_name ? opt_name : "st",
|
|
||||||
+ opt_class ? opt_class : "St"};
|
|
||||||
XWMHints wm = {.flags = InputHint, .input = 1};
|
|
||||||
XSizeHints *sizeh;
|
|
||||||
|
|
||||||
@@ -1104,8 +1118,6 @@ xinit(int cols, int rows)
|
|
||||||
pid_t thispid = getpid();
|
|
||||||
XColor xmousefg, xmousebg;
|
|
||||||
|
|
||||||
- if (!(xw.dpy = XOpenDisplay(NULL)))
|
|
||||||
- die("can't open display\n");
|
|
||||||
xw.scr = XDefaultScreen(xw.dpy);
|
|
||||||
xw.vis = XDefaultVisual(xw.dpy, xw.scr);
|
|
||||||
|
|
||||||
@@ -1964,6 +1976,59 @@ run(void)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+int
|
|
||||||
+resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
|
|
||||||
+{
|
|
||||||
+ char **sdst = dst;
|
|
||||||
+ int *idst = dst;
|
|
||||||
+ float *fdst = dst;
|
|
||||||
+
|
|
||||||
+ char fullname[256];
|
|
||||||
+ char fullclass[256];
|
|
||||||
+ char *type;
|
|
||||||
+ XrmValue ret;
|
|
||||||
+
|
|
||||||
+ snprintf(fullname, sizeof(fullname), "%s.%s",
|
|
||||||
+ opt_name ? opt_name : "st", name);
|
|
||||||
+ snprintf(fullclass, sizeof(fullclass), "%s.%s",
|
|
||||||
+ opt_class ? opt_class : "St", name);
|
|
||||||
+ fullname[sizeof(fullname) - 1] = fullclass[sizeof(fullclass) - 1] = '\0';
|
|
||||||
+
|
|
||||||
+ XrmGetResource(db, fullname, fullclass, &type, &ret);
|
|
||||||
+ if (ret.addr == NULL || strncmp("String", type, 64))
|
|
||||||
+ return 1;
|
|
||||||
+
|
|
||||||
+ switch (rtype) {
|
|
||||||
+ case STRING:
|
|
||||||
+ *sdst = ret.addr;
|
|
||||||
+ break;
|
|
||||||
+ case INTEGER:
|
|
||||||
+ *idst = strtoul(ret.addr, NULL, 10);
|
|
||||||
+ break;
|
|
||||||
+ case FLOAT:
|
|
||||||
+ *fdst = strtof(ret.addr, NULL);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+config_init(void)
|
|
||||||
+{
|
|
||||||
+ char *resm;
|
|
||||||
+ XrmDatabase db;
|
|
||||||
+ ResourcePref *p;
|
|
||||||
+
|
|
||||||
+ XrmInitialize();
|
|
||||||
+ resm = XResourceManagerString(xw.dpy);
|
|
||||||
+ if (!resm)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ db = XrmGetStringDatabase(resm);
|
|
||||||
+ for (p = resources; p < resources + LEN(resources); p++)
|
|
||||||
+ resource_load(db, p->name, p->type, p->dst);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
@@ -2037,6 +2102,11 @@ run:
|
|
||||||
|
|
||||||
setlocale(LC_CTYPE, "");
|
|
||||||
XSetLocaleModifiers("");
|
|
||||||
+
|
|
||||||
+ if(!(xw.dpy = XOpenDisplay(NULL)))
|
|
||||||
+ die("Can't open display\n");
|
|
||||||
+
|
|
||||||
+ config_init();
|
|
||||||
cols = MAX(cols, 1);
|
|
||||||
rows = MAX(rows, 1);
|
|
||||||
tnew(cols, rows);
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
|
@ -1,307 +0,0 @@
|
||||||
diff --git a/Makefile b/Makefile
|
|
||||||
index 470ac86..38240da 100644
|
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -4,7 +4,7 @@
|
|
||||||
|
|
||||||
include config.mk
|
|
||||||
|
|
||||||
-SRC = st.c x.c
|
|
||||||
+SRC = st.c x.c hb.c
|
|
||||||
OBJ = $(SRC:.c=.o)
|
|
||||||
|
|
||||||
all: options st
|
|
||||||
@@ -22,7 +22,8 @@ config.h:
|
|
||||||
$(CC) $(STCFLAGS) -c $<
|
|
||||||
|
|
||||||
st.o: config.h st.h win.h
|
|
||||||
-x.o: arg.h config.h st.h win.h
|
|
||||||
+x.o: arg.h config.h st.h win.h hb.h
|
|
||||||
+hb.o: st.h
|
|
||||||
|
|
||||||
$(OBJ): config.h config.mk
|
|
||||||
|
|
||||||
diff --git a/config.mk b/config.mk
|
|
||||||
index beafc35..3df5c83 100644
|
|
||||||
--- a/config.mk
|
|
||||||
+++ b/config.mk
|
|
||||||
@@ -15,10 +15,12 @@ PKG_CONFIG = pkg-config
|
|
||||||
# includes and libs
|
|
||||||
INCS = -I$(X11INC) \
|
|
||||||
`$(PKG_CONFIG) --cflags fontconfig` \
|
|
||||||
- `$(PKG_CONFIG) --cflags freetype2`
|
|
||||||
+ `$(PKG_CONFIG) --cflags freetype2` \
|
|
||||||
+ `$(PKG_CONFIG) --cflags harfbuzz`
|
|
||||||
LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \
|
|
||||||
`$(PKG_CONFIG) --libs fontconfig` \
|
|
||||||
- `$(PKG_CONFIG) --libs freetype2`
|
|
||||||
+ `$(PKG_CONFIG) --libs freetype2` \
|
|
||||||
+ `$(PKG_CONFIG) --libs harfbuzz`
|
|
||||||
|
|
||||||
# flags
|
|
||||||
STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
|
|
||||||
diff --git a/hb.c b/hb.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..7df2828
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/hb.c
|
|
||||||
@@ -0,0 +1,136 @@
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <math.h>
|
|
||||||
+#include <X11/Xft/Xft.h>
|
|
||||||
+#include <hb.h>
|
|
||||||
+#include <hb-ft.h>
|
|
||||||
+
|
|
||||||
+#include "st.h"
|
|
||||||
+
|
|
||||||
+void hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length);
|
|
||||||
+hb_font_t *hbfindfont(XftFont *match);
|
|
||||||
+
|
|
||||||
+typedef struct {
|
|
||||||
+ XftFont *match;
|
|
||||||
+ hb_font_t *font;
|
|
||||||
+} HbFontMatch;
|
|
||||||
+
|
|
||||||
+static int hbfontslen = 0;
|
|
||||||
+static HbFontMatch *hbfontcache = NULL;
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+hbunloadfonts()
|
|
||||||
+{
|
|
||||||
+ for (int i = 0; i < hbfontslen; i++) {
|
|
||||||
+ hb_font_destroy(hbfontcache[i].font);
|
|
||||||
+ XftUnlockFace(hbfontcache[i].match);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (hbfontcache != NULL) {
|
|
||||||
+ free(hbfontcache);
|
|
||||||
+ hbfontcache = NULL;
|
|
||||||
+ }
|
|
||||||
+ hbfontslen = 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+hb_font_t *
|
|
||||||
+hbfindfont(XftFont *match)
|
|
||||||
+{
|
|
||||||
+ for (int i = 0; i < hbfontslen; i++) {
|
|
||||||
+ if (hbfontcache[i].match == match)
|
|
||||||
+ return hbfontcache[i].font;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Font not found in cache, caching it now. */
|
|
||||||
+ hbfontcache = realloc(hbfontcache, sizeof(HbFontMatch) * (hbfontslen + 1));
|
|
||||||
+ FT_Face face = XftLockFace(match);
|
|
||||||
+ hb_font_t *font = hb_ft_font_create(face, NULL);
|
|
||||||
+ if (font == NULL)
|
|
||||||
+ die("Failed to load Harfbuzz font.");
|
|
||||||
+
|
|
||||||
+ hbfontcache[hbfontslen].match = match;
|
|
||||||
+ hbfontcache[hbfontslen].font = font;
|
|
||||||
+ hbfontslen += 1;
|
|
||||||
+
|
|
||||||
+ return font;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+hbtransform(XftGlyphFontSpec *specs, const Glyph *glyphs, size_t len, int x, int y)
|
|
||||||
+{
|
|
||||||
+ int start = 0, length = 1, gstart = 0;
|
|
||||||
+ hb_codepoint_t *codepoints = calloc(len, sizeof(hb_codepoint_t));
|
|
||||||
+
|
|
||||||
+ for (int idx = 1, specidx = 1; idx < len; idx++) {
|
|
||||||
+ if (glyphs[idx].mode & ATTR_WDUMMY) {
|
|
||||||
+ length += 1;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (specs[specidx].font != specs[start].font || ATTRCMP(glyphs[gstart], glyphs[idx]) || selected(x + idx, y) != selected(x + gstart, y)) {
|
|
||||||
+ hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length);
|
|
||||||
+
|
|
||||||
+ /* Reset the sequence. */
|
|
||||||
+ length = 1;
|
|
||||||
+ start = specidx;
|
|
||||||
+ gstart = idx;
|
|
||||||
+ } else {
|
|
||||||
+ length += 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ specidx++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* EOL. */
|
|
||||||
+ hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length);
|
|
||||||
+
|
|
||||||
+ /* Apply the transformation to glyph specs. */
|
|
||||||
+ for (int i = 0, specidx = 0; i < len; i++) {
|
|
||||||
+ if (glyphs[i].mode & ATTR_WDUMMY)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ if (codepoints[i] != specs[specidx].glyph)
|
|
||||||
+ ((Glyph *)glyphs)[i].mode |= ATTR_LIGA;
|
|
||||||
+
|
|
||||||
+ specs[specidx++].glyph = codepoints[i];
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ free(codepoints);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length)
|
|
||||||
+{
|
|
||||||
+ hb_font_t *font = hbfindfont(xfont);
|
|
||||||
+ if (font == NULL)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ Rune rune;
|
|
||||||
+ ushort mode = USHRT_MAX;
|
|
||||||
+ hb_buffer_t *buffer = hb_buffer_create();
|
|
||||||
+ hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
|
|
||||||
+
|
|
||||||
+ /* Fill buffer with codepoints. */
|
|
||||||
+ for (int i = start; i < (start+length); i++) {
|
|
||||||
+ rune = string[i].u;
|
|
||||||
+ mode = string[i].mode;
|
|
||||||
+ if (mode & ATTR_WDUMMY)
|
|
||||||
+ rune = 0x0020;
|
|
||||||
+ hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Shape the segment. */
|
|
||||||
+ hb_shape(font, buffer, NULL, 0);
|
|
||||||
+
|
|
||||||
+ /* Get new glyph info. */
|
|
||||||
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, NULL);
|
|
||||||
+
|
|
||||||
+ /* Write new codepoints. */
|
|
||||||
+ for (int i = 0; i < length; i++) {
|
|
||||||
+ hb_codepoint_t gid = info[i].codepoint;
|
|
||||||
+ codepoints[start+i] = gid;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Cleanup. */
|
|
||||||
+ hb_buffer_destroy(buffer);
|
|
||||||
+}
|
|
||||||
diff --git a/hb.h b/hb.h
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..b3e02d0
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/hb.h
|
|
||||||
@@ -0,0 +1,7 @@
|
|
||||||
+#include <X11/Xft/Xft.h>
|
|
||||||
+#include <hb.h>
|
|
||||||
+#include <hb-ft.h>
|
|
||||||
+
|
|
||||||
+void hbunloadfonts();
|
|
||||||
+void hbtransform(XftGlyphFontSpec *, const Glyph *, size_t, int, int);
|
|
||||||
+
|
|
||||||
diff --git a/st.c b/st.c
|
|
||||||
index 641edc0..14a0b66 100644
|
|
||||||
--- a/st.c
|
|
||||||
+++ b/st.c
|
|
||||||
@@ -2670,7 +2670,8 @@ draw(void)
|
|
||||||
drawregion(0, 0, term.col, term.row);
|
|
||||||
if (term.scr == 0)
|
|
||||||
xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
|
|
||||||
- term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
|
|
||||||
+ term.ocx, term.ocy, term.line[term.ocy][term.ocx],
|
|
||||||
+ term.line[term.ocy], term.col);
|
|
||||||
term.ocx = cx;
|
|
||||||
term.ocy = term.c.y;
|
|
||||||
xfinishdraw();
|
|
||||||
diff --git a/st.h b/st.h
|
|
||||||
index b9a4eeb..b49b84a 100644
|
|
||||||
--- a/st.h
|
|
||||||
+++ b/st.h
|
|
||||||
@@ -11,7 +11,8 @@
|
|
||||||
#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
|
|
||||||
#define DEFAULT(a, b) (a) = (a) ? (a) : (b)
|
|
||||||
#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
|
|
||||||
-#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \
|
|
||||||
+#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP) & (~ATTR_LIGA)) != ((b).mode & (~ATTR_WRAP) & (~ATTR_LIGA)) || \
|
|
||||||
+ (a).fg != (b).fg || \
|
|
||||||
(a).bg != (b).bg)
|
|
||||||
#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \
|
|
||||||
(t1.tv_nsec-t2.tv_nsec)/1E6)
|
|
||||||
@@ -33,6 +34,7 @@ enum glyph_attribute {
|
|
||||||
ATTR_WRAP = 1 << 8,
|
|
||||||
ATTR_WIDE = 1 << 9,
|
|
||||||
ATTR_WDUMMY = 1 << 10,
|
|
||||||
+ ATTR_LIGA = 1 << 11,
|
|
||||||
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
|
|
||||||
};
|
|
||||||
|
|
||||||
diff --git a/win.h b/win.h
|
|
||||||
index a6ef1b9..bc0d180 100644
|
|
||||||
--- a/win.h
|
|
||||||
+++ b/win.h
|
|
||||||
@@ -25,7 +25,7 @@ enum win_mode {
|
|
||||||
|
|
||||||
void xbell(void);
|
|
||||||
void xclipcopy(void);
|
|
||||||
-void xdrawcursor(int, int, Glyph, int, int, Glyph);
|
|
||||||
+void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
|
|
||||||
void xdrawline(Line, int, int, int);
|
|
||||||
void xfinishdraw(void);
|
|
||||||
void xloadcols(void);
|
|
||||||
diff --git a/x.c b/x.c
|
|
||||||
index e5f1737..3334a83 100644
|
|
||||||
--- a/x.c
|
|
||||||
+++ b/x.c
|
|
||||||
@@ -19,6 +19,7 @@ char *argv0;
|
|
||||||
#include "arg.h"
|
|
||||||
#include "st.h"
|
|
||||||
#include "win.h"
|
|
||||||
+#include "hb.h"
|
|
||||||
|
|
||||||
/* types used in config.h */
|
|
||||||
typedef struct {
|
|
||||||
@@ -1031,6 +1032,9 @@ xunloadfont(Font *f)
|
|
||||||
void
|
|
||||||
xunloadfonts(void)
|
|
||||||
{
|
|
||||||
+ /* Clear Harfbuzz font cache. */
|
|
||||||
+ hbunloadfonts();
|
|
||||||
+
|
|
||||||
/* Free the loaded fonts in the font cache. */
|
|
||||||
while (frclen > 0)
|
|
||||||
XftFontClose(xw.dpy, frc[--frclen].font);
|
|
||||||
@@ -1229,7 +1233,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
|
|
||||||
mode = glyphs[i].mode;
|
|
||||||
|
|
||||||
/* Skip dummy wide-character spacing. */
|
|
||||||
- if (mode == ATTR_WDUMMY)
|
|
||||||
+ if (mode & ATTR_WDUMMY)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Determine font for glyph if different from previous glyph. */
|
|
||||||
@@ -1336,6 +1340,9 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
|
|
||||||
numspecs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Harfbuzz transformation for ligatures. */
|
|
||||||
+ hbtransform(specs, glyphs, len, x, y);
|
|
||||||
+
|
|
||||||
return numspecs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1485,14 +1492,17 @@ xdrawglyph(Glyph g, int x, int y)
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
-xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
|
|
||||||
+xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len)
|
|
||||||
{
|
|
||||||
Color drawcol;
|
|
||||||
|
|
||||||
/* remove the old cursor */
|
|
||||||
if (selected(ox, oy))
|
|
||||||
og.mode ^= ATTR_REVERSE;
|
|
||||||
- xdrawglyph(og, ox, oy);
|
|
||||||
+
|
|
||||||
+ /* Redraw the line where cursor was previously.
|
|
||||||
+ * It will restore the ligatures broken by the cursor. */
|
|
||||||
+ xdrawline(line, 0, oy, len);
|
|
||||||
|
|
||||||
if (IS_SET(MODE_HIDE))
|
|
||||||
return;
|
|
283
st/st.c
283
st/st.c
|
@ -35,7 +35,6 @@
|
||||||
#define ESC_ARG_SIZ 16
|
#define ESC_ARG_SIZ 16
|
||||||
#define STR_BUF_SIZ ESC_BUF_SIZ
|
#define STR_BUF_SIZ ESC_BUF_SIZ
|
||||||
#define STR_ARG_SIZ ESC_ARG_SIZ
|
#define STR_ARG_SIZ ESC_ARG_SIZ
|
||||||
#define HISTSIZE 2000
|
|
||||||
|
|
||||||
/* macros */
|
/* macros */
|
||||||
#define IS_SET(flag) ((term.mode & (flag)) != 0)
|
#define IS_SET(flag) ((term.mode & (flag)) != 0)
|
||||||
|
@ -43,9 +42,6 @@
|
||||||
#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f))
|
#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f))
|
||||||
#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
|
#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
|
||||||
#define ISDELIM(u) (u && wcschr(worddelimiters, u))
|
#define ISDELIM(u) (u && wcschr(worddelimiters, u))
|
||||||
#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \
|
|
||||||
term.scr + HISTSIZE + 1) % HISTSIZE] : \
|
|
||||||
term.line[(y) - term.scr])
|
|
||||||
|
|
||||||
enum term_mode {
|
enum term_mode {
|
||||||
MODE_WRAP = 1 << 0,
|
MODE_WRAP = 1 << 0,
|
||||||
|
@ -119,9 +115,6 @@ typedef struct {
|
||||||
int col; /* nb col */
|
int col; /* nb col */
|
||||||
Line *line; /* screen */
|
Line *line; /* screen */
|
||||||
Line *alt; /* alternate screen */
|
Line *alt; /* alternate screen */
|
||||||
Line hist[HISTSIZE]; /* history buffer */
|
|
||||||
int histi; /* history index */
|
|
||||||
int scr; /* scroll back */
|
|
||||||
int *dirty; /* dirtyness of lines */
|
int *dirty; /* dirtyness of lines */
|
||||||
TCursor c; /* cursor */
|
TCursor c; /* cursor */
|
||||||
int ocx; /* old cursor col */
|
int ocx; /* old cursor col */
|
||||||
|
@ -168,6 +161,7 @@ static void csidump(void);
|
||||||
static void csihandle(void);
|
static void csihandle(void);
|
||||||
static void csiparse(void);
|
static void csiparse(void);
|
||||||
static void csireset(void);
|
static void csireset(void);
|
||||||
|
static void osc_color_response(int, int, int);
|
||||||
static int eschandle(uchar);
|
static int eschandle(uchar);
|
||||||
static void strdump(void);
|
static void strdump(void);
|
||||||
static void strhandle(void);
|
static void strhandle(void);
|
||||||
|
@ -191,20 +185,20 @@ static void tnewline(int);
|
||||||
static void tputtab(int);
|
static void tputtab(int);
|
||||||
static void tputc(Rune);
|
static void tputc(Rune);
|
||||||
static void treset(void);
|
static void treset(void);
|
||||||
static void tscrollup(int, int, int);
|
static void tscrollup(int, int);
|
||||||
static void tscrolldown(int, int, int);
|
static void tscrolldown(int, int);
|
||||||
static void tsetattr(int *, int);
|
static void tsetattr(const int *, int);
|
||||||
static void tsetchar(Rune, Glyph *, int, int);
|
static void tsetchar(Rune, const Glyph *, int, int);
|
||||||
static void tsetdirt(int, int);
|
static void tsetdirt(int, int);
|
||||||
static void tsetscroll(int, int);
|
static void tsetscroll(int, int);
|
||||||
static void tswapscreen(void);
|
static void tswapscreen(void);
|
||||||
static void tsetmode(int, int, int *, int);
|
static void tsetmode(int, int, const int *, int);
|
||||||
static int twrite(const char *, int, int);
|
static int twrite(const char *, int, int);
|
||||||
static void tfulldirt(void);
|
static void tfulldirt(void);
|
||||||
static void tcontrolcode(uchar );
|
static void tcontrolcode(uchar );
|
||||||
static void tdectest(char );
|
static void tdectest(char );
|
||||||
static void tdefutf8(char);
|
static void tdefutf8(char);
|
||||||
static int32_t tdefcolor(int *, int *, int);
|
static int32_t tdefcolor(const int *, int *, int);
|
||||||
static void tdeftran(char);
|
static void tdeftran(char);
|
||||||
static void tstrsequence(uchar);
|
static void tstrsequence(uchar);
|
||||||
|
|
||||||
|
@ -233,10 +227,10 @@ static int iofd = 1;
|
||||||
static int cmdfd;
|
static int cmdfd;
|
||||||
static pid_t pid;
|
static pid_t pid;
|
||||||
|
|
||||||
static uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
|
static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
|
||||||
static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
|
static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
|
||||||
static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
|
static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
|
||||||
static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
xwrite(int fd, const char *s, size_t len)
|
xwrite(int fd, const char *s, size_t len)
|
||||||
|
@ -276,12 +270,14 @@ xrealloc(void *p, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
xstrdup(char *s)
|
xstrdup(const char *s)
|
||||||
{
|
{
|
||||||
if ((s = strdup(s)) == NULL)
|
char *p;
|
||||||
|
|
||||||
|
if ((p = strdup(s)) == NULL)
|
||||||
die("strdup: %s\n", strerror(errno));
|
die("strdup: %s\n", strerror(errno));
|
||||||
|
|
||||||
return s;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
@ -354,25 +350,10 @@ utf8validate(Rune *u, size_t i)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char base64_digits[] = {
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0,
|
|
||||||
63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1,
|
|
||||||
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
|
||||||
22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34,
|
|
||||||
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
char
|
char
|
||||||
base64dec_getc(const char **src)
|
base64dec_getc(const char **src)
|
||||||
{
|
{
|
||||||
while (**src && !isprint(**src))
|
while (**src && !isprint((unsigned char)**src))
|
||||||
(*src)++;
|
(*src)++;
|
||||||
return **src ? *((*src)++) : '='; /* emulate padding if string ends */
|
return **src ? *((*src)++) : '='; /* emulate padding if string ends */
|
||||||
}
|
}
|
||||||
|
@ -382,6 +363,13 @@ base64dec(const char *src)
|
||||||
{
|
{
|
||||||
size_t in_len = strlen(src);
|
size_t in_len = strlen(src);
|
||||||
char *result, *dst;
|
char *result, *dst;
|
||||||
|
static const char base64_digits[256] = {
|
||||||
|
[43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
|
||||||
|
0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||||
|
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0,
|
||||||
|
0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||||
|
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
|
||||||
|
};
|
||||||
|
|
||||||
if (in_len % 4)
|
if (in_len % 4)
|
||||||
in_len += 4 - (in_len % 4);
|
in_len += 4 - (in_len % 4);
|
||||||
|
@ -421,10 +409,10 @@ tlinelen(int y)
|
||||||
{
|
{
|
||||||
int i = term.col;
|
int i = term.col;
|
||||||
|
|
||||||
if (TLINE(y)[i - 1].mode & ATTR_WRAP)
|
if (term.line[y][i - 1].mode & ATTR_WRAP)
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
while (i > 0 && TLINE(y)[i - 1].u == ' ')
|
while (i > 0 && term.line[y][i - 1].u == ' ')
|
||||||
--i;
|
--i;
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
@ -525,7 +513,7 @@ selsnap(int *x, int *y, int direction)
|
||||||
{
|
{
|
||||||
int newx, newy, xt, yt;
|
int newx, newy, xt, yt;
|
||||||
int delim, prevdelim;
|
int delim, prevdelim;
|
||||||
Glyph *gp, *prevgp;
|
const Glyph *gp, *prevgp;
|
||||||
|
|
||||||
switch (sel.snap) {
|
switch (sel.snap) {
|
||||||
case SNAP_WORD:
|
case SNAP_WORD:
|
||||||
|
@ -533,7 +521,7 @@ selsnap(int *x, int *y, int direction)
|
||||||
* Snap around if the word wraps around at the end or
|
* Snap around if the word wraps around at the end or
|
||||||
* beginning of a line.
|
* beginning of a line.
|
||||||
*/
|
*/
|
||||||
prevgp = &TLINE(*y)[*x];
|
prevgp = &term.line[*y][*x];
|
||||||
prevdelim = ISDELIM(prevgp->u);
|
prevdelim = ISDELIM(prevgp->u);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
newx = *x + direction;
|
newx = *x + direction;
|
||||||
|
@ -548,14 +536,14 @@ selsnap(int *x, int *y, int direction)
|
||||||
yt = *y, xt = *x;
|
yt = *y, xt = *x;
|
||||||
else
|
else
|
||||||
yt = newy, xt = newx;
|
yt = newy, xt = newx;
|
||||||
if (!(TLINE(yt)[xt].mode & ATTR_WRAP))
|
if (!(term.line[yt][xt].mode & ATTR_WRAP))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newx >= tlinelen(newy))
|
if (newx >= tlinelen(newy))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
gp = &TLINE(newy)[newx];
|
gp = &term.line[newy][newx];
|
||||||
delim = ISDELIM(gp->u);
|
delim = ISDELIM(gp->u);
|
||||||
if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
|
if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
|
||||||
|| (delim && gp->u != prevgp->u)))
|
|| (delim && gp->u != prevgp->u)))
|
||||||
|
@ -576,14 +564,14 @@ selsnap(int *x, int *y, int direction)
|
||||||
*x = (direction < 0) ? 0 : term.col - 1;
|
*x = (direction < 0) ? 0 : term.col - 1;
|
||||||
if (direction < 0) {
|
if (direction < 0) {
|
||||||
for (; *y > 0; *y += direction) {
|
for (; *y > 0; *y += direction) {
|
||||||
if (!(TLINE(*y-1)[term.col-1].mode
|
if (!(term.line[*y-1][term.col-1].mode
|
||||||
& ATTR_WRAP)) {
|
& ATTR_WRAP)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (direction > 0) {
|
} else if (direction > 0) {
|
||||||
for (; *y < term.row-1; *y += direction) {
|
for (; *y < term.row-1; *y += direction) {
|
||||||
if (!(TLINE(*y)[term.col-1].mode
|
if (!(term.line[*y][term.col-1].mode
|
||||||
& ATTR_WRAP)) {
|
& ATTR_WRAP)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -598,7 +586,7 @@ getsel(void)
|
||||||
{
|
{
|
||||||
char *str, *ptr;
|
char *str, *ptr;
|
||||||
int y, bufsize, lastx, linelen;
|
int y, bufsize, lastx, linelen;
|
||||||
Glyph *gp, *last;
|
const Glyph *gp, *last;
|
||||||
|
|
||||||
if (sel.ob.x == -1)
|
if (sel.ob.x == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -614,13 +602,13 @@ getsel(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sel.type == SEL_RECTANGULAR) {
|
if (sel.type == SEL_RECTANGULAR) {
|
||||||
gp = &TLINE(y)[sel.nb.x];
|
gp = &term.line[y][sel.nb.x];
|
||||||
lastx = sel.ne.x;
|
lastx = sel.ne.x;
|
||||||
} else {
|
} else {
|
||||||
gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
|
gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
|
||||||
lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
|
lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
|
||||||
}
|
}
|
||||||
last = &TLINE(y)[MIN(lastx, linelen-1)];
|
last = &term.line[y][MIN(lastx, linelen-1)];
|
||||||
while (last >= gp && last->u == ' ')
|
while (last >= gp && last->u == ' ')
|
||||||
--last;
|
--last;
|
||||||
|
|
||||||
|
@ -765,7 +753,7 @@ stty(char **args)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ttynew(char *line, char *cmd, char *out, char **args)
|
ttynew(const char *line, char *cmd, const char *out, char **args)
|
||||||
{
|
{
|
||||||
int m, s;
|
int m, s;
|
||||||
|
|
||||||
|
@ -798,14 +786,15 @@ ttynew(char *line, char *cmd, char *out, char **args)
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
close(iofd);
|
close(iofd);
|
||||||
|
close(m);
|
||||||
setsid(); /* create a new process group */
|
setsid(); /* create a new process group */
|
||||||
dup2(s, 0);
|
dup2(s, 0);
|
||||||
dup2(s, 1);
|
dup2(s, 1);
|
||||||
dup2(s, 2);
|
dup2(s, 2);
|
||||||
if (ioctl(s, TIOCSCTTY, NULL) < 0)
|
if (ioctl(s, TIOCSCTTY, NULL) < 0)
|
||||||
die("ioctl TIOCSCTTY failed: %s\n", strerror(errno));
|
die("ioctl TIOCSCTTY failed: %s\n", strerror(errno));
|
||||||
close(s);
|
if (s > 2)
|
||||||
close(m);
|
close(s);
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
if (pledge("stdio getpw proc exec", NULL) == -1)
|
if (pledge("stdio getpw proc exec", NULL) == -1)
|
||||||
die("pledge\n");
|
die("pledge\n");
|
||||||
|
@ -855,9 +844,6 @@ void
|
||||||
ttywrite(const char *s, size_t n, int may_echo)
|
ttywrite(const char *s, size_t n, int may_echo)
|
||||||
{
|
{
|
||||||
const char *next;
|
const char *next;
|
||||||
Arg arg = (Arg) { .i = term.scr };
|
|
||||||
|
|
||||||
kscrolldown(&arg);
|
|
||||||
|
|
||||||
if (may_echo && IS_SET(MODE_ECHO))
|
if (may_echo && IS_SET(MODE_ECHO))
|
||||||
twrite(s, n, 1);
|
twrite(s, n, 1);
|
||||||
|
@ -953,7 +939,7 @@ ttyresize(int tw, int th)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ttyhangup()
|
ttyhangup(void)
|
||||||
{
|
{
|
||||||
/* Send SIGHUP to shell */
|
/* Send SIGHUP to shell */
|
||||||
kill(pid, SIGHUP);
|
kill(pid, SIGHUP);
|
||||||
|
@ -1069,53 +1055,13 @@ tswapscreen(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
kscrolldown(const Arg* a)
|
tscrolldown(int orig, int n)
|
||||||
{
|
|
||||||
int n = a->i;
|
|
||||||
|
|
||||||
if (n < 0)
|
|
||||||
n = term.row + n;
|
|
||||||
|
|
||||||
if (n > term.scr)
|
|
||||||
n = term.scr;
|
|
||||||
|
|
||||||
if (term.scr > 0) {
|
|
||||||
term.scr -= n;
|
|
||||||
selscroll(0, -n);
|
|
||||||
tfulldirt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
kscrollup(const Arg* a)
|
|
||||||
{
|
|
||||||
int n = a->i;
|
|
||||||
|
|
||||||
if (n < 0)
|
|
||||||
n = term.row + n;
|
|
||||||
|
|
||||||
if (term.scr <= HISTSIZE-n) {
|
|
||||||
term.scr += n;
|
|
||||||
selscroll(0, n);
|
|
||||||
tfulldirt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
tscrolldown(int orig, int n, int copyhist)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
Line temp;
|
Line temp;
|
||||||
|
|
||||||
LIMIT(n, 0, term.bot-orig+1);
|
LIMIT(n, 0, term.bot-orig+1);
|
||||||
|
|
||||||
if (copyhist) {
|
|
||||||
term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE;
|
|
||||||
temp = term.hist[term.histi];
|
|
||||||
term.hist[term.histi] = term.line[term.bot];
|
|
||||||
term.line[term.bot] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsetdirt(orig, term.bot-n);
|
tsetdirt(orig, term.bot-n);
|
||||||
tclearregion(0, term.bot-n+1, term.col-1, term.bot);
|
tclearregion(0, term.bot-n+1, term.col-1, term.bot);
|
||||||
|
|
||||||
|
@ -1125,28 +1071,17 @@ tscrolldown(int orig, int n, int copyhist)
|
||||||
term.line[i-n] = temp;
|
term.line[i-n] = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (term.scr == 0)
|
selscroll(orig, n);
|
||||||
selscroll(orig, n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tscrollup(int orig, int n, int copyhist)
|
tscrollup(int orig, int n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
Line temp;
|
Line temp;
|
||||||
|
|
||||||
LIMIT(n, 0, term.bot-orig+1);
|
LIMIT(n, 0, term.bot-orig+1);
|
||||||
|
|
||||||
if (copyhist) {
|
|
||||||
term.histi = (term.histi + 1) % HISTSIZE;
|
|
||||||
temp = term.hist[term.histi];
|
|
||||||
term.hist[term.histi] = term.line[orig];
|
|
||||||
term.line[orig] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (term.scr > 0 && term.scr < HISTSIZE)
|
|
||||||
term.scr = MIN(term.scr + n, HISTSIZE-1);
|
|
||||||
|
|
||||||
tclearregion(0, orig, term.col-1, orig+n-1);
|
tclearregion(0, orig, term.col-1, orig+n-1);
|
||||||
tsetdirt(orig+n, term.bot);
|
tsetdirt(orig+n, term.bot);
|
||||||
|
|
||||||
|
@ -1156,8 +1091,7 @@ tscrollup(int orig, int n, int copyhist)
|
||||||
term.line[i+n] = temp;
|
term.line[i+n] = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (term.scr == 0)
|
selscroll(orig, -n);
|
||||||
selscroll(orig, -n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1186,7 +1120,7 @@ tnewline(int first_col)
|
||||||
int y = term.c.y;
|
int y = term.c.y;
|
||||||
|
|
||||||
if (y == term.bot) {
|
if (y == term.bot) {
|
||||||
tscrollup(term.top, 1, 1);
|
tscrollup(term.top, 1);
|
||||||
} else {
|
} else {
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
@ -1248,9 +1182,9 @@ tmoveto(int x, int y)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tsetchar(Rune u, Glyph *attr, int x, int y)
|
tsetchar(Rune u, const Glyph *attr, int x, int y)
|
||||||
{
|
{
|
||||||
static char *vt100_0[62] = { /* 0x41 - 0x7e */
|
static const char *vt100_0[62] = { /* 0x41 - 0x7e */
|
||||||
"↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */
|
"↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
|
0, 0, 0, 0, 0, 0, 0, 0, /* H - O */
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, /* P - W */
|
0, 0, 0, 0, 0, 0, 0, 0, /* P - W */
|
||||||
|
@ -1351,18 +1285,18 @@ void
|
||||||
tinsertblankline(int n)
|
tinsertblankline(int n)
|
||||||
{
|
{
|
||||||
if (BETWEEN(term.c.y, term.top, term.bot))
|
if (BETWEEN(term.c.y, term.top, term.bot))
|
||||||
tscrolldown(term.c.y, n, 0);
|
tscrolldown(term.c.y, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tdeleteline(int n)
|
tdeleteline(int n)
|
||||||
{
|
{
|
||||||
if (BETWEEN(term.c.y, term.top, term.bot))
|
if (BETWEEN(term.c.y, term.top, term.bot))
|
||||||
tscrollup(term.c.y, n, 0);
|
tscrollup(term.c.y, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
tdefcolor(int *attr, int *npar, int l)
|
tdefcolor(const int *attr, int *npar, int l)
|
||||||
{
|
{
|
||||||
int32_t idx = -1;
|
int32_t idx = -1;
|
||||||
uint r, g, b;
|
uint r, g, b;
|
||||||
|
@ -1412,7 +1346,7 @@ tdefcolor(int *attr, int *npar, int l)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tsetattr(int *attr, int l)
|
tsetattr(const int *attr, int l)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int32_t idx;
|
int32_t idx;
|
||||||
|
@ -1530,9 +1464,9 @@ tsetscroll(int t, int b)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tsetmode(int priv, int set, int *args, int narg)
|
tsetmode(int priv, int set, const int *args, int narg)
|
||||||
{
|
{
|
||||||
int alt, *lim;
|
int alt; const int *lim;
|
||||||
|
|
||||||
for (lim = args + narg; args < lim; ++args) {
|
for (lim = args + narg; args < lim; ++args) {
|
||||||
if (priv) {
|
if (priv) {
|
||||||
|
@ -1795,11 +1729,11 @@ csihandle(void)
|
||||||
break;
|
break;
|
||||||
case 'S': /* SU -- Scroll <n> line up */
|
case 'S': /* SU -- Scroll <n> line up */
|
||||||
DEFAULT(csiescseq.arg[0], 1);
|
DEFAULT(csiescseq.arg[0], 1);
|
||||||
tscrollup(term.top, csiescseq.arg[0], 0);
|
tscrollup(term.top, csiescseq.arg[0]);
|
||||||
break;
|
break;
|
||||||
case 'T': /* SD -- Scroll <n> line down */
|
case 'T': /* SD -- Scroll <n> line down */
|
||||||
DEFAULT(csiescseq.arg[0], 1);
|
DEFAULT(csiescseq.arg[0], 1);
|
||||||
tscrolldown(term.top, csiescseq.arg[0], 0);
|
tscrolldown(term.top, csiescseq.arg[0]);
|
||||||
break;
|
break;
|
||||||
case 'L': /* IL -- Insert <n> blank lines */
|
case 'L': /* IL -- Insert <n> blank lines */
|
||||||
DEFAULT(csiescseq.arg[0], 1);
|
DEFAULT(csiescseq.arg[0], 1);
|
||||||
|
@ -1835,11 +1769,18 @@ csihandle(void)
|
||||||
case 'm': /* SGR -- Terminal attribute (color) */
|
case 'm': /* SGR -- Terminal attribute (color) */
|
||||||
tsetattr(csiescseq.arg, csiescseq.narg);
|
tsetattr(csiescseq.arg, csiescseq.narg);
|
||||||
break;
|
break;
|
||||||
case 'n': /* DSR – Device Status Report (cursor position) */
|
case 'n': /* DSR -- Device Status Report */
|
||||||
if (csiescseq.arg[0] == 6) {
|
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",
|
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);
|
ttywrite(buf, len, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto unknown;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'r': /* DECSTBM -- Set Scrolling Region */
|
case 'r': /* DECSTBM -- Set Scrolling Region */
|
||||||
|
@ -1901,11 +1842,41 @@ csireset(void)
|
||||||
memset(&csiescseq, 0, sizeof(csiescseq));
|
memset(&csiescseq, 0, sizeof(csiescseq));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
osc_color_response(int num, int index, int is_osc4)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
char buf[32];
|
||||||
|
unsigned char r, g, b;
|
||||||
|
|
||||||
|
if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) {
|
||||||
|
fprintf(stderr, "erresc: failed to fetch %s color %d\n",
|
||||||
|
is_osc4 ? "osc4" : "osc",
|
||||||
|
is_osc4 ? num : index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
|
||||||
|
is_osc4 ? "4;" : "", num, r, r, g, g, b, b);
|
||||||
|
if (n < 0 || n >= sizeof(buf)) {
|
||||||
|
fprintf(stderr, "error: %s while printing %s response\n",
|
||||||
|
n < 0 ? "snprintf failed" : "truncation occurred",
|
||||||
|
is_osc4 ? "osc4" : "osc");
|
||||||
|
} else {
|
||||||
|
ttywrite(buf, n, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
strhandle(void)
|
strhandle(void)
|
||||||
{
|
{
|
||||||
char *p = NULL, *dec;
|
char *p = NULL, *dec;
|
||||||
int j, narg, par;
|
int j, narg, par;
|
||||||
|
const struct { int idx; char *str; } osc_table[] = {
|
||||||
|
{ defaultfg, "foreground" },
|
||||||
|
{ defaultbg, "background" },
|
||||||
|
{ defaultcs, "cursor" }
|
||||||
|
};
|
||||||
|
|
||||||
term.esc &= ~(ESC_STR_END|ESC_STR);
|
term.esc &= ~(ESC_STR_END|ESC_STR);
|
||||||
strparse();
|
strparse();
|
||||||
|
@ -1939,16 +1910,39 @@ strhandle(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
case 10:
|
||||||
|
case 11:
|
||||||
|
case 12:
|
||||||
|
if (narg < 2)
|
||||||
|
break;
|
||||||
|
p = strescseq.args[1];
|
||||||
|
if ((j = par - 10) < 0 || j >= LEN(osc_table))
|
||||||
|
break; /* shouldn't be possible */
|
||||||
|
|
||||||
|
if (!strcmp(p, "?")) {
|
||||||
|
osc_color_response(par, osc_table[j].idx, 0);
|
||||||
|
} else if (xsetcolorname(osc_table[j].idx, p)) {
|
||||||
|
fprintf(stderr, "erresc: invalid %s color: %s\n",
|
||||||
|
osc_table[j].str, p);
|
||||||
|
} else {
|
||||||
|
tfulldirt();
|
||||||
|
}
|
||||||
|
return;
|
||||||
case 4: /* color set */
|
case 4: /* color set */
|
||||||
if (narg < 3)
|
if (narg < 3)
|
||||||
break;
|
break;
|
||||||
p = strescseq.args[2];
|
p = strescseq.args[2];
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case 104: /* color reset, here p = NULL */
|
case 104: /* color reset */
|
||||||
j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
|
j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
|
||||||
if (xsetcolorname(j, p)) {
|
|
||||||
if (par == 104 && narg <= 1)
|
if (p && !strcmp(p, "?")) {
|
||||||
|
osc_color_response(j, 0, 1);
|
||||||
|
} else if (xsetcolorname(j, p)) {
|
||||||
|
if (par == 104 && narg <= 1) {
|
||||||
|
xloadcols();
|
||||||
return; /* color reset without parameter */
|
return; /* color reset without parameter */
|
||||||
|
}
|
||||||
fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
|
fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
|
||||||
j, p ? p : "(null)");
|
j, p ? p : "(null)");
|
||||||
} else {
|
} else {
|
||||||
|
@ -1956,7 +1950,7 @@ strhandle(void)
|
||||||
* TODO if defaultbg color is changed, borders
|
* TODO if defaultbg color is changed, borders
|
||||||
* are dirty
|
* are dirty
|
||||||
*/
|
*/
|
||||||
redraw();
|
tfulldirt();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2082,7 +2076,7 @@ void
|
||||||
tdumpline(int n)
|
tdumpline(int n)
|
||||||
{
|
{
|
||||||
char buf[UTF_SIZ];
|
char buf[UTF_SIZ];
|
||||||
Glyph *bp, *end;
|
const Glyph *bp, *end;
|
||||||
|
|
||||||
bp = &term.line[n][0];
|
bp = &term.line[n][0];
|
||||||
end = &bp[MIN(tlinelen(n), term.col) - 1];
|
end = &bp[MIN(tlinelen(n), term.col) - 1];
|
||||||
|
@ -2311,7 +2305,7 @@ eschandle(uchar ascii)
|
||||||
return 0;
|
return 0;
|
||||||
case 'D': /* IND -- Linefeed */
|
case 'D': /* IND -- Linefeed */
|
||||||
if (term.c.y == term.bot) {
|
if (term.c.y == term.bot) {
|
||||||
tscrollup(term.top, 1, 1);
|
tscrollup(term.top, 1);
|
||||||
} else {
|
} else {
|
||||||
tmoveto(term.c.x, term.c.y+1);
|
tmoveto(term.c.x, term.c.y+1);
|
||||||
}
|
}
|
||||||
|
@ -2324,7 +2318,7 @@ eschandle(uchar ascii)
|
||||||
break;
|
break;
|
||||||
case 'M': /* RI -- Reverse index */
|
case 'M': /* RI -- Reverse index */
|
||||||
if (term.c.y == term.top) {
|
if (term.c.y == term.top) {
|
||||||
tscrolldown(term.top, 1, 1);
|
tscrolldown(term.top, 1);
|
||||||
} else {
|
} else {
|
||||||
tmoveto(term.c.x, term.c.y-1);
|
tmoveto(term.c.x, term.c.y-1);
|
||||||
}
|
}
|
||||||
|
@ -2428,6 +2422,9 @@ check_control_code:
|
||||||
* they must not cause conflicts with sequences.
|
* they must not cause conflicts with sequences.
|
||||||
*/
|
*/
|
||||||
if (control) {
|
if (control) {
|
||||||
|
/* in UTF-8 mode ignore handling C1 control characters */
|
||||||
|
if (IS_SET(MODE_UTF8) && ISCONTROLC1(u))
|
||||||
|
return;
|
||||||
tcontrolcode(u);
|
tcontrolcode(u);
|
||||||
/*
|
/*
|
||||||
* control codes are not shown ever
|
* control codes are not shown ever
|
||||||
|
@ -2488,6 +2485,10 @@ check_control_code:
|
||||||
if (width == 2) {
|
if (width == 2) {
|
||||||
gp->mode |= ATTR_WIDE;
|
gp->mode |= ATTR_WIDE;
|
||||||
if (term.c.x+1 < term.col) {
|
if (term.c.x+1 < term.col) {
|
||||||
|
if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) {
|
||||||
|
gp[2].u = ' ';
|
||||||
|
gp[2].mode &= ~ATTR_WDUMMY;
|
||||||
|
}
|
||||||
gp[1].u = '\0';
|
gp[1].u = '\0';
|
||||||
gp[1].mode = ATTR_WDUMMY;
|
gp[1].mode = ATTR_WDUMMY;
|
||||||
}
|
}
|
||||||
|
@ -2534,7 +2535,7 @@ twrite(const char *buf, int buflen, int show_ctrl)
|
||||||
void
|
void
|
||||||
tresize(int col, int row)
|
tresize(int col, int row)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i;
|
||||||
int minrow = MIN(row, term.row);
|
int minrow = MIN(row, term.row);
|
||||||
int mincol = MIN(col, term.col);
|
int mincol = MIN(col, term.col);
|
||||||
int *bp;
|
int *bp;
|
||||||
|
@ -2571,14 +2572,6 @@ tresize(int col, int row)
|
||||||
term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
|
term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
|
||||||
term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
|
term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
|
||||||
|
|
||||||
for (i = 0; i < HISTSIZE; i++) {
|
|
||||||
term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
|
|
||||||
for (j = mincol; j < col; j++) {
|
|
||||||
term.hist[i][j] = term.c.attr;
|
|
||||||
term.hist[i][j].u = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* resize each row to new width, zero-pad if needed */
|
/* resize each row to new width, zero-pad if needed */
|
||||||
for (i = 0; i < minrow; i++) {
|
for (i = 0; i < minrow; i++) {
|
||||||
term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
|
term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
|
||||||
|
@ -2637,7 +2630,7 @@ drawregion(int x1, int y1, int x2, int y2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
term.dirty[y] = 0;
|
term.dirty[y] = 0;
|
||||||
xdrawline(TLINE(y), x1, y, x2);
|
xdrawline(term.line[y], x1, y, x2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2658,10 +2651,8 @@ draw(void)
|
||||||
cx--;
|
cx--;
|
||||||
|
|
||||||
drawregion(0, 0, term.col, term.row);
|
drawregion(0, 0, term.col, term.row);
|
||||||
if (term.scr == 0)
|
xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
|
||||||
xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
|
term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
|
||||||
term.ocx, term.ocy, term.line[term.ocy][term.ocx],
|
|
||||||
term.line[term.ocy], term.col);
|
|
||||||
term.ocx = cx;
|
term.ocx = cx;
|
||||||
term.ocy = term.c.y;
|
term.ocy = term.c.y;
|
||||||
xfinishdraw();
|
xfinishdraw();
|
||||||
|
|
11
st/st.h
11
st/st.h
|
@ -11,8 +11,7 @@
|
||||||
#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
|
#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
|
||||||
#define DEFAULT(a, b) (a) = (a) ? (a) : (b)
|
#define DEFAULT(a, b) (a) = (a) ? (a) : (b)
|
||||||
#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
|
#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
|
||||||
#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP) & (~ATTR_LIGA)) != ((b).mode & (~ATTR_WRAP) & (~ATTR_LIGA)) || \
|
#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \
|
||||||
(a).fg != (b).fg || \
|
|
||||||
(a).bg != (b).bg)
|
(a).bg != (b).bg)
|
||||||
#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \
|
#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \
|
||||||
(t1.tv_nsec-t2.tv_nsec)/1E6)
|
(t1.tv_nsec-t2.tv_nsec)/1E6)
|
||||||
|
@ -34,7 +33,6 @@ enum glyph_attribute {
|
||||||
ATTR_WRAP = 1 << 8,
|
ATTR_WRAP = 1 << 8,
|
||||||
ATTR_WIDE = 1 << 9,
|
ATTR_WIDE = 1 << 9,
|
||||||
ATTR_WDUMMY = 1 << 10,
|
ATTR_WDUMMY = 1 << 10,
|
||||||
ATTR_LIGA = 1 << 11,
|
|
||||||
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
|
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,8 +81,6 @@ void die(const char *, ...);
|
||||||
void redraw(void);
|
void redraw(void);
|
||||||
void draw(void);
|
void draw(void);
|
||||||
|
|
||||||
void kscrolldown(const Arg *);
|
|
||||||
void kscrollup(const Arg *);
|
|
||||||
void printscreen(const Arg *);
|
void printscreen(const Arg *);
|
||||||
void printsel(const Arg *);
|
void printsel(const Arg *);
|
||||||
void sendbreak(const Arg *);
|
void sendbreak(const Arg *);
|
||||||
|
@ -95,7 +91,7 @@ void tnew(int, int);
|
||||||
void tresize(int, int);
|
void tresize(int, int);
|
||||||
void tsetdirtattr(int);
|
void tsetdirtattr(int);
|
||||||
void ttyhangup(void);
|
void ttyhangup(void);
|
||||||
int ttynew(char *, char *, char *, char **);
|
int ttynew(const char *, char *, const char *, char **);
|
||||||
size_t ttyread(void);
|
size_t ttyread(void);
|
||||||
void ttyresize(int, int);
|
void ttyresize(int, int);
|
||||||
void ttywrite(const char *, size_t, int);
|
void ttywrite(const char *, size_t, int);
|
||||||
|
@ -113,7 +109,7 @@ size_t utf8encode(Rune, char *);
|
||||||
|
|
||||||
void *xmalloc(size_t);
|
void *xmalloc(size_t);
|
||||||
void *xrealloc(void *, size_t);
|
void *xrealloc(void *, size_t);
|
||||||
char *xstrdup(char *);
|
char *xstrdup(const char *);
|
||||||
|
|
||||||
/* config.h globals */
|
/* config.h globals */
|
||||||
extern char *utmp;
|
extern char *utmp;
|
||||||
|
@ -127,3 +123,4 @@ extern char *termname;
|
||||||
extern unsigned int tabspaces;
|
extern unsigned int tabspaces;
|
||||||
extern unsigned int defaultfg;
|
extern unsigned int defaultfg;
|
||||||
extern unsigned int defaultbg;
|
extern unsigned int defaultbg;
|
||||||
|
extern unsigned int defaultcs;
|
||||||
|
|
3
st/win.h
3
st/win.h
|
@ -25,11 +25,12 @@ enum win_mode {
|
||||||
|
|
||||||
void xbell(void);
|
void xbell(void);
|
||||||
void xclipcopy(void);
|
void xclipcopy(void);
|
||||||
void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
|
void xdrawcursor(int, int, Glyph, int, int, Glyph);
|
||||||
void xdrawline(Line, int, int, int);
|
void xdrawline(Line, int, int, int);
|
||||||
void xfinishdraw(void);
|
void xfinishdraw(void);
|
||||||
void xloadcols(void);
|
void xloadcols(void);
|
||||||
int xsetcolorname(int, const char *);
|
int xsetcolorname(int, const char *);
|
||||||
|
int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *);
|
||||||
void xseticontitle(char *);
|
void xseticontitle(char *);
|
||||||
void xsettitle(char *);
|
void xsettitle(char *);
|
||||||
int xsetcursor(int);
|
int xsetcursor(int);
|
||||||
|
|
266
st/x.c
266
st/x.c
|
@ -14,13 +14,11 @@
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
#include <X11/Xft/Xft.h>
|
#include <X11/Xft/Xft.h>
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
#include <X11/Xresource.h>
|
|
||||||
|
|
||||||
char *argv0;
|
char *argv0;
|
||||||
#include "arg.h"
|
#include "arg.h"
|
||||||
#include "st.h"
|
#include "st.h"
|
||||||
#include "win.h"
|
#include "win.h"
|
||||||
#include "hb.h"
|
|
||||||
|
|
||||||
/* types used in config.h */
|
/* types used in config.h */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -47,23 +45,10 @@ typedef struct {
|
||||||
signed char appcursor; /* application cursor */
|
signed char appcursor; /* application cursor */
|
||||||
} Key;
|
} Key;
|
||||||
|
|
||||||
/* Xresources preferences */
|
|
||||||
enum resource_type {
|
|
||||||
STRING = 0,
|
|
||||||
INTEGER = 1,
|
|
||||||
FLOAT = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *name;
|
|
||||||
enum resource_type type;
|
|
||||||
void *dst;
|
|
||||||
} ResourcePref;
|
|
||||||
|
|
||||||
/* X modifiers */
|
/* X modifiers */
|
||||||
#define XK_ANY_MOD UINT_MAX
|
#define XK_ANY_MOD UINT_MAX
|
||||||
#define XK_NO_MOD 0
|
#define XK_NO_MOD 0
|
||||||
#define XK_SWITCH_MOD (1<<13)
|
#define XK_SWITCH_MOD (1<<13|1<<14)
|
||||||
|
|
||||||
/* function definitions used in config.h */
|
/* function definitions used in config.h */
|
||||||
static void clipcopy(const Arg *);
|
static void clipcopy(const Arg *);
|
||||||
|
@ -171,7 +156,7 @@ static void xresize(int, int);
|
||||||
static void xhints(void);
|
static void xhints(void);
|
||||||
static int xloadcolor(int, const char *, Color *);
|
static int xloadcolor(int, const char *, Color *);
|
||||||
static int xloadfont(Font *, FcPattern *);
|
static int xloadfont(Font *, FcPattern *);
|
||||||
static void xloadfonts(char *, double);
|
static void xloadfonts(const char *, double);
|
||||||
static void xunloadfont(Font *);
|
static void xunloadfont(Font *);
|
||||||
static void xunloadfonts(void);
|
static void xunloadfonts(void);
|
||||||
static void xsetenv(void);
|
static void xsetenv(void);
|
||||||
|
@ -267,8 +252,7 @@ static char *opt_line = NULL;
|
||||||
static char *opt_name = NULL;
|
static char *opt_name = NULL;
|
||||||
static char *opt_title = NULL;
|
static char *opt_title = NULL;
|
||||||
|
|
||||||
static int oldbutton = 3; /* button event on startup: 3 = release */
|
static uint buttons; /* bit field of pressed buttons */
|
||||||
static int cursorblinks = 0;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
clipcopy(const Arg *dummy)
|
clipcopy(const Arg *dummy)
|
||||||
|
@ -380,59 +364,68 @@ mousesel(XEvent *e, int done)
|
||||||
void
|
void
|
||||||
mousereport(XEvent *e)
|
mousereport(XEvent *e)
|
||||||
{
|
{
|
||||||
int len, x = evcol(e), y = evrow(e),
|
int len, btn, code;
|
||||||
button = e->xbutton.button, state = e->xbutton.state;
|
int x = evcol(e), y = evrow(e);
|
||||||
|
int state = e->xbutton.state;
|
||||||
char buf[40];
|
char buf[40];
|
||||||
static int ox, oy;
|
static int ox, oy;
|
||||||
|
|
||||||
/* from urxvt */
|
if (e->type == MotionNotify) {
|
||||||
if (e->xbutton.type == MotionNotify) {
|
|
||||||
if (x == ox && y == oy)
|
if (x == ox && y == oy)
|
||||||
return;
|
return;
|
||||||
if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY))
|
if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY))
|
||||||
return;
|
return;
|
||||||
/* MOUSE_MOTION: no reporting if no button is pressed */
|
/* MODE_MOUSEMOTION: no reporting if no button is pressed */
|
||||||
if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3)
|
if (IS_SET(MODE_MOUSEMOTION) && buttons == 0)
|
||||||
return;
|
return;
|
||||||
|
/* Set btn to lowest-numbered pressed button, or 12 if no
|
||||||
button = oldbutton + 32;
|
* buttons are pressed. */
|
||||||
ox = x;
|
for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++)
|
||||||
oy = y;
|
;
|
||||||
|
code = 32;
|
||||||
} else {
|
} else {
|
||||||
if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) {
|
btn = e->xbutton.button;
|
||||||
button = 3;
|
/* Only buttons 1 through 11 can be encoded */
|
||||||
} else {
|
if (btn < 1 || btn > 11)
|
||||||
button -= Button1;
|
return;
|
||||||
if (button >= 3)
|
if (e->type == ButtonRelease) {
|
||||||
button += 64 - 3;
|
|
||||||
}
|
|
||||||
if (e->xbutton.type == ButtonPress) {
|
|
||||||
oldbutton = button;
|
|
||||||
ox = x;
|
|
||||||
oy = y;
|
|
||||||
} else if (e->xbutton.type == ButtonRelease) {
|
|
||||||
oldbutton = 3;
|
|
||||||
/* MODE_MOUSEX10: no button release reporting */
|
/* MODE_MOUSEX10: no button release reporting */
|
||||||
if (IS_SET(MODE_MOUSEX10))
|
if (IS_SET(MODE_MOUSEX10))
|
||||||
return;
|
return;
|
||||||
if (button == 64 || button == 65)
|
/* Don't send release events for the scroll wheel */
|
||||||
|
if (btn == 4 || btn == 5)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
code = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ox = x;
|
||||||
|
oy = y;
|
||||||
|
|
||||||
|
/* Encode btn into code. If no button is pressed for a motion event in
|
||||||
|
* MODE_MOUSEMANY, then encode it as a release. */
|
||||||
|
if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12)
|
||||||
|
code += 3;
|
||||||
|
else if (btn >= 8)
|
||||||
|
code += 128 + btn - 8;
|
||||||
|
else if (btn >= 4)
|
||||||
|
code += 64 + btn - 4;
|
||||||
|
else
|
||||||
|
code += btn - 1;
|
||||||
|
|
||||||
if (!IS_SET(MODE_MOUSEX10)) {
|
if (!IS_SET(MODE_MOUSEX10)) {
|
||||||
button += ((state & ShiftMask ) ? 4 : 0)
|
code += ((state & ShiftMask ) ? 4 : 0)
|
||||||
+ ((state & Mod4Mask ) ? 8 : 0)
|
+ ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */
|
||||||
+ ((state & ControlMask) ? 16 : 0);
|
+ ((state & ControlMask) ? 16 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_SET(MODE_MOUSESGR)) {
|
if (IS_SET(MODE_MOUSESGR)) {
|
||||||
len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
|
len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
|
||||||
button, x+1, y+1,
|
code, x+1, y+1,
|
||||||
e->xbutton.type == ButtonRelease ? 'm' : 'M');
|
e->type == ButtonRelease ? 'm' : 'M');
|
||||||
} else if (x < 223 && y < 223) {
|
} else if (x < 223 && y < 223) {
|
||||||
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
|
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
|
||||||
32+button, 32+x+1, 32+y+1);
|
32+code, 32+x+1, 32+y+1);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -475,9 +468,13 @@ mouseaction(XEvent *e, uint release)
|
||||||
void
|
void
|
||||||
bpress(XEvent *e)
|
bpress(XEvent *e)
|
||||||
{
|
{
|
||||||
|
int btn = e->xbutton.button;
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
int snap;
|
int snap;
|
||||||
|
|
||||||
|
if (1 <= btn && btn <= 11)
|
||||||
|
buttons |= 1 << (btn-1);
|
||||||
|
|
||||||
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
||||||
mousereport(e);
|
mousereport(e);
|
||||||
return;
|
return;
|
||||||
|
@ -486,7 +483,7 @@ bpress(XEvent *e)
|
||||||
if (mouseaction(e, 0))
|
if (mouseaction(e, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (e->xbutton.button == Button1) {
|
if (btn == Button1) {
|
||||||
/*
|
/*
|
||||||
* If the user clicks below predefined timeouts specific
|
* If the user clicks below predefined timeouts specific
|
||||||
* snapping behaviour is exposed.
|
* snapping behaviour is exposed.
|
||||||
|
@ -689,8 +686,6 @@ setsel(char *str, Time t)
|
||||||
XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
|
XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
|
||||||
if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
|
if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
|
||||||
selclear();
|
selclear();
|
||||||
|
|
||||||
xclipcopy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -702,6 +697,11 @@ xsetsel(char *str)
|
||||||
void
|
void
|
||||||
brelease(XEvent *e)
|
brelease(XEvent *e)
|
||||||
{
|
{
|
||||||
|
int btn = e->xbutton.button;
|
||||||
|
|
||||||
|
if (1 <= btn && btn <= 11)
|
||||||
|
buttons &= ~(1 << (btn-1));
|
||||||
|
|
||||||
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
||||||
mousereport(e);
|
mousereport(e);
|
||||||
return;
|
return;
|
||||||
|
@ -709,7 +709,7 @@ brelease(XEvent *e)
|
||||||
|
|
||||||
if (mouseaction(e, 1))
|
if (mouseaction(e, 1))
|
||||||
return;
|
return;
|
||||||
if (e->xbutton.button == Button1)
|
if (btn == Button1)
|
||||||
mousesel(e, 1);
|
mousesel(e, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,6 +815,19 @@ xloadcols(void)
|
||||||
loaded = 1;
|
loaded = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b)
|
||||||
|
{
|
||||||
|
if (!BETWEEN(x, 0, dc.collen))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
*r = dc.col[x].color.red >> 8;
|
||||||
|
*g = dc.col[x].color.green >> 8;
|
||||||
|
*b = dc.col[x].color.blue >> 8;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
xsetcolorname(int x, const char *name)
|
xsetcolorname(int x, const char *name)
|
||||||
{
|
{
|
||||||
|
@ -846,8 +859,8 @@ xclear(int x1, int y1, int x2, int y2)
|
||||||
void
|
void
|
||||||
xhints(void)
|
xhints(void)
|
||||||
{
|
{
|
||||||
XClassHint class = {opt_name ? opt_name : "st",
|
XClassHint class = {opt_name ? opt_name : termname,
|
||||||
opt_class ? opt_class : "St"};
|
opt_class ? opt_class : termname};
|
||||||
XWMHints wm = {.flags = InputHint, .input = 1};
|
XWMHints wm = {.flags = InputHint, .input = 1};
|
||||||
XSizeHints *sizeh;
|
XSizeHints *sizeh;
|
||||||
|
|
||||||
|
@ -968,7 +981,7 @@ xloadfont(Font *f, FcPattern *pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
xloadfonts(char *fontstr, double fontsize)
|
xloadfonts(const char *fontstr, double fontsize)
|
||||||
{
|
{
|
||||||
FcPattern *pattern;
|
FcPattern *pattern;
|
||||||
double fontval;
|
double fontval;
|
||||||
|
@ -976,7 +989,7 @@ xloadfonts(char *fontstr, double fontsize)
|
||||||
if (fontstr[0] == '-')
|
if (fontstr[0] == '-')
|
||||||
pattern = XftXlfdParse(fontstr, False, False);
|
pattern = XftXlfdParse(fontstr, False, False);
|
||||||
else
|
else
|
||||||
pattern = FcNameParse((FcChar8 *)fontstr);
|
pattern = FcNameParse((const FcChar8 *)fontstr);
|
||||||
|
|
||||||
if (!pattern)
|
if (!pattern)
|
||||||
die("can't open font %s\n", fontstr);
|
die("can't open font %s\n", fontstr);
|
||||||
|
@ -1049,9 +1062,6 @@ xunloadfont(Font *f)
|
||||||
void
|
void
|
||||||
xunloadfonts(void)
|
xunloadfonts(void)
|
||||||
{
|
{
|
||||||
/* Clear Harfbuzz font cache. */
|
|
||||||
hbunloadfonts();
|
|
||||||
|
|
||||||
/* Free the loaded fonts in the font cache. */
|
/* Free the loaded fonts in the font cache. */
|
||||||
while (frclen > 0)
|
while (frclen > 0)
|
||||||
XftFontClose(xw.dpy, frc[--frclen].font);
|
XftFontClose(xw.dpy, frc[--frclen].font);
|
||||||
|
@ -1125,6 +1135,8 @@ xinit(int cols, int rows)
|
||||||
pid_t thispid = getpid();
|
pid_t thispid = getpid();
|
||||||
XColor xmousefg, xmousebg;
|
XColor xmousefg, xmousebg;
|
||||||
|
|
||||||
|
if (!(xw.dpy = XOpenDisplay(NULL)))
|
||||||
|
die("can't open display\n");
|
||||||
xw.scr = XDefaultScreen(xw.dpy);
|
xw.scr = XDefaultScreen(xw.dpy);
|
||||||
xw.vis = XDefaultVisual(xw.dpy, xw.scr);
|
xw.vis = XDefaultVisual(xw.dpy, xw.scr);
|
||||||
|
|
||||||
|
@ -1249,7 +1261,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
|
||||||
mode = glyphs[i].mode;
|
mode = glyphs[i].mode;
|
||||||
|
|
||||||
/* Skip dummy wide-character spacing. */
|
/* Skip dummy wide-character spacing. */
|
||||||
if (mode & ATTR_WDUMMY)
|
if (mode == ATTR_WDUMMY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Determine font for glyph if different from previous glyph. */
|
/* Determine font for glyph if different from previous glyph. */
|
||||||
|
@ -1356,9 +1368,6 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
|
||||||
numspecs++;
|
numspecs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Harfbuzz transformation for ligatures. */
|
|
||||||
hbtransform(specs, glyphs, len, x, y);
|
|
||||||
|
|
||||||
return numspecs;
|
return numspecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1484,12 +1493,12 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
|
||||||
|
|
||||||
/* Render underline and strikethrough. */
|
/* Render underline and strikethrough. */
|
||||||
if (base.mode & ATTR_UNDERLINE) {
|
if (base.mode & ATTR_UNDERLINE) {
|
||||||
XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
|
XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
|
||||||
width, 1);
|
width, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base.mode & ATTR_STRUCK) {
|
if (base.mode & ATTR_STRUCK) {
|
||||||
XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
|
XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
|
||||||
width, 1);
|
width, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1508,17 +1517,14 @@ xdrawglyph(Glyph g, int x, int y)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len)
|
xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
|
||||||
{
|
{
|
||||||
Color drawcol;
|
Color drawcol;
|
||||||
|
|
||||||
/* remove the old cursor */
|
/* remove the old cursor */
|
||||||
if (selected(ox, oy))
|
if (selected(ox, oy))
|
||||||
og.mode ^= ATTR_REVERSE;
|
og.mode ^= ATTR_REVERSE;
|
||||||
|
xdrawglyph(og, ox, oy);
|
||||||
/* Redraw the line where cursor was previously.
|
|
||||||
* It will restore the ligatures broken by the cursor. */
|
|
||||||
xdrawline(line, 0, oy, len);
|
|
||||||
|
|
||||||
if (IS_SET(MODE_HIDE))
|
if (IS_SET(MODE_HIDE))
|
||||||
return;
|
return;
|
||||||
|
@ -1552,19 +1558,16 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le
|
||||||
/* draw the new one */
|
/* draw the new one */
|
||||||
if (IS_SET(MODE_FOCUSED)) {
|
if (IS_SET(MODE_FOCUSED)) {
|
||||||
switch (win.cursor) {
|
switch (win.cursor) {
|
||||||
case 0: /* Blinking block */
|
case 7: /* st extension */
|
||||||
case 1: /* Blinking block (default) */
|
g.u = 0x2603; /* snowman (U+2603) */
|
||||||
if (IS_SET(MODE_BLINK))
|
|
||||||
break;
|
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case 2: /* Steady block */
|
case 0: /* Blinking Block */
|
||||||
|
case 1: /* Blinking Block (Default) */
|
||||||
|
case 2: /* Steady Block */
|
||||||
xdrawglyph(g, cx, cy);
|
xdrawglyph(g, cx, cy);
|
||||||
break;
|
break;
|
||||||
case 3: /* Blinking underline */
|
case 3: /* Blinking Underline */
|
||||||
if (IS_SET(MODE_BLINK))
|
case 4: /* Steady Underline */
|
||||||
break;
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case 4: /* Steady underline */
|
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
XftDrawRect(xw.draw, &drawcol,
|
||||||
borderpx + cx * win.cw,
|
borderpx + cx * win.cw,
|
||||||
borderpx + (cy + 1) * win.ch - \
|
borderpx + (cy + 1) * win.ch - \
|
||||||
|
@ -1572,23 +1575,12 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le
|
||||||
win.cw, cursorthickness);
|
win.cw, cursorthickness);
|
||||||
break;
|
break;
|
||||||
case 5: /* Blinking bar */
|
case 5: /* Blinking bar */
|
||||||
if (IS_SET(MODE_BLINK))
|
|
||||||
break;
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case 6: /* Steady bar */
|
case 6: /* Steady bar */
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
XftDrawRect(xw.draw, &drawcol,
|
||||||
borderpx + cx * win.cw,
|
borderpx + cx * win.cw,
|
||||||
borderpx + cy * win.ch,
|
borderpx + cy * win.ch,
|
||||||
cursorthickness, win.ch);
|
cursorthickness, win.ch);
|
||||||
break;
|
break;
|
||||||
case 7: /* Blinking st cursor */
|
|
||||||
if (IS_SET(MODE_BLINK))
|
|
||||||
break;
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case 8: /* Steady st cursor */
|
|
||||||
g.u = stcursor;
|
|
||||||
xdrawglyph(g, cx, cy);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
XftDrawRect(xw.draw, &drawcol,
|
XftDrawRect(xw.draw, &drawcol,
|
||||||
|
@ -1625,8 +1617,9 @@ xseticontitle(char *p)
|
||||||
XTextProperty prop;
|
XTextProperty prop;
|
||||||
DEFAULT(p, opt_title);
|
DEFAULT(p, opt_title);
|
||||||
|
|
||||||
Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
|
if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
|
||||||
&prop);
|
&prop) != Success)
|
||||||
|
return;
|
||||||
XSetWMIconName(xw.dpy, xw.win, &prop);
|
XSetWMIconName(xw.dpy, xw.win, &prop);
|
||||||
XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname);
|
XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname);
|
||||||
XFree(prop.value);
|
XFree(prop.value);
|
||||||
|
@ -1638,8 +1631,9 @@ xsettitle(char *p)
|
||||||
XTextProperty prop;
|
XTextProperty prop;
|
||||||
DEFAULT(p, opt_title);
|
DEFAULT(p, opt_title);
|
||||||
|
|
||||||
Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
|
if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
|
||||||
&prop);
|
&prop) != Success)
|
||||||
|
return;
|
||||||
XSetWMName(xw.dpy, xw.win, &prop);
|
XSetWMName(xw.dpy, xw.win, &prop);
|
||||||
XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname);
|
XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname);
|
||||||
XFree(prop.value);
|
XFree(prop.value);
|
||||||
|
@ -1743,12 +1737,9 @@ xsetmode(int set, unsigned int flags)
|
||||||
int
|
int
|
||||||
xsetcursor(int cursor)
|
xsetcursor(int cursor)
|
||||||
{
|
{
|
||||||
if (!BETWEEN(cursor, 0, 8)) /* 7-8: st extensions */
|
if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */
|
||||||
return 1;
|
return 1;
|
||||||
win.cursor = cursor;
|
win.cursor = cursor;
|
||||||
cursorblinks = win.cursor == 0 || win.cursor == 1 ||
|
|
||||||
win.cursor == 3 || win.cursor == 5 ||
|
|
||||||
win.cursor == 7;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1842,7 +1833,7 @@ void
|
||||||
kpress(XEvent *ev)
|
kpress(XEvent *ev)
|
||||||
{
|
{
|
||||||
XKeyEvent *e = &ev->xkey;
|
XKeyEvent *e = &ev->xkey;
|
||||||
KeySym ksym;
|
KeySym ksym = NoSymbol;
|
||||||
char buf[64], *customkey;
|
char buf[64], *customkey;
|
||||||
int len;
|
int len;
|
||||||
Rune c;
|
Rune c;
|
||||||
|
@ -1852,10 +1843,13 @@ kpress(XEvent *ev)
|
||||||
if (IS_SET(MODE_KBDLOCK))
|
if (IS_SET(MODE_KBDLOCK))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (xw.ime.xic)
|
if (xw.ime.xic) {
|
||||||
len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status);
|
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);
|
len = XLookupString(e, buf, sizeof buf, &ksym, NULL);
|
||||||
|
}
|
||||||
/* 1. shortcuts */
|
/* 1. shortcuts */
|
||||||
for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
|
for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
|
||||||
if (ksym == bp->keysym && match(bp->mod, e->state)) {
|
if (ksym == bp->keysym && match(bp->mod, e->state)) {
|
||||||
|
@ -1992,10 +1986,6 @@ run(void)
|
||||||
if (FD_ISSET(ttyfd, &rfd) || xev) {
|
if (FD_ISSET(ttyfd, &rfd) || xev) {
|
||||||
if (!drawing) {
|
if (!drawing) {
|
||||||
trigger = now;
|
trigger = now;
|
||||||
if (IS_SET(MODE_BLINK)) {
|
|
||||||
win.mode ^= MODE_BLINK;
|
|
||||||
}
|
|
||||||
lastblink = now;
|
|
||||||
drawing = 1;
|
drawing = 1;
|
||||||
}
|
}
|
||||||
timeout = (maxlatency - TIMEDIFF(now, trigger)) \
|
timeout = (maxlatency - TIMEDIFF(now, trigger)) \
|
||||||
|
@ -2006,7 +1996,7 @@ run(void)
|
||||||
|
|
||||||
/* idle detected or maxlatency exhausted -> draw */
|
/* idle detected or maxlatency exhausted -> draw */
|
||||||
timeout = -1;
|
timeout = -1;
|
||||||
if (blinktimeout && (cursorblinks || tattrset(ATTR_BLINK))) {
|
if (blinktimeout && tattrset(ATTR_BLINK)) {
|
||||||
timeout = blinktimeout - TIMEDIFF(now, lastblink);
|
timeout = blinktimeout - TIMEDIFF(now, lastblink);
|
||||||
if (timeout <= 0) {
|
if (timeout <= 0) {
|
||||||
if (-timeout > blinktimeout) /* start visible */
|
if (-timeout > blinktimeout) /* start visible */
|
||||||
|
@ -2024,59 +2014,6 @@ run(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
|
|
||||||
{
|
|
||||||
char **sdst = dst;
|
|
||||||
int *idst = dst;
|
|
||||||
float *fdst = dst;
|
|
||||||
|
|
||||||
char fullname[256];
|
|
||||||
char fullclass[256];
|
|
||||||
char *type;
|
|
||||||
XrmValue ret;
|
|
||||||
|
|
||||||
snprintf(fullname, sizeof(fullname), "%s.%s",
|
|
||||||
opt_name ? opt_name : "st", name);
|
|
||||||
snprintf(fullclass, sizeof(fullclass), "%s.%s",
|
|
||||||
opt_class ? opt_class : "St", name);
|
|
||||||
fullname[sizeof(fullname) - 1] = fullclass[sizeof(fullclass) - 1] = '\0';
|
|
||||||
|
|
||||||
XrmGetResource(db, fullname, fullclass, &type, &ret);
|
|
||||||
if (ret.addr == NULL || strncmp("String", type, 64))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
switch (rtype) {
|
|
||||||
case STRING:
|
|
||||||
*sdst = ret.addr;
|
|
||||||
break;
|
|
||||||
case INTEGER:
|
|
||||||
*idst = strtoul(ret.addr, NULL, 10);
|
|
||||||
break;
|
|
||||||
case FLOAT:
|
|
||||||
*fdst = strtof(ret.addr, NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
config_init(void)
|
|
||||||
{
|
|
||||||
char *resm;
|
|
||||||
XrmDatabase db;
|
|
||||||
ResourcePref *p;
|
|
||||||
|
|
||||||
XrmInitialize();
|
|
||||||
resm = XResourceManagerString(xw.dpy);
|
|
||||||
if (!resm)
|
|
||||||
return;
|
|
||||||
|
|
||||||
db = XrmGetStringDatabase(resm);
|
|
||||||
for (p = resources; p < resources + LEN(resources); p++)
|
|
||||||
resource_load(db, p->name, p->type, p->dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
|
@ -2095,7 +2032,7 @@ main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
xw.l = xw.t = 0;
|
xw.l = xw.t = 0;
|
||||||
xw.isfixed = False;
|
xw.isfixed = False;
|
||||||
xsetcursor(cursorstyle);
|
xsetcursor(cursorshape);
|
||||||
|
|
||||||
ARGBEGIN {
|
ARGBEGIN {
|
||||||
case 'a':
|
case 'a':
|
||||||
|
@ -2150,11 +2087,6 @@ run:
|
||||||
|
|
||||||
setlocale(LC_CTYPE, "");
|
setlocale(LC_CTYPE, "");
|
||||||
XSetLocaleModifiers("");
|
XSetLocaleModifiers("");
|
||||||
|
|
||||||
if(!(xw.dpy = XOpenDisplay(NULL)))
|
|
||||||
die("Can't open display\n");
|
|
||||||
|
|
||||||
config_init();
|
|
||||||
cols = MAX(cols, 1);
|
cols = MAX(cols, 1);
|
||||||
rows = MAX(rows, 1);
|
rows = MAX(rows, 1);
|
||||||
tnew(cols, rows);
|
tnew(cols, rows);
|
||||||
|
|
Loading…
Reference in a new issue