21 Commits
0.4 ... 0.4.1

Author SHA1 Message Date
3c546ae739 0.4.1 release. 2013-04-20 15:29:39 +02:00
645c1b0afc Making st compile on OpenBSD again. 2013-04-19 21:11:29 +02:00
e5ff746430 Selection now handles empty lines less counter-intuitively.
Now, when you are selecting a region, you will get all empty lines that happen
to be in it, including trailing ones. Last line terminator is omitted as it previously
was, though.

Signed-off-by: Christoph Lohmann <20h@r-36.net>
2013-04-18 16:51:52 +02:00
da182612b7 Removing trailing whitespace. 2013-04-18 06:51:18 +02:00
b7e6a5c825 Got rid of redundant Glyph state.
Now, newly allocated Glyphs are set to spaces and current cursor colors
with tclearregion() routine.

Signed-off-by: Christoph Lohmann <20h@r-36.net>
2013-04-18 06:48:06 +02:00
3ae0299064 Removing unneeded comments. 2013-04-18 06:41:54 +02:00
fed9968ba5 Got rid of code duplication in tnew() and tresize().
Signed-off-by: Christoph Lohmann <20h@r-36.net>
2013-04-18 06:39:43 +02:00
0ca0dd8b11 Strip trailing spaces from lines when copying selection.
Signed-off-by: Christoph Lohmann <20h@r-36.net>
2013-04-14 21:32:53 +02:00
c371fe58a3 Enable BCE everywhere. 2013-04-14 18:30:10 +02:00
44db38a5f8 Fix the geometry handling. 2013-04-13 15:24:26 +02:00
4de64fa4d2 \033 should be used in printf in the FAQ.
Never apply patches of Apple users without shouting at them. The basic rule of
nature is that when you apply Appl users patches without shouting at them that
something will go horribly wrong.
2013-04-13 12:26:17 +02:00
de4cd2f6af Resize now uses xclear(). 2013-04-13 09:49:11 +02:00
1e7816c202 Drawing a more visible rectangle as cursor on unfocus.
To have a more visible cursor on unfocused windows this patch makes st draw a
rectangle around the terminal cell.

Thanks Mark Hills <mark@xwax.org> for the suggestion!
2013-04-13 09:44:00 +02:00
5dc48af29e Patching while not really woken up. 2013-04-13 08:51:30 +02:00
5984657c00 Minor naming issue fixed. 2013-04-13 08:50:38 +02:00
4018b2c507 Making the copy and pasting consistent.
The copying and pasting in the terminald and GUI world is flawed. Due to the
discussion on the mailinglist it seems that sending '\n' is what GUIs expect
and '\r' what terminal applications want. St now implements that behaviour.
2013-04-13 08:48:17 +02:00
ddd429ea24 Convert FAQ into Markdown, to make it easier to integrate it into http://st.suckless.org/
Signed-off-by: Christoph Lohmann <20h@r-36.net>
2013-04-13 08:25:07 +02:00
684cf55a0d Make st work with a plain -e command. 2013-04-10 17:48:32 +02:00
b1813b14d9 Adopting arg.h with more flexible cmd handling. 2013-04-03 21:00:38 +02:00
580c8bbd46 Add an option to disable alternative screens. 2013-04-03 20:42:27 +02:00
502911e554 Updating the TODO file for after 0.4. 2013-03-29 19:44:37 +01:00
7 changed files with 283 additions and 212 deletions

54
FAQ
View File

@ -1,43 +1,35 @@
--
Why does st not handle utmp entries?
## Why does st not handle utmp entries?
Use the excellent tool of utmp[0] for this task.
Use the excellent tool of [utmp](http://git.suckless.org/utmp/) for this task.
[0] http://git.suckless.org/utmp/
--
Some _random program_ complains that st is unknown/not
recognised/unsupported/whatever!
## Some _random program_ complains that st is unknown/not recognised/unsupported/whatever!
It means that st doesnt have any terminfo entry on your system. Chances are
you did not make install. If you just want to test it without installing it,
you can manualy run tic -s st.info in st dir. It will compile st.info into a
fully working local terminfo description. You can delete it when youre done.
--
Nothing works, and nothing is said about an unknown terminal!
you did not `make install`. If you just want to test it without installing it,
you can manualy run `tic -s st.info`.
## Nothing works, and nothing is said about an unknown terminal!
* Some programs just assume theyre running in xterm i.e. they dont rely on
terminfo. What you see is the current state of the “xterm compliance”.
* Some programs dont complain about the lacking st description and default to
another terminal. In that case see the question about terminfo.
--
I get some weird glitches/visual bug on _random program_!
Try lauching it with a different TERM: $ TERM=xterm myapp. toe(1) will give
you a list of available terminals, but youll most likely switch between
xterm, st or st-256color. The default value for TERM can be changed in
config.h (TNAME).
--
How do I scroll back up?
## I get some weird glitches/visual bug on _random program_!
Invoke st with a screen multiplexer like GNU screen[0] or tmux[1].
st -e screen works better for text reflowing. To enter screens scroll
back mode aka “copy mode”, its C-a ESC. You probably want defscrollback
10000 in your ~/.screenrc too.
Try launching it with a different TERM: $ TERM=xterm myapp. toe(1) will give
you a list of available terminals, but youll most likely switch between xterm,
st or st-256color. The default value for TERM can be changed in config.h
(TNAME).
[0] http://en.wikipedia.org/wiki/GNU_Screen
[1] http://en.wikipedia.org/wiki/Tmux
--
Why doesn't the Del key work in some programs?
## How do I scroll back up?
Using a terminal multiplexer.
* `st -e tmux` using C-a [
* `st -e screen` using C-a ESC
## Why doesn't the Del key work in some programs?
Taken from the terminfo manpage:
@ -49,7 +41,7 @@ Taken from the terminfo manpage:
codes as smkx and rmkx. Otherwise the keypad is assumed to
always transmit.
In the st case smkx=\E[?1h\E= and rmkx=\E[?1l\E>, so it is mandatory that
In the st case smkx=E[?1hE= and rmkx=E[?1lE>, so it is mandatory that
applications which want to test against keypad keys, have to send these
sequences.
@ -73,7 +65,7 @@ Adding this option to your .inputrc will fix the keypad problem for all
applications using readline.
If you are using zsh, then read the zsh FAQ
(http://zsh.sourceforge.net/FAQ/zshfaq03.html#l25):
<http://zsh.sourceforge.net/FAQ/zshfaq03.html#l25>:
It should be noted that the O / [ confusion can occur with other keys
such as Home and End. Some systems let you query the key sequences
@ -91,5 +83,3 @@ If you are using zsh, then read the zsh FAQ
zle -N zle-line-finish
Putting these lines into your .zshrc will fix the problems.
--

15
TODO
View File

@ -1,18 +1,23 @@
vt emulation
------------
* color definition in CSI
* implement CSI parsing
* wide-character support in conjunction with fallback xft code
* mouse selection support
* double-height support
code & interface
----------------
* clean and complete terminfo entry
* add fallback fonts for the restricted xft code
* add a simple way to do multiplexing
drawing
-------
* add diacritics support to xdraws()
* add kerning configuration
* make the font cache simpler
* add hard width handling
* xft is reporting wrong width and height for characters
bugs
----
@ -21,8 +26,6 @@ bugs
* fix rows and column definition in fixed geometry
* fix -e handling
* remove DEC test sequence when appropriate
* reverse cursor when drawin light on light background
* text should be readable
* When some application outputting long text is run in the shell init scripts,
then this text might be stripped to the standard 80x25 due to st running the
virtual terminal at first priority. Maybe the vt initialisation could be

55
arg.h Normal file
View File

@ -0,0 +1,55 @@
/*
* Copy me if you can.
* by 20h
*/
#ifndef __ARG_H__
#define __ARG_H__
extern char *argv0;
#define USED(x) ((void)(x))
/* use main(int argc, char *argv[]) */
#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
argv[0] && argv[0][1]\
&& argv[0][0] == '-';\
argc--, argv++) {\
char _argc;\
char **_argv;\
int brk;\
if (argv[0][1] == '-' && argv[0][2] == '\0') {\
argv++;\
argc--;\
break;\
}\
for (brk = 0, argv[0]++, _argv = argv;\
argv[0][0] && !brk;\
argv[0]++) {\
if (_argv != argv)\
break;\
_argc = argv[0][0];\
switch (_argc)
#define ARGEND }\
USED(_argc);\
}\
USED(argv);\
USED(argc);
#define ARGC() _argc
#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\
((x), abort(), (char *)0) :\
(brk = 1, (argv[0][1] != '\0')?\
(&argv[0][1]) :\
(argc--, argv++, argv[0])))
#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\
(char *)0 :\
(brk = 1, (argv[0][1] != '\0')?\
(&argv[0][1]) :\
(argc--, argv++, argv[0])))
#endif

View File

@ -13,6 +13,9 @@ static char shell[] = "/bin/sh";
static unsigned int doubleclicktimeout = 300;
static unsigned int tripleclicktimeout = 600;
/* alt screens */
static bool allowaltscreen = true;
/* frames per second st should at maximum draw to the screen */
static unsigned int xfps = 60;
static unsigned int actionfps = 30;
@ -49,18 +52,16 @@ static const char *colorname[] = {
/* more colors can be added after 255 to use with DefaultXX */
"#cccccc",
"#333333",
};
/*
* Default colors (colorname index)
* foreground, background, cursor, unfocused cursor
* foreground, background, cursor
*/
static unsigned int defaultfg = 7;
static unsigned int defaultbg = 0;
static unsigned int defaultcs = 256;
static unsigned int defaultucs = 257;
/*
* Colors used, when the specific fg == defaultfg. So in reverse mode this

View File

@ -1,5 +1,5 @@
# st version
VERSION = 0.4
VERSION = 0.4.1
# Customize below to fit your system
@ -12,11 +12,11 @@ X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I. -I/usr/include -I${X11INC} \
$(shell pkg-config --cflags fontconfig) \
$(shell pkg-config --cflags freetype2)
`pkg-config --cflags fontconfig` \
`pkg-config --cflags freetype2`
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lutil -lXext -lXft \
$(shell pkg-config --libs fontconfig) \
$(shell pkg-config --libs freetype2)
`pkg-config --libs fontconfig` \
`pkg-config --libs freetype2`
# flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_BSD_SOURCE -D_XOPEN_SOURCE=600

7
st.1
View File

@ -3,6 +3,7 @@
st \- simple terminal
.SH SYNOPSIS
.B st
.RB [ \-a ]
.RB [ \-c
.IR class ]
.RB [ \-f
@ -23,6 +24,9 @@ st \- simple terminal
is a simple terminal emulator.
.SH OPTIONS
.TP
.B \-a
disable alternate screens in terminal
.TP
.BI \-c " class"
defines the window class (default $TERM).
.TP
@ -33,6 +37,9 @@ to use when st is run.
.TP
.BI \-g " geometry"
defines the X11 geometry string, which will fixate the height and width of st.
The form is [=][<width>{xX}<height>][{+-}<xoffset>{+-}<yoffset>]. See
.BR XParseGeometry (3)
for further details.
.TP
.BI \-o " file"
writes all the I/O to

347
st.c
View File

@ -27,6 +27,10 @@
#include <X11/Xft/Xft.h>
#include <fontconfig/fontconfig.h>
#include "arg.h"
char *argv0;
#define Glyph Glyph_
#define Font Font_
#define Draw XftDraw *
@ -41,10 +45,6 @@
#include <libutil.h>
#endif
#define USAGE \
"st " VERSION " (c) 2010-2013 st engineers\n" \
"usage: st [-v] [-c class] [-f font] [-g geometry] [-o file]" \
" [-t title] [-w windowid] [-e command ...]\n"
/* XEMBED messages */
#define XEMBED_FOCUS_IN 4
@ -98,11 +98,6 @@ enum cursor_state {
CURSOR_ORIGIN = 2
};
enum glyph_state {
GLYPH_SET = 1,
GLYPH_DIRTY = 2
};
enum term_mode {
MODE_WRAP = 1,
MODE_INSERT = 2,
@ -154,7 +149,6 @@ typedef struct {
uchar mode; /* attribute flags */
ushort fg; /* foreground */
ushort bg; /* background */
uchar state; /* state flags */
} Glyph;
typedef Glyph *Line;
@ -310,7 +304,7 @@ static void strhandle(void);
static void strparse(void);
static void strreset(void);
static void tclearregion(int, int, int, int, int);
static void tclearregion(int, int, int, int);
static void tcursor(int);
static void tdeletechar(int);
static void tdeleteline(int);
@ -757,8 +751,8 @@ bpress(XEvent *e) {
void
selcopy(void) {
char *str, *ptr, *p;
int x, y, bufsize, is_selected = 0, size;
char *str, *ptr;
int x, y, bufsize, size;
Glyph *gp, *last;
if(sel.bx == -1) {
@ -769,28 +763,34 @@ selcopy(void) {
/* append every set & selected glyph to the selection */
for(y = sel.b.y; y < sel.e.y + 1; y++) {
is_selected = 0;
gp = &term.line[y][0];
last = gp + term.col;
while(--last >= gp && !(last->state & GLYPH_SET))
while(--last >= gp && !(selected(last - gp, y) && \
strcmp(last->c, " ") != 0))
/* nothing */;
for(x = 0; gp <= last; x++, ++gp) {
if(!selected(x, y)) {
continue;
} else {
is_selected = 1;
}
p = (gp->state & GLYPH_SET) ? gp->c : " ";
size = utf8size(p);
memcpy(ptr, p, size);
size = utf8size(gp->c);
memcpy(ptr, gp->c, size);
ptr += size;
}
/* \n at the end of every selected line except for the last one */
if(is_selected && y < sel.e.y)
*ptr++ = '\r';
/*
* Copy and pasting of line endings is inconsistent
* in the inconsistent terminal and GUI world.
* The best solution seems like to produce '\n' when
* something is copied from st and convert '\n' to
* '\r', when something to be pasted is received by
* st.
* FIXME: Fix the computer world.
*/
if(y < sel.e.y)
*ptr++ = '\n';
}
*ptr = 0;
}
@ -801,7 +801,7 @@ void
selnotify(XEvent *e) {
ulong nitems, ofs, rem;
int format;
uchar *data;
uchar *data, *last, *repl;
Atom type;
ofs = 0;
@ -812,7 +812,21 @@ selnotify(XEvent *e) {
fprintf(stderr, "Clipboard allocation failed\n");
return;
}
ttywrite((const char *) data, nitems * format / 8);
/*
* As seen in selcopy:
* Line endings are inconsistent in the terminal and GUI world
* copy and pasting. When receiving some selection data,
* replace all '\n' with '\r'.
* FIXME: Fix the computer world.
*/
repl = data;
last = data + nitems * format / 8;
while((repl = memchr(repl, '\n', last - repl))) {
*repl++ = '\r';
}
ttywrite((const char *)data, nitems * format / 8);
XFree(data);
/* number of 32-bit chunks returned */
ofs += nitems * format / 32;
@ -919,13 +933,11 @@ brelease(XEvent *e) {
} else if(TIMEDIFF(now, sel.tclick1) <= doubleclicktimeout) {
/* double click to select word */
sel.bx = sel.ex;
while(sel.bx > 0 && term.line[sel.ey][sel.bx-1].state & GLYPH_SET &&
term.line[sel.ey][sel.bx-1].c[0] != ' ') {
while(sel.bx > 0 && term.line[sel.ey][sel.bx-1].c[0] != ' ') {
sel.bx--;
}
sel.b.x = sel.bx;
while(sel.ex < term.col-1 && term.line[sel.ey][sel.ex+1].state & GLYPH_SET &&
term.line[sel.ey][sel.ex+1].c[0] != ' ') {
while(sel.ex < term.col-1 && term.line[sel.ey][sel.ex+1].c[0] != ' ') {
sel.ex++;
}
sel.e.x = sel.ex;
@ -1164,30 +1176,17 @@ treset(void) {
term.bot = term.row - 1;
term.mode = MODE_WRAP;
tclearregion(0, 0, term.col-1, term.row-1, 0);
tclearregion(0, 0, term.col-1, term.row-1);
tmoveto(0, 0);
tcursor(CURSOR_SAVE);
}
void
tnew(int col, int row) {
/* set screen size */
term.row = row;
term.col = col;
term.line = xmalloc(term.row * sizeof(Line));
term.alt = xmalloc(term.row * sizeof(Line));
term.dirty = xmalloc(term.row * sizeof(*term.dirty));
term.tabs = xmalloc(term.col * sizeof(*term.tabs));
for(row = 0; row < term.row; row++) {
term.line[row] = xmalloc(term.col * sizeof(Glyph));
term.alt [row] = xmalloc(term.col * sizeof(Glyph));
term.dirty[row] = 0;
}
memset(&term, 0, sizeof(Term));
tresize(col, row);
term.numlock = 1;
memset(term.tabs, 0, term.col * sizeof(*term.tabs));
/* setup screen */
treset();
}
@ -1208,7 +1207,7 @@ tscrolldown(int orig, int n) {
LIMIT(n, 0, term.bot-orig+1);
tclearregion(0, term.bot-n+1, term.col-1, term.bot, 0);
tclearregion(0, term.bot-n+1, term.col-1, term.bot);
for(i = term.bot; i >= orig+n; i--) {
temp = term.line[i];
@ -1228,7 +1227,7 @@ tscrollup(int orig, int n) {
Line temp;
LIMIT(n, 0, term.bot-orig+1);
tclearregion(0, orig, term.col-1, orig+n-1, 0);
tclearregion(0, orig, term.col-1, orig+n-1);
for(i = orig; i <= term.bot-n; i++) {
temp = term.line[i];
@ -1362,11 +1361,10 @@ tsetchar(char *c, Glyph *attr, int x, int y) {
term.dirty[y] = 1;
term.line[y][x] = *attr;
memcpy(term.line[y][x].c, c, UTF_SIZ);
term.line[y][x].state |= GLYPH_SET;
}
void
tclearregion(int x1, int y1, int x2, int y2, int bce) {
tclearregion(int x1, int y1, int x2, int y2) {
int x, y, temp;
if(x1 > x2)
@ -1382,13 +1380,8 @@ tclearregion(int x1, int y1, int x2, int y2, int bce) {
for(y = y1; y <= y2; y++) {
term.dirty[y] = 1;
for(x = x1; x <= x2; x++) {
if(bce) {
term.line[y][x] = term.c.attr;
memcpy(term.line[y][x].c, " ", 2);
term.line[y][x].state |= GLYPH_SET;
} else {
term.line[y][x].state = 0;
}
term.line[y][x] = term.c.attr;
memcpy(term.line[y][x].c, " ", 2);
}
}
}
@ -1402,13 +1395,13 @@ tdeletechar(int n) {
term.dirty[term.c.y] = 1;
if(src >= term.col) {
tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 0);
tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
return;
}
memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src],
size * sizeof(Glyph));
tclearregion(term.col-n, term.c.y, term.col-1, term.c.y, 0);
tclearregion(term.col-n, term.c.y, term.col-1, term.c.y);
}
void
@ -1420,13 +1413,13 @@ tinsertblank(int n) {
term.dirty[term.c.y] = 1;
if(dst >= term.col) {
tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 0);
tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
return;
}
memmove(&term.line[term.c.y][dst], &term.line[term.c.y][src],
size * sizeof(Glyph));
tclearregion(src, term.c.y, dst - 1, term.c.y, 0);
tclearregion(src, term.c.y, dst - 1, term.c.y);
}
void
@ -1452,8 +1445,9 @@ tsetattr(int *attr, int l) {
for(i = 0; i < l; i++) {
switch(attr[i]) {
case 0:
term.c.attr.mode &= ~(ATTR_REVERSE | ATTR_UNDERLINE | ATTR_BOLD \
| ATTR_ITALIC | ATTR_BLINK);
term.c.attr.mode &= ~(ATTR_REVERSE | ATTR_UNDERLINE \
| ATTR_BOLD | ATTR_ITALIC \
| ATTR_BLINK);
term.c.attr.fg = defaultfg;
term.c.attr.bg = defaultbg;
break;
@ -1615,18 +1609,20 @@ tsetmode(bool priv, bool set, int *args, int narg) {
break;
case 1049: /* = 1047 and 1048 */
case 47:
case 1047: {
case 1047:
if (!allowaltscreen)
break;
alt = IS_SET(MODE_ALTSCREEN);
if(alt) {
tclearregion(0, 0, term.col-1,
term.row-1, 0);
term.row-1);
}
if(set ^ alt) /* set is always 1 or 0 */
tswapscreen();
if(*args != 1049)
break;
}
/* pass through */
/* FALLTRU */
case 1048:
tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD);
break;
@ -1739,19 +1735,19 @@ csihandle(void) {
sel.bx = -1;
switch(csiescseq.arg[0]) {
case 0: /* below */
tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 1);
tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
if(term.c.y < term.row-1) {
tclearregion(0, term.c.y+1, term.col-1,
term.row-1, 1);
term.row-1);
}
break;
case 1: /* above */
if(term.c.y > 1)
tclearregion(0, 0, term.col-1, term.c.y-1, 1);
tclearregion(0, term.c.y, term.c.x, term.c.y, 1);
tclearregion(0, 0, term.col-1, term.c.y-1);
tclearregion(0, term.c.y, term.c.x, term.c.y);
break;
case 2: /* all */
tclearregion(0, 0, term.col-1, term.row-1, 1);
tclearregion(0, 0, term.col-1, term.row-1);
break;
default:
goto unknown;
@ -1761,13 +1757,13 @@ csihandle(void) {
switch(csiescseq.arg[0]) {
case 0: /* right */
tclearregion(term.c.x, term.c.y, term.col-1,
term.c.y, 1);
term.c.y);
break;
case 1: /* left */
tclearregion(0, term.c.y, term.c.x, term.c.y, 1);
tclearregion(0, term.c.y, term.c.x, term.c.y);
break;
case 2: /* all */
tclearregion(0, term.c.y, term.col-1, term.c.y, 1);
tclearregion(0, term.c.y, term.col-1, term.c.y);
break;
}
break;
@ -1793,7 +1789,7 @@ csihandle(void) {
case 'X': /* ECH -- Erase <n> char */
DEFAULT(csiescseq.arg[0], 1);
tclearregion(term.c.x, term.c.y,
term.c.x + csiescseq.arg[0] - 1, term.c.y, 1);
term.c.x + csiescseq.arg[0] - 1, term.c.y);
break;
case 'P': /* DCH -- Delete <n> char */
DEFAULT(csiescseq.arg[0], 1);
@ -2253,11 +2249,12 @@ tputc(char *c, int len) {
int
tresize(int col, int row) {
int i, x;
int i;
int minrow = MIN(row, term.row);
int mincol = MIN(col, term.col);
int slide = term.c.y - row + 1;
bool *bp;
Line *orig;
if(col < 1 || row < 1)
return 0;
@ -2293,10 +2290,6 @@ tresize(int col, int row) {
term.dirty[i] = 1;
term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph));
for(x = mincol; x < col; x++) {
term.line[i][x].state = 0;
term.alt[i][x].state = 0;
}
}
/* allocate any new rows */
@ -2321,6 +2314,17 @@ tresize(int col, int row) {
tsetscroll(0, row-1);
/* make use of the LIMIT in tmoveto */
tmoveto(term.c.x, term.c.y);
/* Clearing both screens */
orig = term.line;
do {
if(mincol < col && 0 < minrow) {
tclearregion(mincol, 0, col - 1, minrow - 1);
}
if(0 < col && minrow < row) {
tclearregion(0, minrow, col - 1, row - 1);
}
tswapscreen();
} while(orig != term.line);
return (slide > 0);
}
@ -2333,10 +2337,8 @@ xresize(int col, int row) {
XFreePixmap(xw.dpy, xw.buf);
xw.buf = XCreatePixmap(xw.dpy, xw.win, xw.w, xw.h,
DefaultDepth(xw.dpy, xw.scr));
XSetForeground(xw.dpy, dc.gc, dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg].pixel);
XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, xw.w, xw.h);
XftDrawChange(xw.draw, xw.buf);
xclear(0, 0, xw.w, xw.h);
}
static inline ushort
@ -2924,33 +2926,47 @@ void
xdrawcursor(void) {
static int oldx = 0, oldy = 0;
int sl;
Glyph g = {{' '}, ATTR_NULL, defaultbg, defaultcs, 0};
Glyph g = {{' '}, ATTR_NULL, defaultbg, defaultcs};
LIMIT(oldx, 0, term.col-1);
LIMIT(oldy, 0, term.row-1);
if(term.line[term.c.y][term.c.x].state & GLYPH_SET)
memcpy(g.c, term.line[term.c.y][term.c.x].c, UTF_SIZ);
memcpy(g.c, term.line[term.c.y][term.c.x].c, UTF_SIZ);
/* remove the old cursor */
if(term.line[oldy][oldx].state & GLYPH_SET) {
sl = utf8size(term.line[oldy][oldx].c);
xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx,
oldy, 1, sl);
} else {
xtermclear(oldx, oldy, oldx, oldy);
}
sl = utf8size(term.line[oldy][oldx].c);
xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx,
oldy, 1, sl);
/* draw the new one */
if(!(IS_SET(MODE_HIDE))) {
if(!(xw.state & WIN_FOCUSED))
g.bg = defaultucs;
if(xw.state & WIN_FOCUSED) {
if(IS_SET(MODE_REVERSE)) {
g.mode |= ATTR_REVERSE;
g.fg = defaultcs;
g.bg = defaultfg;
}
if(IS_SET(MODE_REVERSE))
g.mode |= ATTR_REVERSE, g.fg = defaultcs, g.bg = defaultfg;
sl = utf8size(g.c);
xdraws(g.c, g, term.c.x, term.c.y, 1, sl);
sl = utf8size(g.c);
xdraws(g.c, g, term.c.x, term.c.y, 1, sl);
} else {
XftDrawRect(xw.draw, &dc.col[defaultcs],
borderpx + term.c.x * xw.cw,
borderpx + term.c.y * xw.ch,
xw.cw - 1, 1);
XftDrawRect(xw.draw, &dc.col[defaultcs],
borderpx + term.c.x * xw.cw,
borderpx + term.c.y * xw.ch,
1, xw.ch - 1);
XftDrawRect(xw.draw, &dc.col[defaultcs],
borderpx + (term.c.x + 1) * xw.cw - 1,
borderpx + term.c.y * xw.ch,
1, xw.ch - 1);
XftDrawRect(xw.draw, &dc.col[defaultcs],
borderpx + term.c.x * xw.cw,
borderpx + (term.c.y + 1) * xw.ch - 1,
xw.cw, 1);
}
oldx = term.c.x, oldy = term.c.y;
}
}
@ -3018,23 +3034,20 @@ drawregion(int x1, int y1, int x2, int y2) {
new = term.line[y][x];
if(ena_sel && *(new.c) && selected(x, y))
new.mode ^= ATTR_REVERSE;
if(ib > 0 && (!(new.state & GLYPH_SET)
|| ATTRCMP(base, new)
if(ib > 0 && (ATTRCMP(base, new)
|| ib >= DRAW_BUF_SIZ-UTF_SIZ)) {
xdraws(buf, base, ox, y, ic, ib);
ic = ib = 0;
}
if(new.state & GLYPH_SET) {
if(ib == 0) {
ox = x;
base = new;
}
sl = utf8size(new.c);
memcpy(buf+ib, new.c, sl);
ib += sl;
++ic;
if(ib == 0) {
ox = x;
base = new;
}
sl = utf8size(new.c);
memcpy(buf+ib, new.c, sl);
ib += sl;
++ic;
}
if(ib > 0)
xdraws(buf, base, ox, y, ic, ib);
@ -3306,67 +3319,67 @@ run(void) {
}
}
void
usage(void) {
die("%s " VERSION " (c) 2010-2013 st engineers\n" \
"usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]" \
" [-t title] [-w windowid] [-e command ...]\n", argv0);
}
int
main(int argc, char *argv[]) {
int i, bitm, xr, yr;
int bitm, xr, yr;
uint wr, hr;
xw.fw = xw.fh = xw.fx = xw.fy = 0;
xw.isfixed = False;
for(i = 1; i < argc; i++) {
switch(argv[i][0] != '-' || argv[i][2] ? -1 : argv[i][1]) {
case 'c':
if(++i < argc)
opt_class = argv[i];
break;
case 'e':
/* eat all remaining arguments */
if(++i < argc)
opt_cmd = &argv[i];
goto run;
case 'f':
if(++i < argc)
opt_font = argv[i];
break;
case 'g':
if(++i >= argc)
break;
ARGBEGIN {
case 'a':
allowaltscreen = false;
break;
case 'c':
opt_class = EARGF(usage());
break;
case 'e':
/* eat all remaining arguments */
if(argc > 1)
opt_cmd = &argv[1];
goto run;
case 'f':
opt_font = EARGF(usage());
break;
case 'g':
bitm = XParseGeometry(EARGF(usage()), &xr, &yr, &wr, &hr);
if(bitm & XValue)
xw.fx = xr;
if(bitm & YValue)
xw.fy = yr;
if(bitm & WidthValue)
xw.fw = (int)wr;
if(bitm & HeightValue)
xw.fh = (int)hr;
if(bitm & XNegative && xw.fx == 0)
xw.fx = -1;
if(bitm & XNegative && xw.fy == 0)
xw.fy = -1;
bitm = XParseGeometry(argv[i], &xr, &yr, &wr, &hr);
if(bitm & XValue)
xw.fx = xr;
if(bitm & YValue)
xw.fy = yr;
if(bitm & WidthValue)
xw.fw = (int)wr;
if(bitm & HeightValue)
xw.fh = (int)hr;
if(bitm & XNegative && xw.fx == 0)
xw.fx = -1;
if(bitm & XNegative && xw.fy == 0)
xw.fy = -1;
if(xw.fh != 0 && xw.fw != 0)
xw.isfixed = True;
break;
case 'o':
if(++i < argc)
opt_io = argv[i];
break;
case 't':
if(++i < argc)
opt_title = argv[i];
break;
case 'v':
default:
die(USAGE);
case 'w':
if(++i < argc)
opt_embed = argv[i];
break;
}
}
if(xw.fh != 0 && xw.fw != 0)
xw.isfixed = True;
break;
case 'o':
opt_io = EARGF(usage());
break;
case 't':
opt_title = EARGF(usage());
break;
case 'w':
opt_embed = EARGF(usage());
break;
case 'v':
default:
usage();
} ARGEND;
run:
setlocale(LC_CTYPE, "");
@ -3375,6 +3388,8 @@ run:
xinit();
ttynew();
selinit();
if(xw.isfixed)
cresize(xw.h, xw.w);
run();
return 0;