#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include <X11/Xft/Xft.h>
+#include <X11/XKBlib.h>
#include <fontconfig/fontconfig.h>
#include <wchar.h>
#define XK_NO_MOD 0
#define XK_SWITCH_MOD (1<<13)
-#define REDRAW_TIMEOUT (80*1000) /* 80 ms */
-
/* macros */
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
static void die(const char *, ...);
static void draw(void);
-static void redraw(int);
+static void redraw(void);
static void drawregion(int, int, int, int);
static void execsh(void);
static void sigchld(int);
typedef struct {
XftFont *font;
int flags;
+ long unicodep;
} Fontcache;
/* Fontcache is an array now. A new font will be appended to the array. */
lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
}
last = &term.line[y][MIN(lastx, linelen-1)];
+ while(last >= gp && last->c[0] == ' ')
+ --last;
for( ; gp <= last; ++gp) {
if(gp->mode & ATTR_WDUMMY)
void
execsh(void) {
- char **args, *sh;
+ char **args, *sh, *prog;
const struct passwd *pw;
char buf[sizeof(long) * 8 + 1];
die("who are you?\n");
}
- if (utmp)
- sh = utmp;
- else if (pw->pw_shell[0])
- sh = pw->pw_shell;
+ if (!(sh = getenv("SHELL"))) {
+ sh = (pw->pw_shell[0]) ? pw->pw_shell : shell;
+ }
+
+ if(opt_cmd)
+ prog = opt_cmd[0];
+ else if(utmp)
+ prog = utmp;
else
- sh = shell;
- args = (opt_cmd) ? opt_cmd : (char *[]){sh, NULL};
+ prog = sh;
+ args = (opt_cmd) ? opt_cmd : (char *[]) {prog, NULL};
+
snprintf(buf, sizeof(buf), "%lu", xw.win);
unsetenv("COLUMNS");
unsetenv("TERMCAP");
setenv("LOGNAME", pw->pw_name, 1);
setenv("USER", pw->pw_name, 1);
- setenv("SHELL", args[0], 1);
+ setenv("SHELL", sh, 1);
setenv("HOME", pw->pw_dir, 1);
setenv("TERM", termname, 1);
setenv("WINDOWID", buf, 1);
signal(SIGTERM, SIG_DFL);
signal(SIGALRM, SIG_DFL);
- execvp(args[0], args);
- exit(EXIT_FAILURE);
+ execvp(prog, args);
+ _exit(EXIT_FAILURE);
}
void
mode = term.mode;
MODBIT(term.mode, set, MODE_REVERSE);
if(mode != term.mode)
- redraw(REDRAW_TIMEOUT);
+ redraw();
break;
case 6: /* DECOM -- Origin */
MODBIT(term.c.state, set, CURSOR_ORIGIN);
* TODO if defaultbg color is changed, borders
* are dirty
*/
- redraw(0);
+ redraw();
}
return;
}
if(!(xw.state & WIN_FOCUSED))
xseturgency(1);
if (bellvolume)
- XBell(xw.dpy, bellvolume);
+ XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL);
}
break;
case '\033': /* ESC */
term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST);
term.esc |= ESC_START;
return;
- case '\016': /* SO */
- term.charset = 0;
- return;
- case '\017': /* SI */
- term.charset = 1;
+ case '\016': /* SO (LS1 -- Locking shift 1) */
+ case '\017': /* SI (LS0 -- Locking shift 0) */
+ term.charset = 1 - (ascii - '\016');
return;
case '\032': /* SUB */
tsetchar(question, &term.c.attr, term.c.x, term.c.y);
case 'k': /* old title set compatibility */
tstrsequence(ascii);
return 0;
+ case 'n': /* LS2 -- Locking shift 2 */
+ case 'o': /* LS3 -- Locking shift 3 */
+ term.charset = 2 + (ascii - 'n');
+ break;
case '(': /* GZD4 -- set primary charset G0 */
case ')': /* G1D4 -- set secondary charset G1 */
case '*': /* G2D4 -- set tertiary charset G2 */
unicodep = ascii = *c;
} else {
utf8decode(c, &unicodep, UTF_SIZ);
- width = wcwidth(unicodep);
+ if ((width = wcwidth(unicodep)) == -1) {
+ c = "\357\277\275"; /* UTF_INVALID */
+ width = 1;
+ }
control = ISCONTROLC1(unicodep);
ascii = unicodep;
}
if(IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) {
gp->mode |= ATTR_WRAP;
tnewline(1);
+ gp = &term.line[term.c.y][term.c.x];
}
- if(IS_SET(MODE_INSERT) && term.c.x+1 < term.col)
- memmove(gp+1, gp, (term.col - term.c.x - 1) * sizeof(Glyph));
+ if(IS_SET(MODE_INSERT) && term.c.x+width < term.col)
+ memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph));
- if(term.c.x+width > term.col)
+ if(term.c.x+width > term.col) {
tnewline(1);
+ gp = &term.line[term.c.y][term.c.x];
+ }
tsetchar(c, &term.c.attr, term.c.x, term.c.y);
if(!pattern)
die("st: can't open font %s\n", fontstr);
- if(fontsize > 0) {
+ if(fontsize > 1) {
FcPatternDel(pattern, FC_PIXEL_SIZE);
FcPatternDel(pattern, FC_SIZE);
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize);
xunloadfont(&dc.ibfont);
}
-
void
xzoom(const Arg *arg) {
Arg larg;
+
larg.i = usedfontsize + arg->i;
xzoomabs(&larg);
}
xunloadfonts();
xloadfonts(usedfont, arg->i);
cresize(0, 0);
- redraw(0);
+ redraw();
xhints();
}
void
xzoomreset(const Arg *arg) {
Arg larg;
+
if(defaultfontsize > 0) {
larg.i = defaultfontsize;
xzoomabs(&larg);
| ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
xw.attrs.colormap = xw.cmap;
- parent = opt_embed ? strtol(opt_embed, NULL, 0) : \
- XRootWindow(xw.dpy, xw.scr);
+ if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0))))
+ parent = XRootWindow(xw.dpy, xw.scr);
xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t,
xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput,
xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity
xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) {
int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch,
width = charlen * xw.cw, xp, i;
- int frcflags;
+ int frcflags, charexists;
int u8fl, u8fblen, u8cblen, doesexist;
char *u8c, *u8fs;
long unicodep;
/* Search the font cache. */
for(i = 0; i < frclen; i++) {
- if(XftCharExists(xw.dpy, frc[i].font, unicodep)
- && frc[i].flags == frcflags) {
+ charexists = XftCharExists(xw.dpy, frc[i].font, unicodep);
+ /* Everything correct. */
+ if(charexists && frc[i].flags == frcflags)
+ break;
+ /* We got a default font for a not found glyph. */
+ if(!charexists && frc[i].flags == frcflags \
+ && unicodep == unicodep) {
break;
}
}
FcConfigSubstitute(0, fcpattern,
FcMatchPattern);
+ FcPatternPrint(fcpattern);
FcDefaultSubstitute(fcpattern);
- fontpattern = FcFontSetMatch(0, fcsets,
- FcTrue, fcpattern, &fcres);
+ fontpattern = FcFontSetMatch(0, fcsets, 1,
+ fcpattern, &fcres);
/*
* Overwrite or create the new cache entry.
if(frclen >= LEN(frc)) {
frclen = LEN(frc) - 1;
XftFontClose(xw.dpy, frc[frclen].font);
+ frc[frclen].unicodep = 0;
}
frc[frclen].font = XftFontOpenPattern(xw.dpy,
fontpattern);
frc[frclen].flags = frcflags;
+ frc[frclen].unicodep = unicodep;
i = frclen;
frclen++;
}
void
-redraw(int timeout) {
- struct timespec tv = {0, timeout * 1000};
-
+redraw(void) {
tfulldirt();
draw();
-
- if(timeout > 0) {
- nanosleep(&tv, NULL);
- XSync(xw.dpy, False); /* necessary for a good tput flash */
- }
}
void
if(!e->count)
xw.state &= ~WIN_REDRAW;
}
- redraw(0);
+ redraw();
}
void
TIMEDIFF(now,
lastblink)));
}
+ drawtimeout.tv_sec = \
+ drawtimeout.tv_nsec / 1E9;
+ drawtimeout.tv_nsec %= (long)1E9;
} else {
tv = NULL;
}
void
usage(void) {
- die("%s " VERSION " (c) 2010-2014 st engineers\n" \
+ die("%s " VERSION " (c) 2010-2015 st engineers\n" \
"usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n"
" [-i] [-t title] [-w windowid] [-e command ...]\n", argv0);
}