From e2ee5ee6114eb74bb08cb9abe5a3020203e92688 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Fri, 20 Jan 2017 00:06:39 -0800 Subject: Split X-specific code into x.c --- st.h | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 st.h (limited to 'st.h') diff --git a/st.h b/st.h new file mode 100644 index 0000000..44d4938 --- /dev/null +++ b/st.h @@ -0,0 +1,272 @@ +/* See LICENSE for license details. */ + +/* Arbitrary sizes */ +#define UTF_SIZ 4 + +/* macros */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#define LEN(a) (sizeof(a) / sizeof(a)[0]) +#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) +#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) +#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 || \ + (a).bg != (b).bg) +#define IS_SET(flag) ((term.mode & (flag)) != 0) +#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ + (t1.tv_nsec-t2.tv_nsec)/1E6) +#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) + +#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) +#define IS_TRUECOL(x) (1 << 24 & (x)) + +enum glyph_attribute { + ATTR_NULL = 0, + ATTR_BOLD = 1 << 0, + ATTR_FAINT = 1 << 1, + ATTR_ITALIC = 1 << 2, + ATTR_UNDERLINE = 1 << 3, + ATTR_BLINK = 1 << 4, + ATTR_REVERSE = 1 << 5, + ATTR_INVISIBLE = 1 << 6, + ATTR_STRUCK = 1 << 7, + ATTR_WRAP = 1 << 8, + ATTR_WIDE = 1 << 9, + ATTR_WDUMMY = 1 << 10, + ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, +}; + +enum term_mode { + MODE_WRAP = 1 << 0, + MODE_INSERT = 1 << 1, + MODE_APPKEYPAD = 1 << 2, + MODE_ALTSCREEN = 1 << 3, + MODE_CRLF = 1 << 4, + MODE_MOUSEBTN = 1 << 5, + MODE_MOUSEMOTION = 1 << 6, + MODE_REVERSE = 1 << 7, + MODE_KBDLOCK = 1 << 8, + MODE_HIDE = 1 << 9, + MODE_ECHO = 1 << 10, + MODE_APPCURSOR = 1 << 11, + MODE_MOUSESGR = 1 << 12, + MODE_8BIT = 1 << 13, + MODE_BLINK = 1 << 14, + MODE_FBLINK = 1 << 15, + MODE_FOCUS = 1 << 16, + MODE_MOUSEX10 = 1 << 17, + MODE_MOUSEMANY = 1 << 18, + MODE_BRCKTPASTE = 1 << 19, + MODE_PRINT = 1 << 20, + MODE_UTF8 = 1 << 21, + MODE_SIXEL = 1 << 22, + MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ + |MODE_MOUSEMANY, +}; + +enum selection_mode { + SEL_IDLE = 0, + SEL_EMPTY = 1, + SEL_READY = 2 +}; + +enum selection_type { + SEL_REGULAR = 1, + SEL_RECTANGULAR = 2 +}; + +enum selection_snap { + SNAP_WORD = 1, + SNAP_LINE = 2 +}; + +enum window_state { + WIN_VISIBLE = 1, + WIN_FOCUSED = 2 +}; + +typedef unsigned char uchar; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned short ushort; + +typedef uint_least32_t Rune; + +typedef struct { + Rune u; /* character code */ + ushort mode; /* attribute flags */ + uint32_t fg; /* foreground */ + uint32_t bg; /* background */ +} Glyph; + +typedef Glyph *Line; + +typedef struct { + Glyph attr; /* current char attributes */ + int x; + int y; + char state; +} TCursor; + +/* Internal representation of the screen */ +typedef struct { + int row; /* nb row */ + int col; /* nb col */ + Line *line; /* screen */ + Line *alt; /* alternate screen */ + int *dirty; /* dirtyness of lines */ + GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ + TCursor c; /* cursor */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ + int numlock; /* lock numbers in keyboard */ + int *tabs; +} Term; + +/* Purely graphic info */ +typedef struct { + int tw, th; /* tty width and height */ + int w, h; /* window width and height */ + int ch; /* char height */ + int cw; /* char width */ + char state; /* focus, redraw, visible */ + int cursor; /* cursor style */ +} TermWindow; + +typedef struct { + uint b; + uint mask; + char *s; +} MouseShortcut; + +typedef struct { + int mode; + int type; + int snap; + /* + * Selection variables: + * nb – normalized coordinates of the beginning of the selection + * ne – normalized coordinates of the end of the selection + * ob – original coordinates of the beginning of the selection + * oe – original coordinates of the end of the selection + */ + struct { + int x, y; + } nb, ne, ob, oe; + + char *primary, *clipboard; + int alt; + struct timespec tclick1; + struct timespec tclick2; + + //Atom xtarget; +} Selection; + +typedef union { + int i; + uint ui; + float f; + const void *v; +} Arg; + +typedef struct { + uint mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Shortcut; + +void die(const char *, ...); +void redraw(void); + +int tattrset(int); +void tnew(int, int); +void tsetdirt(int, int); +void tsetdirtattr(int); +int match(uint, uint); +void ttynew(void); +size_t ttyread(void); +void ttyresize(void); +void ttysend(char *, size_t); +void ttywrite(const char *, size_t); + +void resettitle(void); + +char *kmap(KeySym, uint); +void cresize(int, int); +void selclear(void); + +void selinit(void); +void selnormalize(void); +int selected(int, int); +char *getsel(void); +int x2col(int); +int y2row(int); + +size_t utf8decode(char *, Rune *, size_t); +size_t utf8encode(Rune, char *); + +void *xmalloc(size_t); +char *xstrdup(char *); + +void usage(void); + +/* Globals */ +extern TermWindow win; +extern Term term; +extern Selection sel; +extern int cmdfd; +extern pid_t pid; +extern char **opt_cmd; +extern char *opt_class; +extern char *opt_embed; +extern char *opt_font; +extern char *opt_io; +extern char *opt_line; +extern char *opt_name; +extern char *opt_title; +extern int oldbutton; + +extern char *usedfont; +extern double usedfontsize; +extern double defaultfontsize; + +/* config.h globals */ +extern char font[]; +extern int borderpx; +extern float cwscale; +extern float chscale; +extern unsigned int doubleclicktimeout; +extern unsigned int tripleclicktimeout; +extern int allowaltscreen; +extern unsigned int xfps; +extern unsigned int actionfps; +extern unsigned int cursorthickness; +extern unsigned int blinktimeout; +extern char termname[]; +extern const char *colorname[]; +extern size_t colornamelen; +extern unsigned int defaultfg; +extern unsigned int defaultbg; +extern unsigned int defaultcs; +extern unsigned int defaultrcs; +extern unsigned int cursorshape; +extern unsigned int cols; +extern unsigned int rows; +extern unsigned int mouseshape; +extern unsigned int mousefg; +extern unsigned int mousebg; +extern unsigned int defaultattr; +extern MouseShortcut mshortcuts[]; +extern size_t mshortcutslen; +extern Shortcut shortcuts[]; +extern size_t shortcutslen; +extern uint forceselmod; +extern uint selmasks[]; +extern size_t selmaskslen; +extern char ascii_printable[]; -- cgit v1.2.3 From 3518dba2a5fb57f601b74528ddeb67f173e4024b Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 10 Oct 2017 11:11:27 -0500 Subject: Move usage() to be with run() in x.c run/usage/xinit are now all internal to x.c Signed-off-by: Devin J. Pohly --- st.c | 15 --------------- st.h | 2 -- win.h | 2 -- x.c | 18 ++++++++++++++++++ 4 files changed, 18 insertions(+), 19 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index 668b312..6338510 100644 --- a/st.c +++ b/st.c @@ -28,8 +28,6 @@ #include #include -char *argv0; - #define Glyph Glyph_ #define Font Font_ @@ -2687,16 +2685,3 @@ cresize(int width, int height) tresize(col, row); xresize(col, row); } - -void -usage(void) -{ - die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid]" - " [[-e] command [args ...]]\n" - " %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid] -l line" - " [stty_args ...]\n", argv0, argv0); -} diff --git a/st.h b/st.h index 44d4938..28a751d 100644 --- a/st.h +++ b/st.h @@ -214,8 +214,6 @@ size_t utf8encode(Rune, char *); void *xmalloc(size_t); char *xstrdup(char *); -void usage(void); - /* Globals */ extern TermWindow win; extern Term term; diff --git a/win.h b/win.h index 423c114..60cecb1 100644 --- a/win.h +++ b/win.h @@ -9,13 +9,11 @@ typedef XftGlyphFontSpec GlyphFontSpec; void draw(void); void drawregion(int, int, int, int); -void run(void); void xbell(int); void xclipcopy(void); void xclippaste(void); void xhints(void); -void xinit(void); void xloadcols(void); int xsetcolorname(int, const char *); void xloadfonts(char *, double); diff --git a/x.c b/x.c index df2a88c..f660ca3 100644 --- a/x.c +++ b/x.c @@ -15,6 +15,7 @@ #include #include +static char *argv0; #include "arg.h" #define Glyph Glyph_ @@ -87,6 +88,7 @@ static void xdrawglyph(Glyph, int, int); static void xclear(int, int, int, int); static void xdrawcursor(void); static int xgeommasktogravity(int); +static void xinit(void); static int xloadfont(Font *, FcPattern *); static void xunloadfont(Font *); static void xsetenv(void); @@ -110,6 +112,9 @@ static void selcopy(Time); static void getbuttoninfo(XEvent *); static void mousereport(XEvent *); +static void run(void); +static void usage(void); + static void (*handler[LASTEvent])(XEvent *) = { [KeyPress] = kpress, [ClientMessage] = cmessage, @@ -1698,6 +1703,19 @@ run(void) } } +void +usage(void) +{ + die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid]" + " [[-e] command [args ...]]\n" + " %s [-aiv] [-c class] [-f font] [-g geometry]" + " [-n name] [-o file]\n" + " [-T title] [-t title] [-w windowid] -l line" + " [stty_args ...]\n", argv0, argv0); +} + int main(int argc, char *argv[]) { -- cgit v1.2.3 From d5275012b45149a2a6e94679609aacca478221ad Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 10 Oct 2017 11:30:36 -0500 Subject: Move zoom functions into x.c This makes x(un)loadfonts internal to x.c. Needed to reorder includes and move a typedef to keep the compiler happy. Signed-off-by: Devin J. Pohly --- st.c | 36 +----------------------------------- st.h | 1 + win.h | 7 +++---- x.c | 35 ++++++++++++++++++++++++++++++++++- 4 files changed, 39 insertions(+), 40 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index 6338510..f1f7bc1 100644 --- a/st.c +++ b/st.c @@ -31,8 +31,8 @@ #define Glyph Glyph_ #define Font Font_ -#include "win.h" #include "st.h" +#include "win.h" #if defined(__linux) #include @@ -128,9 +128,6 @@ static void clipcopy(const Arg *); static void clippaste(const Arg *); static void numlock(const Arg *); static void selpaste(const Arg *); -static void zoom(const Arg *); -static void zoomabs(const Arg *); -static void zoomreset(const Arg *); static void printsel(const Arg *); static void printscreen(const Arg *) ; static void iso14755(const Arg *); @@ -2573,37 +2570,6 @@ tresize(int col, int row) term.c = c; } -void -zoom(const Arg *arg) -{ - Arg larg; - - larg.f = usedfontsize + arg->f; - zoomabs(&larg); -} - -void -zoomabs(const Arg *arg) -{ - xunloadfonts(); - xloadfonts(usedfont, arg->f); - cresize(0, 0); - ttyresize(); - redraw(); - xhints(); -} - -void -zoomreset(const Arg *arg) -{ - Arg larg; - - if (defaultfontsize > 0) { - larg.f = defaultfontsize; - zoomabs(&larg); - } -} - void resettitle(void) { diff --git a/st.h b/st.h index 28a751d..9ece72f 100644 --- a/st.h +++ b/st.h @@ -100,6 +100,7 @@ typedef struct { } Glyph; typedef Glyph *Line; +typedef XftGlyphFontSpec GlyphFontSpec; typedef struct { Glyph attr; /* current char attributes */ diff --git a/win.h b/win.h index 60cecb1..ea45e60 100644 --- a/win.h +++ b/win.h @@ -5,8 +5,6 @@ #define XK_NO_MOD 0 #define XK_SWITCH_MOD (1<<13) -typedef XftGlyphFontSpec GlyphFontSpec; - void draw(void); void drawregion(int, int, int, int); @@ -16,11 +14,12 @@ void xclippaste(void); void xhints(void); void xloadcols(void); int xsetcolorname(int, const char *); -void xloadfonts(char *, double); void xsettitle(char *); void xsetpointermotion(int); void xseturgency(int); -void xunloadfonts(void); void xresize(int, int); void xselpaste(void); void xsetsel(char *, Time); +void zoom(const Arg *); +void zoomabs(const Arg *); +void zoomreset(const Arg *); diff --git a/x.c b/x.c index f660ca3..426ca28 100644 --- a/x.c +++ b/x.c @@ -21,8 +21,8 @@ static char *argv0; #define Glyph Glyph_ #define Font Font_ -#include "win.h" #include "st.h" +#include "win.h" /* XEMBED messages */ #define XEMBED_FOCUS_IN 4 @@ -90,7 +90,9 @@ static void xdrawcursor(void); static int xgeommasktogravity(int); static void xinit(void); static int xloadfont(Font *, FcPattern *); +static void xloadfonts(char *, double); static void xunloadfont(Font *); +static void xunloadfonts(void); static void xsetenv(void); static void expose(XEvent *); @@ -164,6 +166,37 @@ typedef struct { static Fontcache frc[16]; static int frclen = 0; +void +zoom(const Arg *arg) +{ + Arg larg; + + larg.f = usedfontsize + arg->f; + zoomabs(&larg); +} + +void +zoomabs(const Arg *arg) +{ + xunloadfonts(); + xloadfonts(usedfont, arg->f); + cresize(0, 0); + ttyresize(); + redraw(); + xhints(); +} + +void +zoomreset(const Arg *arg) +{ + Arg larg; + + if (defaultfontsize > 0) { + larg.f = defaultfontsize; + zoomabs(&larg); + } +} + void getbuttoninfo(XEvent *e) { -- cgit v1.2.3 From 626b0ae40c71b6c1e02ece79bf033432647381a6 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 10 Oct 2017 12:01:18 -0500 Subject: Move window urgency handling entirely into x.c This allows us to make xseturgency internal. Signed-off-by: Devin J. Pohly --- config.def.h | 2 +- st.c | 5 +---- st.h | 1 + win.h | 3 +-- x.c | 8 ++++++-- 5 files changed, 10 insertions(+), 9 deletions(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index 877afab..dd94be2 100644 --- a/config.def.h +++ b/config.def.h @@ -60,7 +60,7 @@ unsigned int cursorthickness = 2; * bell volume. It must be a value between -100 and 100. Use 0 for disabling * it */ -static int bellvolume = 0; +int bellvolume = 0; /* default TERM value */ char termname[] = "st-256color"; diff --git a/st.c b/st.c index f1f7bc1..df43fac 100644 --- a/st.c +++ b/st.c @@ -2176,10 +2176,7 @@ tcontrolcode(uchar ascii) /* backwards compatibility to xterm */ strhandle(); } else { - if (!(win.state & WIN_FOCUSED)) - xseturgency(1); - if (bellvolume) - xbell(bellvolume); + xbell(); } break; case '\033': /* ESC */ diff --git a/st.h b/st.h index 9ece72f..ad94351 100644 --- a/st.h +++ b/st.h @@ -246,6 +246,7 @@ extern int allowaltscreen; extern unsigned int xfps; extern unsigned int actionfps; extern unsigned int cursorthickness; +extern int bellvolume; extern unsigned int blinktimeout; extern char termname[]; extern const char *colorname[]; diff --git a/win.h b/win.h index ea45e60..dee0b7f 100644 --- a/win.h +++ b/win.h @@ -8,7 +8,7 @@ void draw(void); void drawregion(int, int, int, int); -void xbell(int); +void xbell(void); void xclipcopy(void); void xclippaste(void); void xhints(void); @@ -16,7 +16,6 @@ void xloadcols(void); int xsetcolorname(int, const char *); void xsettitle(char *); void xsetpointermotion(int); -void xseturgency(int); void xresize(int, int); void xselpaste(void); void xsetsel(char *, Time); diff --git a/x.c b/x.c index 426ca28..5b3c97b 100644 --- a/x.c +++ b/x.c @@ -94,6 +94,7 @@ static void xloadfonts(char *, double); static void xunloadfont(Font *); static void xunloadfonts(void); static void xsetenv(void); +static void xseturgency(int); static void expose(XEvent *); static void visibility(XEvent *); @@ -1521,9 +1522,12 @@ xseturgency(int add) } void -xbell(int vol) +xbell(void) { - XkbBell(xw.dpy, xw.win, vol, (Atom)NULL); + if (!(win.state & WIN_FOCUSED)) + xseturgency(1); + if (bellvolume) + XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); } void -- cgit v1.2.3 From a09138afa57adb4b76dba8ca72dc7ee2642a5c8d Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 10 Oct 2017 12:17:25 -0500 Subject: Move font/fontspec variables into x.c and XWindow Signed-off-by: Devin J. Pohly --- st.c | 11 ----------- st.h | 8 ++------ x.c | 18 +++++++++++++----- 3 files changed, 15 insertions(+), 22 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index df43fac..540b487 100644 --- a/st.c +++ b/st.c @@ -28,9 +28,6 @@ #include #include -#define Glyph Glyph_ -#define Font Font_ - #include "st.h" #include "win.h" @@ -196,7 +193,6 @@ static size_t utf8validate(Rune *, size_t); static char *base64dec(const char *); static ssize_t xwrite(int, const char *, size_t); -static void *xrealloc(void *, size_t); /* Globals */ TermWindow win; @@ -218,10 +214,6 @@ static CSIEscape csiescseq; static STREscape strescseq; static int iofd = 1; -char *usedfont = NULL; -double usedfontsize = 0; -double defaultfontsize = 0; - static uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; @@ -2516,9 +2508,6 @@ tresize(int col, int row) free(term.alt[i]); } - /* resize to new width */ - term.specbuf = xrealloc(term.specbuf, col * sizeof(GlyphFontSpec)); - /* resize to new height */ term.line = xrealloc(term.line, row * sizeof(Line)); term.alt = xrealloc(term.alt, row * sizeof(Line)); diff --git a/st.h b/st.h index ad94351..2199c13 100644 --- a/st.h +++ b/st.h @@ -92,6 +92,7 @@ typedef unsigned short ushort; typedef uint_least32_t Rune; +#define Glyph Glyph_ typedef struct { Rune u; /* character code */ ushort mode; /* attribute flags */ @@ -100,7 +101,6 @@ typedef struct { } Glyph; typedef Glyph *Line; -typedef XftGlyphFontSpec GlyphFontSpec; typedef struct { Glyph attr; /* current char attributes */ @@ -116,7 +116,6 @@ typedef struct { Line *line; /* screen */ Line *alt; /* alternate screen */ int *dirty; /* dirtyness of lines */ - GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ TCursor c; /* cursor */ int top; /* top scroll limit */ int bot; /* bottom scroll limit */ @@ -213,6 +212,7 @@ size_t utf8decode(char *, Rune *, size_t); size_t utf8encode(Rune, char *); void *xmalloc(size_t); +void *xrealloc(void *, size_t); char *xstrdup(char *); /* Globals */ @@ -231,10 +231,6 @@ extern char *opt_name; extern char *opt_title; extern int oldbutton; -extern char *usedfont; -extern double usedfontsize; -extern double defaultfontsize; - /* config.h globals */ extern char font[]; extern int borderpx; diff --git a/x.c b/x.c index 5b3c97b..186e408 100644 --- a/x.c +++ b/x.c @@ -17,10 +17,6 @@ static char *argv0; #include "arg.h" - -#define Glyph Glyph_ -#define Font Font_ - #include "st.h" #include "win.h" @@ -35,6 +31,7 @@ static char *argv0; typedef XftDraw *Draw; typedef XftColor Color; +typedef XftGlyphFontSpec GlyphFontSpec; /* Purely graphic info */ typedef struct { @@ -42,6 +39,7 @@ typedef struct { Colormap cmap; Window win; Drawable buf; + GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ Atom xembed, wmdeletewin, netwmname, netwmpid; XIM xim; XIC xic; @@ -59,6 +57,7 @@ typedef struct { } XSelection; /* Font structure */ +#define Font Font_ typedef struct { int height; int width; @@ -166,6 +165,9 @@ typedef struct { /* Fontcache is an array now. A new font will be appended to the array. */ static Fontcache frc[16]; static int frclen = 0; +static char *usedfont = NULL; +static double usedfontsize = 0; +static double defaultfontsize = 0; void zoom(const Arg *arg) @@ -605,6 +607,9 @@ xresize(int col, int row) DefaultDepth(xw.dpy, xw.scr)); XftDrawChange(xw.draw, xw.buf); xclear(0, 0, win.w, win.h); + + /* resize to new width */ + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); } ushort @@ -965,6 +970,9 @@ xinit(void) XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); + /* font spec buffer */ + xw.specbuf = xmalloc(term.col * sizeof(GlyphFontSpec)); + /* Xft rendering context */ xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); @@ -1456,7 +1464,7 @@ drawregion(int x1, int y1, int x2, int y2) term.dirty[y] = 0; - specs = term.specbuf; + specs = xw.specbuf; numspecs = xmakeglyphfontspecs(specs, &term.line[y][x1], x2 - x1, x1, y); i = ox = 0; -- cgit v1.2.3 From a8314643b1aeaa2187dad71dc5748aaac1760c1b Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 10 Oct 2017 12:46:53 -0500 Subject: Move window-manipulating functions into x.c xresize is now internal to x.c Signed-off-by: Devin J. Pohly --- st.c | 36 ------------------------------------ st.h | 9 +-------- win.h | 1 - x.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 45 insertions(+), 46 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index 540b487..75c191d 100644 --- a/st.c +++ b/st.c @@ -165,7 +165,6 @@ static void tnewline(int); static void tputtab(int); static void tputc(Rune); static void treset(void); -static void tresize(int, int); static void tscrollup(int, int); static void tscrolldown(int, int); static void tsetattr(int *, int); @@ -419,24 +418,6 @@ selinit(void) sel.clipboard = NULL; } -int -x2col(int x) -{ - x -= borderpx; - x /= win.cw; - - return LIMIT(x, 0, term.col-1); -} - -int -y2row(int y) -{ - y -= borderpx; - y /= win.ch; - - return LIMIT(y, 0, term.row-1); -} - int tlinelen(int y) { @@ -2620,20 +2601,3 @@ kmap(KeySym k, uint state) return NULL; } - -void -cresize(int width, int height) -{ - int col, row; - - if (width != 0) - win.w = width; - if (height != 0) - win.h = height; - - col = (win.w - 2 * borderpx) / win.cw; - row = (win.h - 2 * borderpx) / win.ch; - - tresize(col, row); - xresize(col, row); -} diff --git a/st.h b/st.h index 2199c13..5d44411 100644 --- a/st.h +++ b/st.h @@ -80,11 +80,6 @@ enum selection_snap { SNAP_LINE = 2 }; -enum window_state { - WIN_VISIBLE = 1, - WIN_FOCUSED = 2 -}; - typedef unsigned char uchar; typedef unsigned int uint; typedef unsigned long ulong; @@ -186,6 +181,7 @@ void redraw(void); int tattrset(int); void tnew(int, int); +void tresize(int, int); void tsetdirt(int, int); void tsetdirtattr(int); int match(uint, uint); @@ -198,15 +194,12 @@ void ttywrite(const char *, size_t); void resettitle(void); char *kmap(KeySym, uint); -void cresize(int, int); void selclear(void); void selinit(void); void selnormalize(void); int selected(int, int); char *getsel(void); -int x2col(int); -int y2row(int); size_t utf8decode(char *, Rune *, size_t); size_t utf8encode(Rune, char *); diff --git a/win.h b/win.h index dee0b7f..00113c5 100644 --- a/win.h +++ b/win.h @@ -16,7 +16,6 @@ void xloadcols(void); int xsetcolorname(int, const char *); void xsettitle(char *); void xsetpointermotion(int); -void xresize(int, int); void xselpaste(void); void xsetsel(char *, Time); void zoom(const Arg *); diff --git a/x.c b/x.c index 186e408..01ef1b0 100644 --- a/x.c +++ b/x.c @@ -88,12 +88,16 @@ static void xclear(int, int, int, int); static void xdrawcursor(void); static int xgeommasktogravity(int); static void xinit(void); +static void cresize(int, int); +static void xresize(int, int); static int xloadfont(Font *, FcPattern *); static void xloadfonts(char *, double); static void xunloadfont(Font *); static void xunloadfonts(void); static void xsetenv(void); static void xseturgency(int); +static int x2col(int); +static int y2row(int); static void expose(XEvent *); static void visibility(XEvent *); @@ -109,7 +113,6 @@ static void propnotify(XEvent *); static void selnotify(XEvent *); static void selclear_(XEvent *); static void selrequest(XEvent *); - static void selcopy(Time); static void getbuttoninfo(XEvent *); static void mousereport(XEvent *); @@ -148,6 +151,11 @@ static DC dc; static XWindow xw; static XSelection xsel; +enum window_state { + WIN_VISIBLE = 1, + WIN_FOCUSED = 2 +}; + /* Font Ring Cache */ enum { FRC_NORMAL, @@ -200,6 +208,24 @@ zoomreset(const Arg *arg) } } +int +x2col(int x) +{ + x -= borderpx; + x /= win.cw; + + return LIMIT(x, 0, term.col-1); +} + +int +y2row(int y) +{ + y -= borderpx; + y /= win.ch; + + return LIMIT(y, 0, term.row-1); +} + void getbuttoninfo(XEvent *e) { @@ -596,6 +622,23 @@ bmotion(XEvent *e) tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); } +void +cresize(int width, int height) +{ + int col, row; + + if (width != 0) + win.w = width; + if (height != 0) + win.h = height; + + col = (win.w - 2 * borderpx) / win.cw; + row = (win.h - 2 * borderpx) / win.ch; + + tresize(col, row); + xresize(col, row); +} + void xresize(int col, int row) { -- cgit v1.2.3 From dbe8676d7d69651132bde2b6d9ec3787cbbc552a Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 10 Oct 2017 15:51:23 -0500 Subject: Pass new dimensions into ttyresize This removes another reference to TermWindow from st.c. Signed-off-by: Devin J. Pohly --- st.c | 6 +++--- st.h | 2 +- x.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index 75c191d..839dc94 100644 --- a/st.c +++ b/st.c @@ -905,14 +905,14 @@ ttysend(char *s, size_t n) } void -ttyresize(void) +ttyresize(int tw, int th) { struct winsize w; w.ws_row = term.row; w.ws_col = term.col; - w.ws_xpixel = win.tw; - w.ws_ypixel = win.th; + w.ws_xpixel = tw; + w.ws_ypixel = th; if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); } diff --git a/st.h b/st.h index 5d44411..372462d 100644 --- a/st.h +++ b/st.h @@ -187,7 +187,7 @@ void tsetdirtattr(int); int match(uint, uint); void ttynew(void); size_t ttyread(void); -void ttyresize(void); +void ttyresize(int, int); void ttysend(char *, size_t); void ttywrite(const char *, size_t); diff --git a/x.c b/x.c index 01ef1b0..1b656ac 100644 --- a/x.c +++ b/x.c @@ -192,7 +192,7 @@ zoomabs(const Arg *arg) xunloadfonts(); xloadfonts(usedfont, arg->f); cresize(0, 0); - ttyresize(); + ttyresize(win.tw, win.th); redraw(); xhints(); } @@ -1679,7 +1679,7 @@ resize(XEvent *e) return; cresize(e->xconfigure.width, e->xconfigure.height); - ttyresize(); + ttyresize(win.tw, win.th); } void @@ -1710,7 +1710,7 @@ run(void) cresize(w, h); ttynew(); - ttyresize(); + ttyresize(win.tw, win.th); clock_gettime(CLOCK_MONOTONIC, &last); lastblink = last; -- cgit v1.2.3 From ed132e11271d18a5d8aa163096bc6192c694bc47 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Wed, 11 Oct 2017 08:47:14 -0500 Subject: Move key-matching functions into x.c Modifiers and keysyms are specific to X, and the functions match and kmap are only used in x.c. Needed to global-ize the key arrays and lengths from config.h (for now). Signed-off-by: Devin J. Pohly --- config.def.h | 6 +++--- st.c | 58 ++-------------------------------------------------------- st.h | 18 +++++++++++++++--- x.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 62 deletions(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index dd94be2..18cb31c 100644 --- a/config.def.h +++ b/config.def.h @@ -209,13 +209,13 @@ Shortcut shortcuts[] = { * 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 }; +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; +uint ignoremod = Mod2Mask|XK_SWITCH_MOD; /* * Override mouse-select while mask is active (when MODE_MOUSE is set). @@ -228,7 +228,7 @@ uint forceselmod = ShiftMask; * This is the huge key array which defines all compatibility to the Linux * world. Please decide about changes wisely. */ -static Key key[] = { +Key key[] = { /* keysym mask string appkey appcursor crlf */ { XK_KP_Home, ShiftMask, "\033[2J", 0, -1, 0}, { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1, 0}, diff --git a/st.c b/st.c index 839dc94..1a8fa1f 100644 --- a/st.c +++ b/st.c @@ -110,16 +110,6 @@ typedef struct { int narg; /* nb of args */ } STREscape; -typedef struct { - KeySym k; - uint mask; - char *s; - /* three valued logic variables: 0 indifferent, 1 on, -1 off */ - signed char appkey; /* application keypad */ - signed char appcursor; /* application cursor */ - signed char crlf; /* crlf mode */ -} Key; - /* function definitions used in config.h */ static void clipcopy(const Arg *); static void clippaste(const Arg *); @@ -223,6 +213,8 @@ size_t colornamelen = LEN(colorname); size_t mshortcutslen = LEN(mshortcuts); size_t shortcutslen = LEN(shortcuts); size_t selmaskslen = LEN(selmasks); +size_t keyslen = LEN(key); +size_t mappedkeyslen = LEN(mappedkeys); ssize_t xwrite(int fd, const char *s, size_t len) @@ -2550,54 +2542,8 @@ redraw(void) draw(); } -int -match(uint mask, uint state) -{ - return mask == XK_ANY_MOD || mask == (state & ~ignoremod); -} - void numlock(const Arg *dummy) { term.numlock ^= 1; } - -char* -kmap(KeySym k, uint state) -{ - Key *kp; - int i; - - /* Check for mapped keys out of X11 function keys. */ - for (i = 0; i < LEN(mappedkeys); i++) { - if (mappedkeys[i] == k) - break; - } - if (i == LEN(mappedkeys)) { - if ((k & 0xFFFF) < 0xFD00) - return NULL; - } - - for (kp = key; kp < key + LEN(key); kp++) { - if (kp->k != k) - continue; - - if (!match(kp->mask, state)) - continue; - - if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) - continue; - if (term.numlock && kp->appkey == 2) - continue; - - if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) - continue; - - if (IS_SET(MODE_CRLF) ? kp->crlf < 0 : kp->crlf > 0) - continue; - - return kp->s; - } - - return NULL; -} diff --git a/st.h b/st.h index 372462d..c255b7c 100644 --- a/st.h +++ b/st.h @@ -176,6 +176,16 @@ typedef struct { const Arg arg; } Shortcut; +typedef struct { + KeySym k; + uint mask; + char *s; + /* three valued logic variables: 0 indifferent, 1 on, -1 off */ + signed char appkey; /* application keypad */ + signed char appcursor; /* application cursor */ + signed char crlf; /* crlf mode */ +} Key; + void die(const char *, ...); void redraw(void); @@ -184,7 +194,6 @@ void tnew(int, int); void tresize(int, int); void tsetdirt(int, int); void tsetdirtattr(int); -int match(uint, uint); void ttynew(void); size_t ttyread(void); void ttyresize(int, int); @@ -193,9 +202,7 @@ void ttywrite(const char *, size_t); void resettitle(void); -char *kmap(KeySym, uint); void selclear(void); - void selinit(void); void selnormalize(void); int selected(int, int); @@ -255,7 +262,12 @@ extern MouseShortcut mshortcuts[]; extern size_t mshortcutslen; extern Shortcut shortcuts[]; extern size_t shortcutslen; +extern KeySym mappedkeys[]; +extern size_t mappedkeyslen; +extern uint ignoremod; extern uint forceselmod; +extern Key key[]; +extern size_t keyslen; extern uint selmasks[]; extern size_t selmaskslen; extern char ascii_printable[]; diff --git a/x.c b/x.c index 1b656ac..371a467 100644 --- a/x.c +++ b/x.c @@ -116,6 +116,8 @@ static void selrequest(XEvent *); static void selcopy(Time); static void getbuttoninfo(XEvent *); static void mousereport(XEvent *); +static char *kmap(KeySym, uint); +static int match(uint, uint); static void run(void); static void usage(void); @@ -1603,6 +1605,52 @@ focus(XEvent *ev) } } +int +match(uint mask, uint state) +{ + return mask == XK_ANY_MOD || mask == (state & ~ignoremod); +} + +char* +kmap(KeySym k, uint state) +{ + Key *kp; + int i; + + /* Check for mapped keys out of X11 function keys. */ + for (i = 0; i < mappedkeyslen; i++) { + if (mappedkeys[i] == k) + break; + } + if (i == mappedkeyslen) { + if ((k & 0xFFFF) < 0xFD00) + return NULL; + } + + for (kp = key; kp < key + keyslen; kp++) { + if (kp->k != k) + continue; + + if (!match(kp->mask, state)) + continue; + + if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) + continue; + if (term.numlock && kp->appkey == 2) + continue; + + if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) + continue; + + if (IS_SET(MODE_CRLF) ? kp->crlf < 0 : kp->crlf > 0) + continue; + + return kp->s; + } + + return NULL; +} + void kpress(XEvent *ev) { -- cgit v1.2.3 From 69e32a61df15787c410a48eaa10a89240c36257d Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 12 Oct 2017 22:25:49 -0500 Subject: Move opt_* into same file as main()/run() This commit is purely about reducing externs and LOC. If the main and run functions ever move elsewhere (which will probably make sense eventually), these should come along with them. Signed-off-by: Devin J. Pohly --- st.c | 50 ++++++++++++++++++++------------------------------ st.h | 11 ++--------- x.c | 12 +++++++++++- 3 files changed, 33 insertions(+), 40 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index 1a8fa1f..58f7941 100644 --- a/st.c +++ b/st.c @@ -48,7 +48,6 @@ /* macros */ #define NUMMAXLEN(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) -#define DEFAULT(a, b) (a) = (a) ? (a) : (b) #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) @@ -124,8 +123,8 @@ static void sendbreak(const Arg *); /* config.h for applying patches and the configuration. */ #include "config.h" -static void execsh(void); -static void stty(void); +static void execsh(char **); +static void stty(char **); static void sigchld(int); static void csidump(void); @@ -189,14 +188,6 @@ Term term; Selection sel; int cmdfd; pid_t pid; -char **opt_cmd = NULL; -char *opt_class = NULL; -char *opt_embed = NULL; -char *opt_font = NULL; -char *opt_io = NULL; -char *opt_line = NULL; -char *opt_name = NULL; -char *opt_title = NULL; int oldbutton = 3; /* button event on startup: 3 = release */ static CSIEscape csiescseq; @@ -634,9 +625,9 @@ die(const char *errstr, ...) } void -execsh(void) +execsh(char **args) { - char **args, *sh, *prog; + char *sh, *prog; const struct passwd *pw; errno = 0; @@ -650,13 +641,13 @@ execsh(void) if ((sh = getenv("SHELL")) == NULL) sh = (pw->pw_shell[0]) ? pw->pw_shell : shell; - if (opt_cmd) - prog = opt_cmd[0]; + if (args) + prog = args[0]; else if (utmp) prog = utmp; else prog = sh; - args = (opt_cmd) ? opt_cmd : (char *[]) {prog, NULL}; + DEFAULT(args, ((char *[]) {prog, NULL})); unsetenv("COLUMNS"); unsetenv("LINES"); @@ -697,7 +688,7 @@ sigchld(int a) void -stty(void) +stty(char **args) { char cmd[_POSIX_ARG_MAX], **p, *q, *s; size_t n, siz; @@ -707,7 +698,7 @@ stty(void) memcpy(cmd, stty_args, n); q = cmd + n; siz = sizeof(cmd) - n; - for (p = opt_cmd; p && (s = *p); ++p) { + for (p = args; p && (s = *p); ++p) { if ((n = strlen(s)) > siz-1) die("stty parameter length too long\n"); *q++ = ' '; @@ -721,26 +712,26 @@ stty(void) } void -ttynew(void) +ttynew(char *line, char *out, char **args) { int m, s; struct winsize w = {term.row, term.col, 0, 0}; - if (opt_io) { + if (out) { term.mode |= MODE_PRINT; - iofd = (!strcmp(opt_io, "-")) ? - 1 : open(opt_io, O_WRONLY | O_CREAT, 0666); + iofd = (!strcmp(out, "-")) ? + 1 : open(out, O_WRONLY | O_CREAT, 0666); if (iofd < 0) { fprintf(stderr, "Error opening %s:%s\n", - opt_io, strerror(errno)); + out, strerror(errno)); } } - if (opt_line) { - if ((cmdfd = open(opt_line, O_RDWR)) < 0) + if (line) { + if ((cmdfd = open(line, O_RDWR)) < 0) die("open line failed: %s\n", strerror(errno)); dup2(cmdfd, 0); - stty(); + stty(args); return; } @@ -762,7 +753,7 @@ ttynew(void) die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); close(s); close(m); - execsh(); + execsh(args); break; default: close(s); @@ -1942,8 +1933,7 @@ void tprinter(char *s, size_t len) { if (iofd != -1 && xwrite(iofd, s, len) < 0) { - fprintf(stderr, "Error writing in %s:%s\n", - opt_io, strerror(errno)); + perror("Error writing to output file"); close(iofd); iofd = -1; } @@ -2532,7 +2522,7 @@ tresize(int col, int row) void resettitle(void) { - xsettitle(opt_title ? opt_title : "st"); + xsettitle(NULL); } void diff --git a/st.h b/st.h index c255b7c..09473c2 100644 --- a/st.h +++ b/st.h @@ -9,6 +9,7 @@ #define LEN(a) (sizeof(a) / sizeof(a)[0]) #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) #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 || \ (a).bg != (b).bg) @@ -194,7 +195,7 @@ void tnew(int, int); void tresize(int, int); void tsetdirt(int, int); void tsetdirtattr(int); -void ttynew(void); +void ttynew(char *, char *, char **); size_t ttyread(void); void ttyresize(int, int); void ttysend(char *, size_t); @@ -221,14 +222,6 @@ extern Term term; extern Selection sel; extern int cmdfd; extern pid_t pid; -extern char **opt_cmd; -extern char *opt_class; -extern char *opt_embed; -extern char *opt_font; -extern char *opt_io; -extern char *opt_line; -extern char *opt_name; -extern char *opt_title; extern int oldbutton; /* config.h globals */ diff --git a/x.c b/x.c index 371a467..e267961 100644 --- a/x.c +++ b/x.c @@ -179,6 +179,15 @@ static char *usedfont = NULL; static double usedfontsize = 0; static double defaultfontsize = 0; +static char *opt_class = NULL; +static char **opt_cmd = NULL; +static char *opt_embed = NULL; +static char *opt_font = NULL; +static char *opt_io = NULL; +static char *opt_line = NULL; +static char *opt_name = NULL; +static char *opt_title = NULL; + void zoom(const Arg *arg) { @@ -1473,6 +1482,7 @@ void xsettitle(char *p) { XTextProperty prop; + DEFAULT(p, "st"); Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop); @@ -1757,7 +1767,7 @@ run(void) } while (ev.type != MapNotify); cresize(w, h); - ttynew(); + ttynew(opt_line, opt_io, opt_cmd); ttyresize(win.tw, win.th); clock_gettime(CLOCK_MONOTONIC, &last); -- cgit v1.2.3 From 32d3b1d00f66eda4f5446f3b32cabed2c9a77a40 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sun, 15 Oct 2017 20:35:48 -0500 Subject: Factor out equivalent code from ttyread/ttysend The echo-to-terminal portions of ttyread and ttysend were actually doing the same thing. New function twrite() now handles this. The parameter show_ctrl determines whether control characters are shown as "^A". This was the only difference between tputc and techo, and techo is now unused and removed. (This commit should not change st's behaviour.) Signed-off-by: Devin J. Pohly --- st.c | 101 +++++++++++++++++++++++++++---------------------------------------- st.h | 2 +- 2 files changed, 41 insertions(+), 62 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index 58f7941..641f896 100644 --- a/st.c +++ b/st.c @@ -161,8 +161,8 @@ static void tsetchar(Rune, Glyph *, int, int); static void tsetscroll(int, int); static void tswapscreen(void); static void tsetmode(int, int, int *, int); +static int twrite(const char *, int, int); static void tfulldirt(void); -static void techo(Rune); static void tcontrolcode(uchar ); static void tdectest(char ); static void tdefutf8(char); @@ -254,7 +254,7 @@ xstrdup(char *s) } size_t -utf8decode(char *c, Rune *u, size_t clen) +utf8decode(const char *c, Rune *u, size_t clen) { size_t i, j, len, type; Rune udecoded; @@ -768,38 +768,19 @@ ttyread(void) { static char buf[BUFSIZ]; static int buflen = 0; - char *ptr; - int charsize; /* size of utf8 char in bytes */ - Rune unicodep; + int written; int ret; /* append read bytes to unprocessed bytes */ if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0) die("Couldn't read from shell: %s\n", strerror(errno)); - buflen += ret; - ptr = buf; - for (;;) { - if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) { - /* process a complete utf8 char */ - charsize = utf8decode(ptr, &unicodep, buflen); - if (charsize == 0) - break; - tputc(unicodep); - ptr += charsize; - buflen -= charsize; - - } else { - if (buflen <= 0) - break; - tputc(*ptr++ & 0xFF); - buflen--; - } - } + written = twrite(buf, buflen, 0); + buflen -= written; /* keep any uncomplete utf8 char for the next call */ if (buflen > 0) - memmove(buf, ptr, buflen); + memmove(buf, buf + written, buflen); return ret; } @@ -864,27 +845,9 @@ write_error: void ttysend(char *s, size_t n) { - int len; - char *t, *lim; - Rune u; - ttywrite(s, n); - if (!IS_SET(MODE_ECHO)) - return; - - lim = &s[n]; - for (t = s; t < lim; t += len) { - if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) { - len = utf8decode(t, &u, n); - } else { - u = *t & 0xFF; - len = 1; - } - if (len <= 0) - break; - techo(u); - n -= len; - } + if (IS_SET(MODE_ECHO)) + twrite(s, n, 1); } void @@ -2031,22 +1994,6 @@ tputtab(int n) term.c.x = LIMIT(x, 0, term.col-1); } -void -techo(Rune u) -{ - if (ISCONTROL(u)) { /* control code */ - if (u & 0x80) { - u &= 0x7f; - tputc('^'); - tputc('['); - } else if (u != '\n' && u != '\r' && u != '\t') { - u ^= 0x40; - tputc('^'); - } - } - tputc(u); -} - void tdefutf8(char ascii) { @@ -2437,6 +2384,38 @@ check_control_code: } } +int +twrite(const char *buf, int buflen, int show_ctrl) +{ + int charsize; + Rune u; + int n; + + for (n = 0; n < buflen; n += charsize) { + if (IS_SET(MODE_UTF8) && !IS_SET(MODE_SIXEL)) { + /* process a complete utf8 char */ + charsize = utf8decode(buf + n, &u, buflen - n); + if (charsize == 0) + break; + } else { + u = buf[n] & 0xFF; + charsize = 1; + } + if (show_ctrl && ISCONTROL(u)) { + if (u & 0x80) { + u &= 0x7f; + tputc('^'); + tputc('['); + } else if (u != '\n' && u != '\r' && u != '\t') { + u ^= 0x40; + tputc('^'); + } + } + tputc(u); + } + return n; +} + void tresize(int col, int row) { diff --git a/st.h b/st.h index 09473c2..3d9b6e7 100644 --- a/st.h +++ b/st.h @@ -209,7 +209,7 @@ void selnormalize(void); int selected(int, int); char *getsel(void); -size_t utf8decode(char *, Rune *, size_t); +size_t utf8decode(const char *, Rune *, size_t); size_t utf8encode(Rune, char *); void *xmalloc(size_t); -- cgit v1.2.3 From 65976c1a29f2945c3cfb6af74cd6440cf193021d Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 17 Oct 2017 15:21:04 -0500 Subject: Move config.h include from st.c to x.c config.h includes references to KeySyms and other X stuff. Until we come up with a cleaner way to separate configuration, it is simpler (leads to more code removal) to have this here. Signed-off-by: Devin J. Pohly --- config.def.h | 73 ++++++++++++++++++++++++++++++------------------------------ st.c | 47 ++++---------------------------------- st.h | 50 ++++++++++++----------------------------- win.h | 3 --- x.c | 37 ++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 119 deletions(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index 18cb31c..1c181ab 100644 --- a/config.def.h +++ b/config.def.h @@ -5,8 +5,8 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -char font[] = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; -int borderpx = 2; +static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static int borderpx = 2; /* * What program is execed by st depends of these precedence rules: @@ -16,54 +16,54 @@ int borderpx = 2; * 4: value of shell in /etc/passwd * 5: value of shell in config.h */ -static char shell[] = "/bin/sh"; -static char *utmp = NULL; -static char stty_args[] = "stty raw pass8 nl -echo -iexten -cstopb 38400"; +char *shell = "/bin/sh"; +char *utmp = NULL; +char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; /* identification sequence returned in DA and DECID */ -static char vtiden[] = "\033[?6c"; +char *vtiden = "\033[?6c"; /* Kerning / character bounding-box multipliers */ -float cwscale = 1.0; -float chscale = 1.0; +static float cwscale = 1.0; +static float chscale = 1.0; /* * word delimiter string * * More advanced example: " `'\"()[]{}" */ -static char worddelimiters[] = " "; +char *worddelimiters = " "; /* selection timeouts (in milliseconds) */ -unsigned int doubleclicktimeout = 300; -unsigned int tripleclicktimeout = 600; +static unsigned int doubleclicktimeout = 300; +static unsigned int tripleclicktimeout = 600; /* alt screens */ int allowaltscreen = 1; /* frames per second st should at maximum draw to the screen */ -unsigned int xfps = 120; -unsigned int actionfps = 30; +static unsigned int xfps = 120; +static unsigned int actionfps = 30; /* * blinking timeout (set to 0 to disable blinking) for the terminal blinking * attribute. */ -unsigned int blinktimeout = 800; +static unsigned int blinktimeout = 800; /* * thickness of underline and bar cursors */ -unsigned int cursorthickness = 2; +static unsigned int cursorthickness = 2; /* * bell volume. It must be a value between -100 and 100. Use 0 for disabling * it */ -int bellvolume = 0; +static int bellvolume = 0; /* default TERM value */ -char termname[] = "st-256color"; +char *termname = "st-256color"; /* * spaces per tab @@ -80,10 +80,10 @@ char termname[] = "st-256color"; * * stty tabs */ -static unsigned int tabspaces = 8; +unsigned int tabspaces = 8; /* Terminal colors (16 first used in escape sequence) */ -const char *colorname[] = { +static const char *colorname[] = { /* 8 normal colors */ "black", "red3", @@ -118,8 +118,8 @@ const char *colorname[] = { */ unsigned int defaultfg = 7; unsigned int defaultbg = 0; -unsigned int defaultcs = 256; -unsigned int defaultrcs = 257; +static unsigned int defaultcs = 256; +static unsigned int defaultrcs = 257; /* * Default shape of cursor @@ -128,33 +128,33 @@ unsigned int defaultrcs = 257; * 6: Bar ("|") * 7: Snowman ("☃") */ -unsigned int cursorshape = 2; +static unsigned int cursorshape = 2; /* * Default columns and rows numbers */ -unsigned int cols = 80; -unsigned int rows = 24; +static unsigned int cols = 80; +static unsigned int rows = 24; /* * Default colour and shape of the mouse cursor */ -unsigned int mouseshape = XC_xterm; -unsigned int mousefg = 7; -unsigned int mousebg = 0; +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. */ -unsigned int defaultattr = 11; +static unsigned int defaultattr = 11; /* * Internal mouse shortcuts. * Beware that overloading Button1 will disable the selection. */ -MouseShortcut mshortcuts[] = { +static MouseShortcut mshortcuts[] = { /* button mask string */ { Button4, XK_ANY_MOD, "\031" }, { Button5, XK_ANY_MOD, "\005" }, @@ -164,7 +164,7 @@ MouseShortcut mshortcuts[] = { #define MODKEY Mod1Mask #define TERMMOD (ControlMask|ShiftMask) -Shortcut shortcuts[] = { +static Shortcut shortcuts[] = { /* mask keysym function argument */ { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, { ControlMask, XK_Print, toggleprinter, {.i = 0} }, @@ -209,26 +209,26 @@ Shortcut shortcuts[] = { * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) * to be mapped below, add them to this array. */ -KeySym mappedkeys[] = { -1 }; +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. */ -uint ignoremod = Mod2Mask|XK_SWITCH_MOD; +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; /* * Override mouse-select 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. */ -uint forceselmod = ShiftMask; +static uint forceselmod = ShiftMask; /* * This is the huge key array which defines all compatibility to the Linux * world. Please decide about changes wisely. */ -Key key[] = { +static Key key[] = { /* keysym mask string appkey appcursor crlf */ { XK_KP_Home, ShiftMask, "\033[2J", 0, -1, 0}, { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1, 0}, @@ -451,7 +451,7 @@ Key key[] = { * ButtonRelease and MotionNotify. * If no match is found, regular selection is used. */ -uint selmasks[] = { +static uint selmasks[] = { [SEL_RECTANGULAR] = Mod1Mask, }; @@ -459,8 +459,7 @@ uint selmasks[] = { * Printable characters in ASCII, used to estimate the advance width * of single wide characters. */ -char ascii_printable[] = +static char ascii_printable[] = " !\"#$%&'()*+,-./0123456789:;<=>?" "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" "`abcdefghijklmnopqrstuvwxyz{|}~"; - diff --git a/st.c b/st.c index 641f896..ec747cc 100644 --- a/st.c +++ b/st.c @@ -109,19 +109,6 @@ typedef struct { int narg; /* nb of args */ } STREscape; -/* function definitions used in config.h */ -static void clipcopy(const Arg *); -static void clippaste(const Arg *); -static void numlock(const Arg *); -static void selpaste(const Arg *); -static void printsel(const Arg *); -static void printscreen(const Arg *) ; -static void iso14755(const Arg *); -static void toggleprinter(const Arg *); -static void sendbreak(const Arg *); - -/* config.h for applying patches and the configuration. */ -#include "config.h" static void execsh(char **); static void stty(char **); @@ -199,14 +186,6 @@ static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; -/* config.h array lengths */ -size_t colornamelen = LEN(colorname); -size_t mshortcutslen = LEN(mshortcuts); -size_t shortcutslen = LEN(shortcuts); -size_t selmaskslen = LEN(selmasks); -size_t keyslen = LEN(key); -size_t mappedkeyslen = LEN(mappedkeys); - ssize_t xwrite(int fd, const char *s, size_t len) { @@ -585,24 +564,6 @@ getsel(void) return str; } -void -selpaste(const Arg *dummy) -{ - xselpaste(); -} - -void -clipcopy(const Arg *dummy) -{ - xclipcopy(); -} - -void -clippaste(const Arg *dummy) -{ - xclippaste(); -} - void selclear(void) { @@ -1572,7 +1533,7 @@ csihandle(void) break; case 'c': /* DA -- Device Attributes */ if (csiescseq.arg[0] == 0) - ttywrite(vtiden, sizeof(vtiden) - 1); + ttywrite(vtiden, strlen(vtiden)); break; case 'C': /* CUF -- Cursor Forward */ case 'a': /* HPR -- Cursor Forward */ @@ -1791,7 +1752,7 @@ strhandle(void) dec = base64dec(strescseq.args[2]); if (dec) { xsetsel(dec, CurrentTime); - clipcopy(NULL); + xclipcopy(); } else { fprintf(stderr, "erresc: invalid base64\n"); } @@ -2134,7 +2095,7 @@ tcontrolcode(uchar ascii) case 0x99: /* TODO: SGCI */ break; case 0x9a: /* DECID -- Identify Terminal */ - ttywrite(vtiden, sizeof(vtiden) - 1); + ttywrite(vtiden, strlen(vtiden)); break; case 0x9b: /* TODO: CSI */ case 0x9c: /* TODO: ST */ @@ -2206,7 +2167,7 @@ eschandle(uchar ascii) } break; case 'Z': /* DECID -- Identify Terminal */ - ttywrite(vtiden, sizeof(vtiden) - 1); + ttywrite(vtiden, strlen(vtiden)); break; case 'c': /* RIS -- Reset to inital state */ treset(); diff --git a/st.h b/st.h index 3d9b6e7..9314607 100644 --- a/st.h +++ b/st.h @@ -190,6 +190,13 @@ typedef struct { void die(const char *, ...); void redraw(void); +void iso14755(const Arg *); +void numlock(const Arg *); +void printscreen(const Arg *); +void printsel(const Arg *); +void sendbreak(const Arg *); +void toggleprinter(const Arg *); + int tattrset(int); void tnew(int, int); void tresize(int, int); @@ -225,42 +232,13 @@ extern pid_t pid; extern int oldbutton; /* config.h globals */ -extern char font[]; -extern int borderpx; -extern float cwscale; -extern float chscale; -extern unsigned int doubleclicktimeout; -extern unsigned int tripleclicktimeout; +extern char *shell; +extern char *utmp; +extern char *stty_args; +extern char *vtiden; +extern char *worddelimiters; extern int allowaltscreen; -extern unsigned int xfps; -extern unsigned int actionfps; -extern unsigned int cursorthickness; -extern int bellvolume; -extern unsigned int blinktimeout; -extern char termname[]; -extern const char *colorname[]; -extern size_t colornamelen; +extern char *termname; +extern unsigned int tabspaces; extern unsigned int defaultfg; extern unsigned int defaultbg; -extern unsigned int defaultcs; -extern unsigned int defaultrcs; -extern unsigned int cursorshape; -extern unsigned int cols; -extern unsigned int rows; -extern unsigned int mouseshape; -extern unsigned int mousefg; -extern unsigned int mousebg; -extern unsigned int defaultattr; -extern MouseShortcut mshortcuts[]; -extern size_t mshortcutslen; -extern Shortcut shortcuts[]; -extern size_t shortcutslen; -extern KeySym mappedkeys[]; -extern size_t mappedkeyslen; -extern uint ignoremod; -extern uint forceselmod; -extern Key key[]; -extern size_t keyslen; -extern uint selmasks[]; -extern size_t selmaskslen; -extern char ascii_printable[]; diff --git a/win.h b/win.h index 00113c5..b7022ec 100644 --- a/win.h +++ b/win.h @@ -18,6 +18,3 @@ void xsettitle(char *); void xsetpointermotion(int); void xselpaste(void); void xsetsel(char *, Time); -void zoom(const Arg *); -void zoomabs(const Arg *); -void zoomreset(const Arg *); diff --git a/x.c b/x.c index e267961..cb8c351 100644 --- a/x.c +++ b/x.c @@ -20,6 +20,25 @@ static char *argv0; #include "st.h" #include "win.h" +/* function definitions used in config.h */ +static void clipcopy(const Arg *); +static void clippaste(const Arg *); +static void selpaste(const Arg *); +static void zoom(const Arg *); +static void zoomabs(const Arg *); +static void zoomreset(const Arg *); + +/* config.h for applying patches and the configuration. */ +#include "config.h" + +/* config.h array lengths */ +size_t colornamelen = LEN(colorname); +size_t mshortcutslen = LEN(mshortcuts); +size_t shortcutslen = LEN(shortcuts); +size_t selmaskslen = LEN(selmasks); +size_t keyslen = LEN(key); +size_t mappedkeyslen = LEN(mappedkeys); + /* XEMBED messages */ #define XEMBED_FOCUS_IN 4 #define XEMBED_FOCUS_OUT 5 @@ -188,6 +207,24 @@ static char *opt_line = NULL; static char *opt_name = NULL; static char *opt_title = NULL; +void +clipcopy(const Arg *dummy) +{ + xclipcopy(); +} + +void +clippaste(const Arg *dummy) +{ + xclippaste(); +} + +void +selpaste(const Arg *dummy) +{ + xselpaste(); +} + void zoom(const Arg *arg) { -- cgit v1.2.3 From 416dd257274fd334be082b1138338adffa3e2d5e Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 17 Oct 2017 16:46:26 -0500 Subject: Move X-related config.h types into x.c No need to expose Shortcut, MouseShortcut, and Key anymore. Signed-off-by: Devin J. Pohly --- st.h | 23 ----------------------- x.c | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 23 deletions(-) (limited to 'st.h') diff --git a/st.h b/st.h index 9314607..71c79f4 100644 --- a/st.h +++ b/st.h @@ -134,12 +134,6 @@ typedef struct { int cursor; /* cursor style */ } TermWindow; -typedef struct { - uint b; - uint mask; - char *s; -} MouseShortcut; - typedef struct { int mode; int type; @@ -170,23 +164,6 @@ typedef union { const void *v; } Arg; -typedef struct { - uint mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Shortcut; - -typedef struct { - KeySym k; - uint mask; - char *s; - /* three valued logic variables: 0 indifferent, 1 on, -1 off */ - signed char appkey; /* application keypad */ - signed char appcursor; /* application cursor */ - signed char crlf; /* crlf mode */ -} Key; - void die(const char *, ...); void redraw(void); diff --git a/x.c b/x.c index 03555d1..24f6991 100644 --- a/x.c +++ b/x.c @@ -20,6 +20,30 @@ static char *argv0; #include "st.h" #include "win.h" +/* types used in config.h */ +typedef struct { + uint mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Shortcut; + +typedef struct { + uint b; + uint mask; + char *s; +} MouseShortcut; + +typedef struct { + KeySym k; + uint mask; + char *s; + /* three valued logic variables: 0 indifferent, 1 on, -1 off */ + signed char appkey; /* application keypad */ + signed char appcursor; /* application cursor */ + signed char crlf; /* crlf mode */ +} Key; + /* function definitions used in config.h */ static void clipcopy(const Arg *); static void clippaste(const Arg *); -- cgit v1.2.3 From 323d38da20c8a1d295ab1dbc0fc7ce947ef824e1 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 6 Nov 2017 17:57:45 -0600 Subject: Make win variable internal to x.c There was only a single reference to the `win` variable in st.c, so exporting that to x.c allows us to rid ourselves of another extern. Signed-off-by: Devin J. Pohly --- st.c | 6 +----- st.h | 1 - win.h | 1 + x.c | 11 +++++++++++ 4 files changed, 13 insertions(+), 6 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index ec747cc..fdf697b 100644 --- a/st.c +++ b/st.c @@ -170,7 +170,6 @@ static char *base64dec(const char *); static ssize_t xwrite(int, const char *, size_t); /* Globals */ -TermWindow win; Term term; Selection sel; int cmdfd; @@ -1683,11 +1682,8 @@ csihandle(void) case ' ': switch (csiescseq.mode[1]) { case 'q': /* DECSCUSR -- Set Cursor Style */ - DEFAULT(csiescseq.arg[0], 1); - if (!BETWEEN(csiescseq.arg[0], 0, 6)) { + if (xsetcursor(csiescseq.arg[0])) goto unknown; - } - win.cursor = csiescseq.arg[0]; break; default: goto unknown; diff --git a/st.h b/st.h index 71c79f4..8637d35 100644 --- a/st.h +++ b/st.h @@ -201,7 +201,6 @@ void *xrealloc(void *, size_t); char *xstrdup(char *); /* Globals */ -extern TermWindow win; extern Term term; extern Selection sel; extern int cmdfd; diff --git a/win.h b/win.h index beb458d..c6a5337 100644 --- a/win.h +++ b/win.h @@ -14,5 +14,6 @@ void xhints(void); void xloadcols(void); int xsetcolorname(int, const char *); void xsettitle(char *); +int xsetcursor(int); void xsetpointermotion(int); void xsetsel(char *, Time); diff --git a/x.c b/x.c index 24f6991..04e2e05 100644 --- a/x.c +++ b/x.c @@ -187,6 +187,7 @@ static void (*handler[LASTEvent])(XEvent *) = { static DC dc; static XWindow xw; static XSelection xsel; +static TermWindow win; enum window_state { WIN_VISIBLE = 1, @@ -1615,6 +1616,16 @@ xsetpointermotion(int set) XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); } +int +xsetcursor(int cursor) +{ + DEFAULT(cursor, 1); + if (!BETWEEN(cursor, 0, 6)) + return 1; + win.cursor = cursor; + return 0; +} + void xseturgency(int add) { -- cgit v1.2.3 From 5683b1f80c5ac274adf98517ce2217b4d4896243 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Wed, 21 Feb 2018 22:56:02 -0600 Subject: Move X-specific selection info into XSelection Data about PRIMARY/CLIPBOARD and clicks are part of the front-end, not the terminal. Signed-off-by: Devin J. Pohly --- st.c | 4 ---- st.h | 5 ----- x.c | 31 +++++++++++++++++++------------ 3 files changed, 19 insertions(+), 21 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index d4dfe6e..ea0726c 100644 --- a/st.c +++ b/st.c @@ -365,13 +365,9 @@ base64dec(const char *src) void selinit(void) { - clock_gettime(CLOCK_MONOTONIC, &sel.tclick1); - clock_gettime(CLOCK_MONOTONIC, &sel.tclick2); sel.mode = SEL_IDLE; sel.snap = 0; sel.ob.x = -1; - sel.primary = NULL; - sel.clipboard = NULL; } int diff --git a/st.h b/st.h index 8637d35..79dd47e 100644 --- a/st.h +++ b/st.h @@ -149,12 +149,7 @@ typedef struct { int x, y; } nb, ne, ob, oe; - char *primary, *clipboard; int alt; - struct timespec tclick1; - struct timespec tclick2; - - //Atom xtarget; } Selection; typedef union { diff --git a/x.c b/x.c index e3e5451..9f506b1 100644 --- a/x.c +++ b/x.c @@ -94,6 +94,9 @@ typedef struct { typedef struct { Atom xtarget; + char *primary, *clipboard; + struct timespec tclick1; + struct timespec tclick2; } XSelection; /* Font structure */ @@ -234,11 +237,11 @@ clipcopy(const Arg *dummy) { Atom clipboard; - if (sel.clipboard != NULL) - free(sel.clipboard); + if (xsel.clipboard != NULL) + free(xsel.clipboard); - if (sel.primary != NULL) { - sel.clipboard = xstrdup(sel.primary); + if (xsel.primary != NULL) { + xsel.clipboard = xstrdup(xsel.primary); clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); } @@ -427,9 +430,9 @@ bpress(XEvent *e) * If the user clicks below predefined timeouts specific * snapping behaviour is exposed. */ - if (TIMEDIFF(now, sel.tclick2) <= tripleclicktimeout) { + if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { sel.snap = SNAP_LINE; - } else if (TIMEDIFF(now, sel.tclick1) <= doubleclicktimeout) { + } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { sel.snap = SNAP_WORD; } else { sel.snap = 0; @@ -439,8 +442,8 @@ bpress(XEvent *e) if (sel.snap != 0) sel.mode = SEL_READY; tsetdirt(sel.nb.y, sel.ne.y); - sel.tclick2 = sel.tclick1; - sel.tclick1 = now; + xsel.tclick2 = xsel.tclick1; + xsel.tclick1 = now; } } @@ -594,9 +597,9 @@ selrequest(XEvent *e) */ clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); if (xsre->selection == XA_PRIMARY) { - seltext = sel.primary; + seltext = xsel.primary; } else if (xsre->selection == clipboard) { - seltext = sel.clipboard; + seltext = xsel.clipboard; } else { fprintf(stderr, "Unhandled clipboard selection 0x%lx\n", @@ -620,8 +623,8 @@ selrequest(XEvent *e) void setsel(char *str, Time t) { - free(sel.primary); - sel.primary = str; + free(xsel.primary); + xsel.primary = str; XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) @@ -1127,6 +1130,10 @@ xinit(void) xhints(); XSync(xw.dpy, False); + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); + clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); + xsel.primary = NULL; + xsel.clipboard = NULL; xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); if (xsel.xtarget == None) xsel.xtarget = XA_STRING; -- cgit v1.2.3 From bcb5d3adbe57ead05a829e5144c2ba1dc465865f Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Wed, 21 Feb 2018 23:29:41 -0600 Subject: Move terminal-related selection logic into st.c The front-end determines information about mouse clicks and motion, and the terminal handles the actual selection start/extend/dirty logic by row and column. While we're in the neighborhood, we'll also rename getbuttoninfo() to mousesel() which is, at least, less wrong. Signed-off-by: Devin J. Pohly --- st.c | 37 +++++++++++++++++++++++++++++++++++++ st.h | 3 ++- x.c | 55 +++++++++++++++---------------------------------------- 3 files changed, 54 insertions(+), 41 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index ea0726c..21cba9e 100644 --- a/st.c +++ b/st.c @@ -140,6 +140,7 @@ static void tscrollup(int, int); static void tscrolldown(int, int); static void tsetattr(int *, int); static void tsetchar(Rune, Glyph *, int, int); +static void tsetdirt(int, int); static void tsetscroll(int, int); static void tswapscreen(void); static void tsetmode(int, int, int *, int); @@ -384,6 +385,42 @@ tlinelen(int y) return i; } +void +selstart(int col, int row, int snap) +{ + selclear(); + sel.mode = SEL_EMPTY; + sel.type = SEL_REGULAR; + sel.snap = snap; + sel.oe.x = sel.ob.x = col; + sel.oe.y = sel.ob.y = row; + selnormalize(); + + if (sel.snap != 0) + sel.mode = SEL_READY; + tsetdirt(sel.nb.y, sel.ne.y); +} + +void +selextend(int col, int row, int type) +{ + int oldey, oldex, oldsby, oldsey, oldtype; + oldey = sel.oe.y; + oldex = sel.oe.x; + oldsby = sel.nb.y; + oldsey = sel.ne.y; + oldtype = sel.type; + + sel.alt = IS_SET(MODE_ALTSCREEN); + sel.oe.x = col; + sel.oe.y = row; + selnormalize(); + sel.type = type; + + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type) + tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); +} + void selnormalize(void) { diff --git a/st.h b/st.h index 79dd47e..c5ff5cf 100644 --- a/st.h +++ b/st.h @@ -172,7 +172,6 @@ void toggleprinter(const Arg *); int tattrset(int); void tnew(int, int); void tresize(int, int); -void tsetdirt(int, int); void tsetdirtattr(int); void ttynew(char *, char *, char **); size_t ttyread(void); @@ -184,6 +183,8 @@ void resettitle(void); void selclear(void); void selinit(void); +void selstart(int, int, int); +void selextend(int, int, int); void selnormalize(void); int selected(int, int); char *getsel(void); diff --git a/x.c b/x.c index 9f506b1..ddae6b6 100644 --- a/x.c +++ b/x.c @@ -157,7 +157,7 @@ static void selnotify(XEvent *); static void selclear_(XEvent *); static void selrequest(XEvent *); static void setsel(char *, Time); -static void getbuttoninfo(XEvent *); +static void mousesel(XEvent *); static void mousereport(XEvent *); static char *kmap(KeySym, uint); static int match(uint, uint); @@ -313,24 +313,19 @@ y2row(int y) } void -getbuttoninfo(XEvent *e) +mousesel(XEvent *e) { - int type; + int type, seltype = SEL_REGULAR; uint state = e->xbutton.state & ~(Button1Mask | forceselmod); - sel.alt = IS_SET(MODE_ALTSCREEN); - - sel.oe.x = x2col(e->xbutton.x); - sel.oe.y = y2row(e->xbutton.y); - selnormalize(); - - sel.type = SEL_REGULAR; for (type = 1; type < LEN(selmasks); ++type) { if (match(selmasks[type], state)) { - sel.type = type; + seltype = type; break; } } + + selextend(x2col(e->xbutton.x), y2row(e->xbutton.y), seltype); } void @@ -402,6 +397,7 @@ bpress(XEvent *e) { struct timespec now; MouseShortcut *ms; + int snap; if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { mousereport(e); @@ -417,33 +413,22 @@ bpress(XEvent *e) } if (e->xbutton.button == Button1) { - clock_gettime(CLOCK_MONOTONIC, &now); - - /* Clear previous selection, logically and visually. */ - selclear_(NULL); - sel.mode = SEL_EMPTY; - sel.type = SEL_REGULAR; - sel.oe.x = sel.ob.x = x2col(e->xbutton.x); - sel.oe.y = sel.ob.y = y2row(e->xbutton.y); - /* * If the user clicks below predefined timeouts specific * snapping behaviour is exposed. */ + clock_gettime(CLOCK_MONOTONIC, &now); if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { - sel.snap = SNAP_LINE; + snap = SNAP_LINE; } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { - sel.snap = SNAP_WORD; + snap = SNAP_WORD; } else { - sel.snap = 0; + snap = 0; } - selnormalize(); - - if (sel.snap != 0) - sel.mode = SEL_READY; - tsetdirt(sel.nb.y, sel.ne.y); xsel.tclick2 = xsel.tclick1; xsel.tclick1 = now; + + selstart(x2col(e->xbutton.x), y2row(e->xbutton.y), snap); } } @@ -649,20 +634,17 @@ brelease(XEvent *e) selpaste(NULL); } else if (e->xbutton.button == Button1) { if (sel.mode == SEL_READY) { - getbuttoninfo(e); + mousesel(e); setsel(getsel(), e->xbutton.time); } else selclear_(NULL); sel.mode = SEL_IDLE; - tsetdirt(sel.nb.y, sel.ne.y); } } void bmotion(XEvent *e) { - int oldey, oldex, oldsby, oldsey; - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { mousereport(e); return; @@ -672,14 +654,7 @@ bmotion(XEvent *e) return; sel.mode = SEL_READY; - oldey = sel.oe.y; - oldex = sel.oe.x; - oldsby = sel.nb.y; - oldsey = sel.ne.y; - getbuttoninfo(e); - - if (oldey != sel.oe.y || oldex != sel.oe.x) - tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); + mousesel(e); } void -- cgit v1.2.3 From cfc7acdfd923924ae150a32061fb95987697b159 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Wed, 21 Feb 2018 23:54:29 -0600 Subject: Move remaining selection mode logic into selextend The "done" parameter indicates a change which finalizes the selection (e.g. a mouse button release as opposed to motion). Signed-off-by: Devin J. Pohly --- st.c | 14 ++++++++++++-- st.h | 3 +-- x.c | 27 +++++++++------------------ 3 files changed, 22 insertions(+), 22 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index 21cba9e..b7e215e 100644 --- a/st.c +++ b/st.c @@ -167,11 +167,11 @@ static ssize_t xwrite(int, const char *, size_t); /* Globals */ Term term; -Selection sel; int cmdfd; pid_t pid; int oldbutton = 3; /* button event on startup: 3 = release */ +static Selection sel; static CSIEscape csiescseq; static STREscape strescseq; static int iofd = 1; @@ -402,9 +402,17 @@ selstart(int col, int row, int snap) } void -selextend(int col, int row, int type) +selextend(int col, int row, int type, int done) { int oldey, oldex, oldsby, oldsey, oldtype; + + if (!sel.mode) + return; + if (done && sel.mode == SEL_EMPTY) { + selclear(); + return; + } + oldey = sel.oe.y; oldex = sel.oe.x; oldsby = sel.nb.y; @@ -419,6 +427,8 @@ selextend(int col, int row, int type) if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type) tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); + + sel.mode = done ? SEL_IDLE : SEL_READY; } void diff --git a/st.h b/st.h index c5ff5cf..a34e31c 100644 --- a/st.h +++ b/st.h @@ -184,7 +184,7 @@ void resettitle(void); void selclear(void); void selinit(void); void selstart(int, int, int); -void selextend(int, int, int); +void selextend(int, int, int, int); void selnormalize(void); int selected(int, int); char *getsel(void); @@ -198,7 +198,6 @@ char *xstrdup(char *); /* Globals */ extern Term term; -extern Selection sel; extern int cmdfd; extern pid_t pid; extern int oldbutton; diff --git a/x.c b/x.c index ddae6b6..a7f619e 100644 --- a/x.c +++ b/x.c @@ -157,7 +157,7 @@ static void selnotify(XEvent *); static void selclear_(XEvent *); static void selrequest(XEvent *); static void setsel(char *, Time); -static void mousesel(XEvent *); +static void mousesel(XEvent *, int); static void mousereport(XEvent *); static char *kmap(KeySym, uint); static int match(uint, uint); @@ -313,7 +313,7 @@ y2row(int y) } void -mousesel(XEvent *e) +mousesel(XEvent *e, int done) { int type, seltype = SEL_REGULAR; uint state = e->xbutton.state & ~(Button1Mask | forceselmod); @@ -324,8 +324,9 @@ mousesel(XEvent *e) break; } } - - selextend(x2col(e->xbutton.x), y2row(e->xbutton.y), seltype); + selextend(x2col(e->xbutton.x), y2row(e->xbutton.y), seltype, done); + if (done) + setsel(getsel(), e->xbutton.time); } void @@ -630,16 +631,10 @@ brelease(XEvent *e) return; } - if (e->xbutton.button == Button2) { + if (e->xbutton.button == Button2) selpaste(NULL); - } else if (e->xbutton.button == Button1) { - if (sel.mode == SEL_READY) { - mousesel(e); - setsel(getsel(), e->xbutton.time); - } else - selclear_(NULL); - sel.mode = SEL_IDLE; - } + else if (e->xbutton.button == Button1) + mousesel(e, 1); } void @@ -650,11 +645,7 @@ bmotion(XEvent *e) return; } - if (!sel.mode) - return; - - sel.mode = SEL_READY; - mousesel(e); + mousesel(e, 0); } void -- cgit v1.2.3 From 52d6fb1ab1f7d41839edebb63c3408578cd44e3c Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Thu, 22 Feb 2018 00:42:23 -0600 Subject: Move terminal echo logic into st.c The only thing differentiating ttywrite and ttysend was the potential for echo; make this a parameter and remove ttysend. Signed-off-by: Devin J. Pohly --- st.c | 23 +++++++++-------------- st.h | 3 +-- x.c | 18 +++++++++--------- 3 files changed, 19 insertions(+), 25 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index b7e215e..7d546da 100644 --- a/st.c +++ b/st.c @@ -784,12 +784,15 @@ ttyread(void) } void -ttywrite(const char *s, size_t n) +ttywrite(const char *s, size_t n, int may_echo) { fd_set wfd, rfd; ssize_t r; size_t lim = 256; + if (may_echo && IS_SET(MODE_ECHO)) + twrite(s, n, 1); + /* * Remember that we are using a pty, which might be a modem line. * Writing too much will clog the line. That's why we are doing this @@ -840,14 +843,6 @@ write_error: die("write error on tty: %s\n", strerror(errno)); } -void -ttysend(char *s, size_t n) -{ - ttywrite(s, n); - if (IS_SET(MODE_ECHO)) - twrite(s, n, 1); -} - void ttyresize(int tw, int th) { @@ -1570,7 +1565,7 @@ csihandle(void) break; case 'c': /* DA -- Device Attributes */ if (csiescseq.arg[0] == 0) - ttywrite(vtiden, strlen(vtiden)); + ttywrite(vtiden, strlen(vtiden), 0); break; case 'C': /* CUF -- Cursor Forward */ case 'a': /* HPR -- Cursor Forward */ @@ -1698,7 +1693,7 @@ csihandle(void) if (csiescseq.arg[0] == 6) { len = snprintf(buf, sizeof(buf),"\033[%i;%iR", term.c.y+1, term.c.x+1); - ttywrite(buf, len); + ttywrite(buf, len, 0); } break; case 'r': /* DECSTBM -- Set Scrolling Region */ @@ -1916,7 +1911,7 @@ iso14755(const Arg *arg) (*e != '\n' && *e != '\0')) return; - ttysend(uc, utf8encode(utf32, uc)); + ttywrite(uc, utf8encode(utf32, uc), 1); } void @@ -2129,7 +2124,7 @@ tcontrolcode(uchar ascii) case 0x99: /* TODO: SGCI */ break; case 0x9a: /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden)); + ttywrite(vtiden, strlen(vtiden), 0); break; case 0x9b: /* TODO: CSI */ case 0x9c: /* TODO: ST */ @@ -2201,7 +2196,7 @@ eschandle(uchar ascii) } break; case 'Z': /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden)); + ttywrite(vtiden, strlen(vtiden), 0); break; case 'c': /* RIS -- Reset to inital state */ treset(); diff --git a/st.h b/st.h index a34e31c..d7738a0 100644 --- a/st.h +++ b/st.h @@ -176,8 +176,7 @@ void tsetdirtattr(int); void ttynew(char *, char *, char **); size_t ttyread(void); void ttyresize(int, int); -void ttysend(char *, size_t); -void ttywrite(const char *, size_t); +void ttywrite(const char *, size_t, int); void resettitle(void); diff --git a/x.c b/x.c index a7f619e..49a22e4 100644 --- a/x.c +++ b/x.c @@ -390,7 +390,7 @@ mousereport(XEvent *e) return; } - ttywrite(buf, len); + ttywrite(buf, len, 0); } void @@ -408,7 +408,7 @@ bpress(XEvent *e) for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { if (e->xbutton.button == ms->b && match(ms->mask, e->xbutton.state)) { - ttysend(ms->s, strlen(ms->s)); + ttywrite(ms->s, strlen(ms->s), 1); return; } } @@ -520,10 +520,10 @@ selnotify(XEvent *e) } if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) - ttywrite("\033[200~", 6); - ttysend((char *)data, nitems * format / 8); + ttywrite("\033[200~", 6, 0); + ttywrite((char *)data, nitems * format / 8, 1); if (IS_SET(MODE_BRCKTPASTE) && rem == 0) - ttywrite("\033[201~", 6); + ttywrite("\033[201~", 6, 0); XFree(data); /* number of 32-bit chunks returned */ ofs += nitems * format / 32; @@ -1634,12 +1634,12 @@ focus(XEvent *ev) win.state |= WIN_FOCUSED; xseturgency(0); if (IS_SET(MODE_FOCUS)) - ttywrite("\033[I", 3); + ttywrite("\033[I", 3, 0); } else { XUnsetICFocus(xw.xic); win.state &= ~WIN_FOCUSED; if (IS_SET(MODE_FOCUS)) - ttywrite("\033[O", 3); + ttywrite("\033[O", 3, 0); } } @@ -1714,7 +1714,7 @@ kpress(XEvent *ev) /* 2. custom keys from config.h */ if ((customkey = kmap(ksym, e->state))) { - ttysend(customkey, strlen(customkey)); + ttywrite(customkey, strlen(customkey), 1); return; } @@ -1733,7 +1733,7 @@ kpress(XEvent *ev) len = 2; } } - ttysend(buf, len); + ttywrite(buf, len, 1); } -- cgit v1.2.3 From 05c66cb37d9ff278a3e0c45682c4b5e7945deb42 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Fri, 23 Feb 2018 14:16:52 -0600 Subject: Split mode bits between Term and TermWindow Moves the mode bits used by x.c from Term to TermWindow, absorbing UI/input-related mode bits (visible/focused/numlock) along the way. This is gradually reducing external references to Term. Since TermWindow is already internal to x.c, we add xsetmode() to allow st to modify window bits in accordance with escape sequences. IS_SET() is redefined accordingly (term.mode in st.c, win.mode in x.c). Signed-off-by: Devin J. Pohly --- st.c | 64 ++++++++++++++++++++++++++++++++-------------------------------- st.h | 33 +-------------------------------- win.h | 24 ++++++++++++++++++++++++ x.c | 50 +++++++++++++++++++++++++++++++------------------- 4 files changed, 88 insertions(+), 83 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index 3ebf8c6..01791a5 100644 --- a/st.c +++ b/st.c @@ -42,6 +42,7 @@ #define STR_ARG_SIZ ESC_ARG_SIZ /* macros */ +#define IS_SET(flag) ((term.mode & (flag)) != 0) #define NUMMAXLEN(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) @@ -51,6 +52,17 @@ /* constants */ #define ISO14755CMD "dmenu -w \"$WINDOWID\" -p codepoint: ': /* DECPNM -- Normal keypad */ - term.mode &= ~MODE_APPKEYPAD; + xsetmode(0, MODE_APPKEYPAD); break; case '7': /* DECSC -- Save Cursor */ tcursor(CURSOR_SAVE); @@ -2526,9 +2532,3 @@ redraw(void) tfulldirt(); draw(); } - -void -numlock(const Arg *dummy) -{ - term.numlock ^= 1; -} diff --git a/st.h b/st.h index d7738a0..3382d61 100644 --- a/st.h +++ b/st.h @@ -13,7 +13,6 @@ #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 || \ (a).bg != (b).bg) -#define IS_SET(flag) ((term.mode & (flag)) != 0) #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ (t1.tv_nsec-t2.tv_nsec)/1E6) #define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) @@ -37,34 +36,6 @@ enum glyph_attribute { ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, }; -enum term_mode { - MODE_WRAP = 1 << 0, - MODE_INSERT = 1 << 1, - MODE_APPKEYPAD = 1 << 2, - MODE_ALTSCREEN = 1 << 3, - MODE_CRLF = 1 << 4, - MODE_MOUSEBTN = 1 << 5, - MODE_MOUSEMOTION = 1 << 6, - MODE_REVERSE = 1 << 7, - MODE_KBDLOCK = 1 << 8, - MODE_HIDE = 1 << 9, - MODE_ECHO = 1 << 10, - MODE_APPCURSOR = 1 << 11, - MODE_MOUSESGR = 1 << 12, - MODE_8BIT = 1 << 13, - MODE_BLINK = 1 << 14, - MODE_FBLINK = 1 << 15, - MODE_FOCUS = 1 << 16, - MODE_MOUSEX10 = 1 << 17, - MODE_MOUSEMANY = 1 << 18, - MODE_BRCKTPASTE = 1 << 19, - MODE_PRINT = 1 << 20, - MODE_UTF8 = 1 << 21, - MODE_SIXEL = 1 << 22, - MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ - |MODE_MOUSEMANY, -}; - enum selection_mode { SEL_IDLE = 0, SEL_EMPTY = 1, @@ -120,7 +91,6 @@ typedef struct { char trantbl[4]; /* charset table translation */ int charset; /* current charset */ int icharset; /* selected charset for sequence */ - int numlock; /* lock numbers in keyboard */ int *tabs; } Term; @@ -130,7 +100,7 @@ typedef struct { int w, h; /* window width and height */ int ch; /* char height */ int cw; /* char width */ - char state; /* focus, redraw, visible */ + int mode; /* window state/mode flags */ int cursor; /* cursor style */ } TermWindow; @@ -163,7 +133,6 @@ void die(const char *, ...); void redraw(void); void iso14755(const Arg *); -void numlock(const Arg *); void printscreen(const Arg *); void printsel(const Arg *); void sendbreak(const Arg *); diff --git a/win.h b/win.h index 123662e..1e08b16 100644 --- a/win.h +++ b/win.h @@ -1,5 +1,28 @@ /* See LICENSE for license details. */ +enum win_mode { + MODE_VISIBLE = 1 << 0, + MODE_FOCUSED = 1 << 1, + MODE_APPKEYPAD = 1 << 2, + MODE_MOUSEBTN = 1 << 3, + MODE_MOUSEMOTION = 1 << 4, + MODE_REVERSE = 1 << 5, + MODE_KBDLOCK = 1 << 6, + MODE_HIDE = 1 << 7, + MODE_APPCURSOR = 1 << 8, + MODE_MOUSESGR = 1 << 9, + MODE_8BIT = 1 << 10, + MODE_BLINK = 1 << 11, + MODE_FBLINK = 1 << 12, + MODE_FOCUS = 1 << 13, + MODE_MOUSEX10 = 1 << 14, + MODE_MOUSEMANY = 1 << 15, + MODE_BRCKTPASTE = 1 << 16, + MODE_NUMLOCK = 1 << 17, + MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ + |MODE_MOUSEMANY, +}; + void draw(void); void drawregion(int, int, int, int); @@ -10,5 +33,6 @@ void xloadcols(void); int xsetcolorname(int, const char *); void xsettitle(char *); int xsetcursor(int); +void xsetmode(int, unsigned int); void xsetpointermotion(int); void xsetsel(char *); diff --git a/x.c b/x.c index 76fb910..c5826cf 100644 --- a/x.c +++ b/x.c @@ -51,6 +51,7 @@ typedef struct { /* function definitions used in config.h */ static void clipcopy(const Arg *); static void clippaste(const Arg *); +static void numlock(const Arg *); static void selpaste(const Arg *); static void zoom(const Arg *); static void zoomabs(const Arg *); @@ -64,6 +65,7 @@ static void zoomreset(const Arg *); #define XEMBED_FOCUS_OUT 5 /* macros */ +#define IS_SET(flag) ((win.mode & (flag)) != 0) #define TRUERED(x) (((x) & 0xff0000) >> 8) #define TRUEGREEN(x) (((x) & 0xff00)) #define TRUEBLUE(x) (((x) & 0xff) << 8) @@ -196,11 +198,6 @@ static XWindow xw; static XSelection xsel; static TermWindow win; -enum window_state { - WIN_VISIBLE = 1, - WIN_FOCUSED = 2 -}; - /* Font Ring Cache */ enum { FRC_NORMAL, @@ -263,6 +260,12 @@ selpaste(const Arg *dummy) xw.win, CurrentTime); } +void +numlock(const Arg *dummy) +{ + win.mode ^= MODE_NUMLOCK; +} + void zoom(const Arg *arg) { @@ -1090,6 +1093,7 @@ xinit(void) XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, PropModeReplace, (uchar *)&thispid, 1); + win.mode = MODE_NUMLOCK; resettitle(); XMapWindow(xw.dpy, xw.win); xhints(); @@ -1319,14 +1323,13 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i fg = &revfg; } - if (base.mode & ATTR_REVERSE) { temp = fg; fg = bg; bg = temp; } - if (base.mode & ATTR_BLINK && term.mode & MODE_BLINK) + if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) fg = bg; if (base.mode & ATTR_INVISIBLE) @@ -1440,7 +1443,7 @@ xdrawcursor(void) return; /* draw the new one */ - if (win.state & WIN_FOCUSED) { + if (IS_SET(MODE_FOCUSED)) { switch (win.cursor) { case 7: /* st extension: snowman */ utf8decode("☃", &g.u, UTF_SIZ); @@ -1527,7 +1530,7 @@ drawregion(int x1, int y1, int x2, int y2) Glyph base, new; XftGlyphFontSpec *specs; - if (!(win.state & WIN_VISIBLE)) + if (!(IS_SET(MODE_VISIBLE))) return; for (y = y1; y < y2; y++) { @@ -1575,13 +1578,13 @@ visibility(XEvent *ev) { XVisibilityEvent *e = &ev->xvisibility; - MODBIT(win.state, e->state != VisibilityFullyObscured, WIN_VISIBLE); + MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); } void unmap(XEvent *ev) { - win.state &= ~WIN_VISIBLE; + win.mode &= ~MODE_VISIBLE; } void @@ -1591,6 +1594,15 @@ xsetpointermotion(int set) XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); } +void +xsetmode(int set, unsigned int flags) +{ + int mode = win.mode; + MODBIT(win.mode, set, flags); + if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) + redraw(); +} + int xsetcursor(int cursor) { @@ -1614,7 +1626,7 @@ xseturgency(int add) void xbell(void) { - if (!(win.state & WIN_FOCUSED)) + if (!(IS_SET(MODE_FOCUSED))) xseturgency(1); if (bellvolume) XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); @@ -1630,13 +1642,13 @@ focus(XEvent *ev) if (ev->type == FocusIn) { XSetICFocus(xw.xic); - win.state |= WIN_FOCUSED; + win.mode |= MODE_FOCUSED; xseturgency(0); if (IS_SET(MODE_FOCUS)) ttywrite("\033[I", 3, 0); } else { XUnsetICFocus(xw.xic); - win.state &= ~WIN_FOCUSED; + win.mode &= ~MODE_FOCUSED; if (IS_SET(MODE_FOCUS)) ttywrite("\033[O", 3, 0); } @@ -1673,7 +1685,7 @@ kmap(KeySym k, uint state) if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) continue; - if (term.numlock && kp->appkey == 2) + if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) continue; if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) @@ -1742,10 +1754,10 @@ cmessage(XEvent *e) */ if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { - win.state |= WIN_FOCUSED; + win.mode |= MODE_FOCUSED; xseturgency(0); } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { - win.state &= ~WIN_FOCUSED; + win.mode &= ~MODE_FOCUSED; } } else if (e->xclient.data.l[0] == xw.wmdeletewin) { /* Send SIGHUP to shell */ @@ -1810,7 +1822,7 @@ run(void) if (blinktimeout) { blinkset = tattrset(ATTR_BLINK); if (!blinkset) - MODBIT(term.mode, 0, MODE_BLINK); + MODBIT(win.mode, 0, MODE_BLINK); } } @@ -1825,7 +1837,7 @@ run(void) dodraw = 0; if (blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) { tsetdirtattr(ATTR_BLINK); - term.mode ^= MODE_BLINK; + win.mode ^= MODE_BLINK; lastblink = now; dodraw = 1; } -- cgit v1.2.3 From 88d8293fb4ba150a5f19d58d133b5db93d9dcfa5 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sat, 24 Feb 2018 14:53:23 -0600 Subject: Move win-agnostic parts of draw/drawregion to st.c Introduces three functions to encapsulate X-specific behavior: * xdrawline: draws a portion of a single line (used by drawregion) * xbegindraw: called to prepare for drawing (will be useful for e.g. Wayland) and returns true if drawing should happen * xfinishdraw: called to finish drawing (used by draw) Signed-off-by: Devin J. Pohly --- st.c | 25 +++++++++++++++++++++ st.h | 1 + win.h | 7 +++--- x.c | 79 ++++++++++++++++++++++++++++++------------------------------------- 4 files changed, 65 insertions(+), 47 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index 01791a5..504239e 100644 --- a/st.c +++ b/st.c @@ -166,6 +166,8 @@ static int32_t tdefcolor(int *, int *, int); static void tdeftran(char); static void tstrsequence(uchar); +static void drawregion(int, int, int, int); + static void selscroll(int, int); static void selsnap(int *, int *, int); @@ -2526,6 +2528,29 @@ resettitle(void) xsettitle(NULL); } +void +drawregion(int x1, int y1, int x2, int y2) +{ + int y; + for (y = y1; y < y2; y++) { + if (!term.dirty[y]) + continue; + + term.dirty[y] = 0; + xdrawline(term.line[y], x1, y, x2); + } +} + +void +draw(void) +{ + if (!xstartdraw()) + return; + drawregion(0, 0, term.col, term.row); + xdrawcursor(); + xfinishdraw(); +} + void redraw(void) { diff --git a/st.h b/st.h index 3382d61..7026de8 100644 --- a/st.h +++ b/st.h @@ -131,6 +131,7 @@ typedef union { void die(const char *, ...); void redraw(void); +void draw(void); void iso14755(const Arg *); void printscreen(const Arg *); diff --git a/win.h b/win.h index 1e08b16..6e662af 100644 --- a/win.h +++ b/win.h @@ -23,12 +23,12 @@ enum win_mode { |MODE_MOUSEMANY, }; -void draw(void); -void drawregion(int, int, int, int); - void xbell(void); void xclipcopy(void); +void xdrawcursor(void); +void xdrawline(Line, int, int, int); void xhints(void); +void xfinishdraw(void); void xloadcols(void); int xsetcolorname(int, const char *); void xsettitle(char *); @@ -36,3 +36,4 @@ int xsetcursor(int); void xsetmode(int, unsigned int); void xsetpointermotion(int); void xsetsel(char *); +int xstartdraw(void); diff --git a/x.c b/x.c index c5826cf..96944ee 100644 --- a/x.c +++ b/x.c @@ -129,7 +129,6 @@ static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int) static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); static void xdrawglyph(Glyph, int, int); static void xclear(int, int, int, int); -static void xdrawcursor(void); static int xgeommasktogravity(int); static void xinit(void); static void cresize(int, int); @@ -1512,59 +1511,51 @@ xsettitle(char *p) XFree(prop.value); } -void -draw(void) +int +xstartdraw(void) { - drawregion(0, 0, term.col, term.row); - XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, - win.h, 0, 0); - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE)? - defaultfg : defaultbg].pixel); + return IS_SET(MODE_VISIBLE); } void -drawregion(int x1, int y1, int x2, int y2) +xdrawline(Line line, int x1, int y1, int x2) { - int i, x, y, ox, numspecs; + int i, x, ox, numspecs; Glyph base, new; - XftGlyphFontSpec *specs; + XftGlyphFontSpec *specs = xw.specbuf; - if (!(IS_SET(MODE_VISIBLE))) - return; - - for (y = y1; y < y2; y++) { - if (!term.dirty[y]) + numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); + i = ox = 0; + for (x = x1; x < x2 && i < numspecs; x++) { + new = line[x]; + if (new.mode == ATTR_WDUMMY) continue; - - term.dirty[y] = 0; - - specs = xw.specbuf; - numspecs = xmakeglyphfontspecs(specs, &term.line[y][x1], x2 - x1, x1, y); - - i = ox = 0; - for (x = x1; x < x2 && i < numspecs; x++) { - new = term.line[y][x]; - if (new.mode == ATTR_WDUMMY) - continue; - if (selected(x, y)) - new.mode ^= ATTR_REVERSE; - if (i > 0 && ATTRCMP(base, new)) { - xdrawglyphfontspecs(specs, base, i, ox, y); - specs += i; - numspecs -= i; - i = 0; - } - if (i == 0) { - ox = x; - base = new; - } - i++; + if (selected(x, y1)) + new.mode ^= ATTR_REVERSE; + if (i > 0 && ATTRCMP(base, new)) { + xdrawglyphfontspecs(specs, base, i, ox, y1); + specs += i; + numspecs -= i; + i = 0; + } + if (i == 0) { + ox = x; + base = new; } - if (i > 0) - xdrawglyphfontspecs(specs, base, i, ox, y); + i++; } - xdrawcursor(); + if (i > 0) + xdrawglyphfontspecs(specs, base, i, ox, y1); +} + +void +xfinishdraw(void) +{ + XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, + win.h, 0, 0); + XSetForeground(xw.dpy, dc.gc, + dc.col[IS_SET(MODE_REVERSE)? + defaultfg : defaultbg].pixel); } void -- cgit v1.2.3 From a5dc1b46976b2252f9d7bb68f126c4b0f351dd1a Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sat, 24 Feb 2018 14:58:54 -0600 Subject: Pull term references out of xdrawcursor Gradually reducing x.c dependency on Term object. Old and new cursor glyph/position are passed to xdrawcursor. (There may be an opportunity to refactor further if we can unify "clear old cursor" and "draw new cursor" functionality.) Signed-off-by: Devin J. Pohly --- st.c | 15 ++++++++++++++- st.h | 4 +++- win.h | 2 +- x.c | 61 ++++++++++++++++++++++--------------------------------------- 4 files changed, 40 insertions(+), 42 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index 504239e..4bf6378 100644 --- a/st.c +++ b/st.c @@ -2544,10 +2544,23 @@ drawregion(int x1, int y1, int x2, int y2) void draw(void) { + int cx = term.c.x; + if (!xstartdraw()) return; + + /* adjust cursor position */ + LIMIT(term.ocx, 0, term.col-1); + LIMIT(term.ocy, 0, term.row-1); + if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) + term.ocx--; + if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) + cx--; + drawregion(0, 0, term.col, term.row); - xdrawcursor(); + 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 7026de8..27c48cf 100644 --- a/st.h +++ b/st.h @@ -82,8 +82,10 @@ typedef struct { int col; /* nb col */ Line *line; /* screen */ Line *alt; /* alternate screen */ - int *dirty; /* dirtyness of lines */ + int *dirty; /* dirtyness of lines */ TCursor c; /* cursor */ + int ocx; /* old cursor col */ + int ocy; /* old cursor row */ int top; /* top scroll limit */ int bot; /* bottom scroll limit */ int mode; /* terminal mode flags */ diff --git a/win.h b/win.h index 6e662af..7a866fd 100644 --- a/win.h +++ b/win.h @@ -25,7 +25,7 @@ enum win_mode { void xbell(void); void xclipcopy(void); -void xdrawcursor(void); +void xdrawcursor(int, int, Glyph, int, int, Glyph); void xdrawline(Line, int, int, int); void xhints(void); void xfinishdraw(void); diff --git a/x.c b/x.c index 96944ee..d205ca7 100644 --- a/x.c +++ b/x.c @@ -1387,41 +1387,26 @@ xdrawglyph(Glyph g, int x, int y) } void -xdrawcursor(void) +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) { - static int oldx = 0, oldy = 0; - int curx; - Glyph g = {' ', ATTR_NULL, defaultbg, defaultcs}, og; Color drawcol; - LIMIT(oldx, 0, term.col-1); - LIMIT(oldy, 0, term.row-1); - - curx = term.c.x; - - /* adjust position if in dummy */ - if (term.line[oldy][oldx].mode & ATTR_WDUMMY) - oldx--; - if (term.line[term.c.y][curx].mode & ATTR_WDUMMY) - curx--; - /* remove the old cursor */ - og = term.line[oldy][oldx]; - if (selected(oldx, oldy)) + if (selected(ox, oy)) og.mode ^= ATTR_REVERSE; - xdrawglyph(og, oldx, oldy); - - g.u = term.line[term.c.y][term.c.x].u; - g.mode |= term.line[term.c.y][term.c.x].mode & - (ATTR_BOLD | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_STRUCK); + xdrawglyph(og, ox, oy); /* * Select the right color for the right mode. */ + g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; + g.fg = defaultbg; + g.bg = defaultcs; + if (IS_SET(MODE_REVERSE)) { g.mode |= ATTR_REVERSE; g.bg = defaultfg; - if (selected(term.c.x, term.c.y)) { + if (selected(cx, cy)) { drawcol = dc.col[defaultcs]; g.fg = defaultrcs; } else { @@ -1429,7 +1414,7 @@ xdrawcursor(void) g.fg = defaultcs; } } else { - if (selected(term.c.x, term.c.y)) { + if (selected(cx, cy)) { drawcol = dc.col[defaultrcs]; g.fg = defaultfg; g.bg = defaultrcs; @@ -1449,44 +1434,42 @@ xdrawcursor(void) case 0: /* Blinking Block */ case 1: /* Blinking Block (Default) */ case 2: /* Steady Block */ - g.mode |= term.line[term.c.y][curx].mode & ATTR_WIDE; - xdrawglyph(g, term.c.x, term.c.y); + xdrawglyph(g, cx, cy); break; case 3: /* Blinking Underline */ case 4: /* Steady Underline */ XftDrawRect(xw.draw, &drawcol, - borderpx + curx * win.cw, - borderpx + (term.c.y + 1) * win.ch - \ + borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - \ cursorthickness, win.cw, cursorthickness); break; case 5: /* Blinking bar */ case 6: /* Steady bar */ XftDrawRect(xw.draw, &drawcol, - borderpx + curx * win.cw, - borderpx + term.c.y * win.ch, + borderpx + cx * win.cw, + borderpx + cy * win.ch, cursorthickness, win.ch); break; } } else { XftDrawRect(xw.draw, &drawcol, - borderpx + curx * win.cw, - borderpx + term.c.y * win.ch, + borderpx + cx * win.cw, + borderpx + cy * win.ch, win.cw - 1, 1); XftDrawRect(xw.draw, &drawcol, - borderpx + curx * win.cw, - borderpx + term.c.y * win.ch, + borderpx + cx * win.cw, + borderpx + cy * win.ch, 1, win.ch - 1); XftDrawRect(xw.draw, &drawcol, - borderpx + (curx + 1) * win.cw - 1, - borderpx + term.c.y * win.ch, + borderpx + (cx + 1) * win.cw - 1, + borderpx + cy * win.ch, 1, win.ch - 1); XftDrawRect(xw.draw, &drawcol, - borderpx + curx * win.cw, - borderpx + (term.c.y + 1) * win.ch - 1, + borderpx + cx * win.cw, + borderpx + (cy + 1) * win.ch - 1, win.cw, 1); } - oldx = curx, oldy = term.c.y; } void -- cgit v1.2.3 From a3beb626d2dae9d4d0883c7c8cb6ba58b0609105 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sat, 24 Feb 2018 15:32:48 -0600 Subject: Remove x.c dependency on term The xinit function only needs to the rows/cols, so pass those in rather than accessing term directly. With a bit of arithmetic, we are able to avoid the need for term.row and term.col in x2col, y2row, and xdrawglyphfontspecs as well, completing the removal. Term is now fully internal to st.c. Signed-off-by: Devin J. Pohly --- st.c | 22 +++++++++++++++++++++- st.h | 21 --------------------- x.c | 35 ++++++++++++++++++----------------- 3 files changed, 39 insertions(+), 39 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index 4bf6378..da832ed 100644 --- a/st.c +++ b/st.c @@ -95,6 +95,26 @@ enum escape_state { ESC_DCS =128, }; +/* Internal representation of the screen */ +typedef struct { + int row; /* nb row */ + int col; /* nb col */ + Line *line; /* screen */ + Line *alt; /* alternate screen */ + int *dirty; /* dirtyness of lines */ + TCursor c; /* cursor */ + int ocx; /* old cursor col */ + int ocy; /* old cursor row */ + int top; /* top scroll limit */ + int bot; /* bottom scroll limit */ + int mode; /* terminal mode flags */ + int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ + int *tabs; +} Term; + /* CSI Escape sequence structs */ /* ESC '[' [[ [] [;]] []] */ typedef struct { @@ -181,11 +201,11 @@ static char *base64dec(const char *); static ssize_t xwrite(int, const char *, size_t); /* Globals */ -Term term; int cmdfd; pid_t pid; int oldbutton = 3; /* button event on startup: 3 = release */ +static Term term; static Selection sel; static CSIEscape csiescseq; static STREscape strescseq; diff --git a/st.h b/st.h index 27c48cf..b5bc1b5 100644 --- a/st.h +++ b/st.h @@ -76,26 +76,6 @@ typedef struct { char state; } TCursor; -/* Internal representation of the screen */ -typedef struct { - int row; /* nb row */ - int col; /* nb col */ - Line *line; /* screen */ - Line *alt; /* alternate screen */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ - int ocy; /* old cursor row */ - int top; /* top scroll limit */ - int bot; /* bottom scroll limit */ - int mode; /* terminal mode flags */ - int esc; /* escape state flags */ - char trantbl[4]; /* charset table translation */ - int charset; /* current charset */ - int icharset; /* selected charset for sequence */ - int *tabs; -} Term; - /* Purely graphic info */ typedef struct { int tw, th; /* tty width and height */ @@ -168,7 +148,6 @@ void *xrealloc(void *, size_t); char *xstrdup(char *); /* Globals */ -extern Term term; extern int cmdfd; extern pid_t pid; extern int oldbutton; diff --git a/x.c b/x.c index d205ca7..873ff08 100644 --- a/x.c +++ b/x.c @@ -130,7 +130,7 @@ static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); static void xdrawglyph(Glyph, int, int); static void xclear(int, int, int, int); static int xgeommasktogravity(int); -static void xinit(void); +static void xinit(int, int); static void cresize(int, int); static void xresize(int, int); static int xloadfont(Font *, FcPattern *); @@ -299,18 +299,16 @@ int x2col(int x) { x -= borderpx; - x /= win.cw; - - return LIMIT(x, 0, term.col-1); + LIMIT(x, 0, win.tw - 1); + return x / win.cw; } int y2row(int y) { y -= borderpx; - y /= win.ch; - - return LIMIT(y, 0, term.row-1); + LIMIT(y, 0, win.th - 1); + return y / win.ch; } void @@ -984,7 +982,7 @@ xunloadfonts(void) } void -xinit(void) +xinit(int cols, int rows) { XGCValues gcvalues; Cursor cursor; @@ -1009,8 +1007,8 @@ xinit(void) xloadcols(); /* adjust fixed window geometry */ - win.w = 2 * borderpx + term.col * win.cw; - win.h = 2 * borderpx + term.row * win.ch; + win.w = 2 * borderpx + cols * win.cw; + win.h = 2 * borderpx + rows * win.ch; if (xw.gm & XNegative) xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; if (xw.gm & YNegative) @@ -1042,7 +1040,7 @@ xinit(void) XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); /* font spec buffer */ - xw.specbuf = xmalloc(term.col * sizeof(GlyphFontSpec)); + xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); /* Xft rendering context */ xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); @@ -1337,15 +1335,16 @@ 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, - winy + win.ch + ((y >= term.row-1)? win.h : 0)); + winy + win.ch + + ((winy + win.ch >= borderpx + win.th)? win.h : 0)); } - if (x + charlen >= term.col) { + if (winx + width >= borderpx + win.tw) { xclear(winx + width, (y == 0)? 0 : winy, win.w, - ((y >= term.row-1)? win.h : (winy + win.ch))); + ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); } if (y == 0) xclear(winx, 0, winx + width, borderpx); - if (y == term.row-1) + if (winy + win.ch >= borderpx + win.th) xclear(winx, winy + win.ch, winx + width, win.h); /* Clean up the region we want to draw to. */ @@ -1930,8 +1929,10 @@ run: } setlocale(LC_CTYPE, ""); XSetLocaleModifiers(""); - tnew(MAX(cols, 1), MAX(rows, 1)); - xinit(); + cols = MAX(cols, 1); + rows = MAX(rows, 1); + tnew(cols, rows); + xinit(cols, rows); xsetenv(); selinit(); run(); -- cgit v1.2.3 From 30683c70ab62fd37b5921cf72077b9aef2cb842e Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sat, 24 Feb 2018 16:16:12 -0600 Subject: Limit usage of extern to config.h globals Prefer passing arguments to declaring external global variables. The only remaining usage of extern is for config.h variables which are needed in st.c instead of x.c (where it is now included). Signed-off-by: Devin J. Pohly --- config.def.h | 2 +- st.c | 29 +++++++++++++++++------------ st.h | 9 ++------- x.c | 16 +++++++++------- 4 files changed, 29 insertions(+), 27 deletions(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index 616616a..82b1b09 100644 --- a/config.def.h +++ b/config.def.h @@ -16,7 +16,7 @@ static int borderpx = 2; * 4: value of shell in /etc/passwd * 5: value of shell in config.h */ -char *shell = "/bin/sh"; +static char *shell = "/bin/sh"; char *utmp = NULL; char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; diff --git a/st.c b/st.c index da832ed..ce32cc0 100644 --- a/st.c +++ b/st.c @@ -136,8 +136,7 @@ typedef struct { int narg; /* nb of args */ } STREscape; - -static void execsh(char **); +static void execsh(char *, char **); static void stty(char **); static void sigchld(int); static void ttywriteraw(const char *, size_t); @@ -201,15 +200,13 @@ static char *base64dec(const char *); static ssize_t xwrite(int, const char *, size_t); /* Globals */ -int cmdfd; -pid_t pid; -int oldbutton = 3; /* button event on startup: 3 = release */ - static Term term; static Selection sel; static CSIEscape csiescseq; static STREscape strescseq; static int iofd = 1; +static int cmdfd; +static pid_t pid; static uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; @@ -659,7 +656,7 @@ die(const char *errstr, ...) } void -execsh(char **args) +execsh(char *cmd, char **args) { char *sh, *prog; const struct passwd *pw; @@ -673,7 +670,7 @@ execsh(char **args) } if ((sh = getenv("SHELL")) == NULL) - sh = (pw->pw_shell[0]) ? pw->pw_shell : shell; + sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; if (args) prog = args[0]; @@ -745,8 +742,8 @@ stty(char **args) perror("Couldn't call stty"); } -void -ttynew(char *line, char *out, char **args) +int +ttynew(char *line, char *cmd, char *out, char **args) { int m, s; @@ -765,7 +762,7 @@ ttynew(char *line, char *out, char **args) die("open line failed: %s\n", strerror(errno)); dup2(cmdfd, 0); stty(args); - return; + return cmdfd; } /* seems to work fine on linux, openbsd and freebsd */ @@ -786,7 +783,7 @@ ttynew(char *line, char *out, char **args) die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); close(s); close(m); - execsh(args); + execsh(cmd, args); break; default: close(s); @@ -794,6 +791,7 @@ ttynew(char *line, char *out, char **args) signal(SIGCHLD, sigchld); break; } + return cmdfd; } size_t @@ -916,6 +914,13 @@ ttyresize(int tw, int th) fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); } +void +ttyhangup() +{ + /* Send SIGHUP to shell */ + kill(pid, SIGHUP); +} + int tattrset(int attr) { diff --git a/st.h b/st.h index b5bc1b5..0a7472b 100644 --- a/st.h +++ b/st.h @@ -125,7 +125,8 @@ int tattrset(int); void tnew(int, int); void tresize(int, int); void tsetdirtattr(int); -void ttynew(char *, char *, char **); +void ttyhangup(void); +int ttynew(char *, char *, char *, char **); size_t ttyread(void); void ttyresize(int, int); void ttywrite(const char *, size_t, int); @@ -147,13 +148,7 @@ void *xmalloc(size_t); void *xrealloc(void *, size_t); char *xstrdup(char *); -/* Globals */ -extern int cmdfd; -extern pid_t pid; -extern int oldbutton; - /* config.h globals */ -extern char *shell; extern char *utmp; extern char *stty_args; extern char *vtiden; diff --git a/x.c b/x.c index 873ff08..970d6dd 100644 --- a/x.c +++ b/x.c @@ -227,6 +227,8 @@ static char *opt_line = NULL; static char *opt_name = NULL; static char *opt_title = NULL; +static int oldbutton = 3; /* button event on startup: 3 = release */ + void clipcopy(const Arg *dummy) { @@ -1733,8 +1735,7 @@ cmessage(XEvent *e) win.mode &= ~MODE_FOCUSED; } } else if (e->xclient.data.l[0] == xw.wmdeletewin) { - /* Send SIGHUP to shell */ - kill(pid, SIGHUP); + ttyhangup(); exit(0); } } @@ -1755,6 +1756,7 @@ run(void) int w = win.w, h = win.h; fd_set rfd; int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0; + int ttyfd; struct timespec drawtimeout, *tv = NULL, now, last, lastblink; long deltatime; @@ -1774,7 +1776,7 @@ run(void) } } while (ev.type != MapNotify); - ttynew(opt_line, opt_io, opt_cmd); + ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); cresize(w, h); clock_gettime(CLOCK_MONOTONIC, &last); @@ -1782,15 +1784,15 @@ run(void) for (xev = actionfps;;) { FD_ZERO(&rfd); - FD_SET(cmdfd, &rfd); + FD_SET(ttyfd, &rfd); FD_SET(xfd, &rfd); - if (pselect(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { + if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { if (errno == EINTR) continue; die("select failed: %s\n", strerror(errno)); } - if (FD_ISSET(cmdfd, &rfd)) { + if (FD_ISSET(ttyfd, &rfd)) { ttyread(); if (blinktimeout) { blinkset = tattrset(ATTR_BLINK); @@ -1834,7 +1836,7 @@ run(void) if (xev && !FD_ISSET(xfd, &rfd)) xev--; - if (!FD_ISSET(cmdfd, &rfd) && !FD_ISSET(xfd, &rfd)) { + if (!FD_ISSET(ttyfd, &rfd) && !FD_ISSET(xfd, &rfd)) { if (blinkset) { if (TIMEDIFF(now, lastblink) \ > blinktimeout) { -- cgit v1.2.3 From e0215d53770a9b6bc6e5d7b9a603ecd34dbd7100 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sat, 24 Feb 2018 16:32:20 -0600 Subject: Reduce visibility wherever possible When possible, declare functions/variables static and move struct definitions out of headers. In order to allow utf8decode to become internal, use codepoint for DECSCUSR extension directly. Signed-off-by: Devin J. Pohly --- st.c | 31 ++++++++++++++++++++++++++++++- st.h | 40 ---------------------------------------- win.h | 1 - x.c | 15 +++++++++++++-- 4 files changed, 43 insertions(+), 44 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index ce32cc0..f46aab6 100644 --- a/st.c +++ b/st.c @@ -36,6 +36,7 @@ /* Arbitrary sizes */ #define UTF_INVALID 0xFFFD +#define UTF_SIZ 4 #define ESC_BUF_SIZ (128*UTF_SIZ) #define ESC_ARG_SIZ 16 #define STR_BUF_SIZ ESC_BUF_SIZ @@ -95,6 +96,31 @@ enum escape_state { ESC_DCS =128, }; +typedef struct { + Glyph attr; /* current char attributes */ + int x; + int y; + char state; +} TCursor; + +typedef struct { + int mode; + int type; + int snap; + /* + * Selection variables: + * nb – normalized coordinates of the beginning of the selection + * ne – normalized coordinates of the end of the selection + * ob – original coordinates of the beginning of the selection + * oe – original coordinates of the end of the selection + */ + struct { + int x, y; + } nb, ne, ob, oe; + + int alt; +} Selection; + /* Internal representation of the screen */ typedef struct { int row; /* nb row */ @@ -187,15 +213,18 @@ static void tstrsequence(uchar); static void drawregion(int, int, int, int); +static void selnormalize(void); static void selscroll(int, int); static void selsnap(int *, int *, int); +static size_t utf8decode(const char *, Rune *, size_t); static Rune utf8decodebyte(char, size_t *); static char utf8encodebyte(Rune, size_t); -static char *utf8strchr(char *s, Rune u); +static char *utf8strchr(char *, Rune); static size_t utf8validate(Rune *, size_t); static char *base64dec(const char *); +static char base64dec_getc(const char **); static ssize_t xwrite(int, const char *, size_t); diff --git a/st.h b/st.h index 0a7472b..1015fc6 100644 --- a/st.h +++ b/st.h @@ -1,8 +1,5 @@ /* See LICENSE for license details. */ -/* Arbitrary sizes */ -#define UTF_SIZ 4 - /* macros */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) @@ -69,41 +66,6 @@ typedef struct { typedef Glyph *Line; -typedef struct { - Glyph attr; /* current char attributes */ - int x; - int y; - char state; -} TCursor; - -/* Purely graphic info */ -typedef struct { - int tw, th; /* tty width and height */ - int w, h; /* window width and height */ - int ch; /* char height */ - int cw; /* char width */ - int mode; /* window state/mode flags */ - int cursor; /* cursor style */ -} TermWindow; - -typedef struct { - int mode; - int type; - int snap; - /* - * Selection variables: - * nb – normalized coordinates of the beginning of the selection - * ne – normalized coordinates of the end of the selection - * ob – original coordinates of the beginning of the selection - * oe – original coordinates of the end of the selection - */ - struct { - int x, y; - } nb, ne, ob, oe; - - int alt; -} Selection; - typedef union { int i; uint ui; @@ -137,11 +99,9 @@ void selclear(void); void selinit(void); void selstart(int, int, int); void selextend(int, int, int, int); -void selnormalize(void); int selected(int, int); char *getsel(void); -size_t utf8decode(const char *, Rune *, size_t); size_t utf8encode(Rune, char *); void *xmalloc(size_t); diff --git a/win.h b/win.h index 7a866fd..31f327d 100644 --- a/win.h +++ b/win.h @@ -27,7 +27,6 @@ void xbell(void); void xclipcopy(void); void xdrawcursor(int, int, Glyph, int, int, Glyph); void xdrawline(Line, int, int, int); -void xhints(void); void xfinishdraw(void); void xloadcols(void); int xsetcolorname(int, const char *); diff --git a/x.c b/x.c index 970d6dd..f7b0528 100644 --- a/x.c +++ b/x.c @@ -75,6 +75,15 @@ typedef XftColor Color; typedef XftGlyphFontSpec GlyphFontSpec; /* Purely graphic info */ +typedef struct { + int tw, th; /* tty width and height */ + int w, h; /* window width and height */ + int ch; /* char height */ + int cw; /* char width */ + int mode; /* window state/mode flags */ + int cursor; /* cursor style */ +} TermWindow; + typedef struct { Display *dpy; Colormap cmap; @@ -133,6 +142,8 @@ static int xgeommasktogravity(int); static void xinit(int, int); static void cresize(int, int); static void xresize(int, int); +static void xhints(void); +static int xloadcolor(int, const char *, Color *); static int xloadfont(Font *, FcPattern *); static void xloadfonts(char *, double); static void xunloadfont(Font *); @@ -1430,8 +1441,8 @@ 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: snowman */ - utf8decode("☃", &g.u, UTF_SIZ); + case 7: /* st extension: snowman (U+2603) */ + g.u = 0x2603; case 0: /* Blinking Block */ case 1: /* Blinking Block (Default) */ case 2: /* Steady Block */ -- cgit v1.2.3 From 403c57ebb5b3745ff93e49b87e526c49dc59a5b9 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Sat, 24 Feb 2018 16:45:42 -0600 Subject: Clean up #includes Signed-off-by: Devin J. Pohly --- st.c | 7 ------- st.h | 3 +++ x.c | 3 +-- 3 files changed, 4 insertions(+), 9 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index f46aab6..543c615 100644 --- a/st.c +++ b/st.c @@ -3,24 +3,17 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include #include -#include -#include #include #include -#include -#include #include -#include #include #include "st.h" diff --git a/st.h b/st.h index 1015fc6..dac64d8 100644 --- a/st.h +++ b/st.h @@ -1,5 +1,8 @@ /* See LICENSE for license details. */ +#include +#include + /* macros */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) diff --git a/x.c b/x.c index f7b0528..d0acfee 100644 --- a/x.c +++ b/x.c @@ -1,15 +1,14 @@ /* See LICENSE for license details. */ #include +#include #include #include -#include #include #include #include #include #include #include -#include #include #include #include -- cgit v1.2.3 From 67d0cb65d0794e2d91e72e5fa1e3612172e5812e Mon Sep 17 00:00:00 2001 From: Quentin Rameau Date: Tue, 11 Sep 2018 13:11:28 +0200 Subject: Remove the ISO 14755 feature And move it to the patches section. Keeping it would force to add an exec pledge on OpenBSD, and some people think it's bloated, so bye! --- config.def.h | 1 - st.1 | 4 ---- st.c | 26 -------------------------- st.h | 1 - 4 files changed, 32 deletions(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index 82b1b09..823e79f 100644 --- a/config.def.h +++ b/config.def.h @@ -177,7 +177,6 @@ static Shortcut shortcuts[] = { { TERMMOD, XK_V, clippaste, {.i = 0} }, { TERMMOD, XK_Y, selpaste, {.i = 0} }, { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { TERMMOD, XK_I, iso14755, {.i = 0} }, }; /* diff --git a/st.1 b/st.1 index 81bceff..e8d6059 100644 --- a/st.1 +++ b/st.1 @@ -159,10 +159,6 @@ Copy the selected text to the clipboard selection. .TP .B Ctrl-Shift-v Paste from the clipboard selection. -.TP -.B Ctrl-Shift-i -Launch dmenu to enter a unicode codepoint and send the corresponding glyph -to st. .SH CUSTOMIZATION .B st can be customized by creating a custom config.h and (re)compiling the source diff --git a/st.c b/st.c index 76bb3ea..574dbee 100644 --- a/st.c +++ b/st.c @@ -38,15 +38,11 @@ /* macros */ #define IS_SET(flag) ((term.mode & (flag)) != 0) -#define NUMMAXLEN(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) #define ISDELIM(u) (utf8strchr(worddelimiters, u) != NULL) -/* constants */ -#define ISO14755CMD "dmenu -w \"$WINDOWID\" -p codepoint: 7) - return; - if ((utf32 = strtoul(us, &e, 16)) == ULONG_MAX || - (*e != '\n' && *e != '\0')) - return; - - ttywrite(uc, utf8encode(utf32, uc), 1); -} - void toggleprinter(const Arg *arg) { diff --git a/st.h b/st.h index dac64d8..38c61c4 100644 --- a/st.h +++ b/st.h @@ -80,7 +80,6 @@ void die(const char *, ...); void redraw(void); void draw(void); -void iso14755(const Arg *); void printscreen(const Arg *); void printsel(const Arg *); void sendbreak(const Arg *); -- cgit v1.2.3 From d5efd256aa3840476579a27293ef1fb92a4b51e7 Mon Sep 17 00:00:00 2001 From: Lauri Tirkkonen Date: Wed, 13 Mar 2019 19:40:52 +0200 Subject: replace utf8strchr with wcschr --- config.def.h | 4 ++-- st.c | 20 +------------------- st.h | 2 +- 3 files changed, 4 insertions(+), 22 deletions(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index 0e01717..482901e 100644 --- a/config.def.h +++ b/config.def.h @@ -30,9 +30,9 @@ static float chscale = 1.0; /* * word delimiter string * - * More advanced example: " `'\"()[]{}" + * More advanced example: L" `'\"()[]{}" */ -char *worddelimiters = " "; +wchar_t *worddelimiters = L" "; /* selection timeouts (in milliseconds) */ static unsigned int doubleclicktimeout = 300; diff --git a/st.c b/st.c index d35f89d..812f30c 100644 --- a/st.c +++ b/st.c @@ -41,7 +41,7 @@ #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) (utf8strchr(worddelimiters, u) != NULL) +#define ISDELIM(u) (u != 0 && wcschr(worddelimiters, u) != NULL) enum term_mode { MODE_WRAP = 1 << 0, @@ -210,7 +210,6 @@ static void selsnap(int *, int *, int); static size_t utf8decode(const char *, Rune *, size_t); static Rune utf8decodebyte(char, size_t *); static char utf8encodebyte(Rune, size_t); -static char *utf8strchr(char *, Rune); static size_t utf8validate(Rune *, size_t); static char *base64dec(const char *); @@ -337,23 +336,6 @@ utf8encodebyte(Rune u, size_t i) return utfbyte[i] | (u & ~utfmask[i]); } -char * -utf8strchr(char *s, Rune u) -{ - Rune r; - size_t i, j, len; - - len = strlen(s); - for (i = 0, j = 0; i < len; i += j) { - if (!(j = utf8decode(&s[i], &r, len - i))) - break; - if (r == u) - return &(s[i]); - } - - return NULL; -} - size_t utf8validate(Rune *u, size_t i) { diff --git a/st.h b/st.h index 38c61c4..4da3051 100644 --- a/st.h +++ b/st.h @@ -114,7 +114,7 @@ char *xstrdup(char *); extern char *utmp; extern char *stty_args; extern char *vtiden; -extern char *worddelimiters; +extern wchar_t *worddelimiters; extern int allowaltscreen; extern char *termname; extern unsigned int tabspaces; -- cgit v1.2.3 From add0211522737b79dad990ccd65c8af63b5cc1dd Mon Sep 17 00:00:00 2001 From: Lauri Tirkkonen Date: Wed, 13 Mar 2019 17:15:04 +0200 Subject: use iswspace()/iswpunct() to find word delimiters this inverts the configuration logic: you no longer provide a list of delimiters -- all space and punctuation characters are considered delimiters, unless listed in extrawordchars. --- config.def.h | 7 ++++--- st.c | 3 ++- st.h | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index 482901e..9ce45a7 100644 --- a/config.def.h +++ b/config.def.h @@ -28,11 +28,12 @@ static float cwscale = 1.0; static float chscale = 1.0; /* - * word delimiter string + * all space and punctuation characters are considered word delimiters, unless + * listed here. * - * More advanced example: L" `'\"()[]{}" + * More advanced example: L"#$%&+,-./:=?_~" */ -wchar_t *worddelimiters = L" "; +wchar_t *extrawordchars = L"./:"; /* selection timeouts (in milliseconds) */ static unsigned int doubleclicktimeout = 300; diff --git a/st.c b/st.c index 812f30c..c383b43 100644 --- a/st.c +++ b/st.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "st.h" #include "win.h" @@ -41,7 +42,7 @@ #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) (u != 0 && wcschr(worddelimiters, u) != NULL) +#define ISDELIM(u) ((iswspace(u) || iswpunct(u)) && wcschr(extrawordchars, u) == NULL) enum term_mode { MODE_WRAP = 1 << 0, diff --git a/st.h b/st.h index 4da3051..a3b19de 100644 --- a/st.h +++ b/st.h @@ -114,7 +114,7 @@ char *xstrdup(char *); extern char *utmp; extern char *stty_args; extern char *vtiden; -extern wchar_t *worddelimiters; +extern wchar_t *extrawordchars; extern int allowaltscreen; extern char *termname; extern unsigned int tabspaces; -- cgit v1.2.3 From 21367a040f056f6a207fafa066bd1cb2d9cae586 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 15 Mar 2019 20:40:16 +0100 Subject: revert part of commit add0211522737b79dad990ccd65c8af63b5cc1dd "use iswspace()/iswpunct() to find word delimiters this inverts the configuration logic: you no longer provide a list of delimiters -- all space and punctuation characters are considered delimiters, unless listed in extrawordchars." Feedback from IRC and personal preference. --- config.def.h | 7 +++---- st.c | 3 +-- st.h | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index ac5e8ce..482901e 100644 --- a/config.def.h +++ b/config.def.h @@ -28,12 +28,11 @@ static float cwscale = 1.0; static float chscale = 1.0; /* - * all space and punctuation characters are considered word delimiters, unless - * listed here. + * word delimiter string * - * More advanced example: L"#$%&+,-./:=?_~" + * More advanced example: L" `'\"()[]{}" */ -wchar_t *extrawordchars = L""; +wchar_t *worddelimiters = L" "; /* selection timeouts (in milliseconds) */ static unsigned int doubleclicktimeout = 300; diff --git a/st.c b/st.c index 48d65ca..8e6ccb5 100644 --- a/st.c +++ b/st.c @@ -16,7 +16,6 @@ #include #include #include -#include #include "st.h" #include "win.h" @@ -42,7 +41,7 @@ #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) ((iswspace(u) || iswpunct(u)) && wcschr(extrawordchars, u) == NULL) +#define ISDELIM(u) (u && wcschr(worddelimiters, u)) enum term_mode { MODE_WRAP = 1 << 0, diff --git a/st.h b/st.h index a3b19de..4da3051 100644 --- a/st.h +++ b/st.h @@ -114,7 +114,7 @@ char *xstrdup(char *); extern char *utmp; extern char *stty_args; extern char *vtiden; -extern wchar_t *extrawordchars; +extern wchar_t *worddelimiters; extern int allowaltscreen; extern char *termname; extern unsigned int tabspaces; -- cgit v1.2.3 From ba7f4d69af62d20e13fea78a408095e017410651 Mon Sep 17 00:00:00 2001 From: "Avi Halachmi (:avih)" Date: Thu, 10 Oct 2019 23:02:26 +0300 Subject: mouse shortcuts: allow same functions as kb shortcuts Previously mouse shortcuts supported only ttywrite. This required adding an "Arg" function ttysend - which does what the original mouse shortcuts did. --- config.def.h | 6 +++--- st.h | 1 + x.c | 20 ++++++++++++++------ 3 files changed, 18 insertions(+), 9 deletions(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index 6ebea98..36ff6ce 100644 --- a/config.def.h +++ b/config.def.h @@ -155,9 +155,9 @@ static unsigned int defaultattr = 11; * Beware that overloading Button1 will disable the selection. */ static MouseShortcut mshortcuts[] = { - /* button mask string */ - { Button4, XK_ANY_MOD, "\031" }, - { Button5, XK_ANY_MOD, "\005" }, + /* mask button function argument */ + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, }; /* Internal keyboard shortcuts. */ diff --git a/st.h b/st.h index 4da3051..a1928ca 100644 --- a/st.h +++ b/st.h @@ -74,6 +74,7 @@ typedef union { uint ui; float f; const void *v; + const char *s; } Arg; void die(const char *, ...); diff --git a/x.c b/x.c index 5828a3b..2a05a81 100644 --- a/x.c +++ b/x.c @@ -29,9 +29,10 @@ typedef struct { } Shortcut; typedef struct { - uint b; - uint mask; - char *s; + uint mod; + uint button; + void (*func)(const Arg *); + const Arg arg; } MouseShortcut; typedef struct { @@ -56,6 +57,7 @@ static void selpaste(const Arg *); static void zoom(const Arg *); static void zoomabs(const Arg *); static void zoomreset(const Arg *); +static void ttysend(const Arg *); /* config.h for applying patches and the configuration. */ #include "config.h" @@ -312,6 +314,12 @@ zoomreset(const Arg *arg) } } +void +ttysend(const Arg *arg) +{ + ttywrite(arg->s, strlen(arg->s), 1); +} + int evcol(XEvent *e) { @@ -421,9 +429,9 @@ bpress(XEvent *e) } for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { - if (e->xbutton.button == ms->b - && match(ms->mask, e->xbutton.state)) { - ttywrite(ms->s, strlen(ms->s), 1); + if (e->xbutton.button == ms->button + && match(ms->mod, e->xbutton.state)) { + ms->func(&(ms->arg)); return; } } -- cgit v1.2.3 From 21e0d6e8b8d20903494386e7e6f43201b3761154 Mon Sep 17 00:00:00 2001 From: "Roberto E. Vargas Caballero" Date: Fri, 10 Apr 2020 22:06:32 +0200 Subject: Add support for scroll(1) Scroll is a program that stores all the lines of its child and be used in st as a way of implementing scrollback. This solution is much better than implementing the scrollback in st itself because having a different program allows to use it in any other program without doing modifications to those programs. --- config.def.h | 3 ++- st.1 | 3 ++- st.c | 16 ++++++++++------ st.h | 1 + 4 files changed, 15 insertions(+), 8 deletions(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index 546edda..dfcbda9 100644 --- a/config.def.h +++ b/config.def.h @@ -11,13 +11,14 @@ static int borderpx = 2; /* * What program is execed by st depends of these precedence rules: * 1: program passed with -e - * 2: utmp option + * 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/sh"; char *utmp = NULL; +char *scroll = NULL; char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; /* identification sequence returned in DA and DECID */ diff --git a/st.1 b/st.1 index e8d6059..39120b4 100644 --- a/st.1 +++ b/st.1 @@ -170,7 +170,8 @@ See the LICENSE file for the terms of redistribution. .SH SEE ALSO .BR tabbed (1), .BR utmp (1), -.BR stty (1) +.BR stty (1), +.BR scroll (1) .SH BUGS See the TODO file in the distribution. diff --git a/st.c b/st.c index 3e48410..5f2352a 100644 --- a/st.c +++ b/st.c @@ -664,7 +664,7 @@ die(const char *errstr, ...) void execsh(char *cmd, char **args) { - char *sh, *prog; + char *sh, *prog, *arg; const struct passwd *pw; errno = 0; @@ -678,13 +678,17 @@ execsh(char *cmd, char **args) if ((sh = getenv("SHELL")) == NULL) sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; - if (args) + if (args) { prog = args[0]; - else if (utmp) - prog = utmp; - else + arg = NULL; + } else if (scroll || utmp) { + prog = scroll ? scroll : utmp; + arg = scroll ? utmp : NULL; + } else { prog = sh; - DEFAULT(args, ((char *[]) {prog, NULL})); + arg = NULL; + } + DEFAULT(args, ((char *[]) {prog, arg, NULL})); unsetenv("COLUMNS"); unsetenv("LINES"); diff --git a/st.h b/st.h index a1928ca..d978458 100644 --- a/st.h +++ b/st.h @@ -113,6 +113,7 @@ char *xstrdup(char *); /* config.h globals */ extern char *utmp; +extern char *scroll; extern char *stty_args; extern char *vtiden; extern wchar_t *worddelimiters; -- cgit v1.2.3 From a2a704492b9f4d2408d180f7aeeacf4c789a1d67 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sat, 30 May 2020 21:56:18 +0200 Subject: config.def.h: add an option allowwindowops, by default off (secure) Similar to the xterm AllowWindowOps option, this is an option to allow or disallow certain (non-interactive) operations that can be insecure or exploited. NOTE: xsettitle() is not guarded by this because st does not support printing the window title. Else this could be exploitable (arbitrary code execution). Similar problems have been found in the past in other terminal emulators. The sequence for base64-encoded clipboard copy is now guarded because it allows a sequence written to the terminal to manipulate the clipboard of the running user non-interactively, for example: printf '\x1b]52;0;ZWNobyBoaQ0=\a' --- config.def.h | 4 ++++ st.c | 2 +- st.h | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index 293e00c..6f05dce 100644 --- a/config.def.h +++ b/config.def.h @@ -43,6 +43,10 @@ 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 diff --git a/st.c b/st.c index 2d901ab..ef8abd5 100644 --- a/st.c +++ b/st.c @@ -1861,7 +1861,7 @@ strhandle(void) xsettitle(strescseq.args[1]); return; case 52: - if (narg > 2) { + if (narg > 2 && allowwindowops) { dec = base64dec(strescseq.args[2]); if (dec) { xsetsel(dec); diff --git a/st.h b/st.h index d978458..3d351b6 100644 --- a/st.h +++ b/st.h @@ -118,6 +118,7 @@ extern char *stty_args; extern char *vtiden; extern wchar_t *worddelimiters; extern int allowaltscreen; +extern int allowwindowops; extern char *termname; extern unsigned int tabspaces; extern unsigned int defaultfg; -- cgit v1.2.3 From 4536f46cfff50c66a115755def0155d8e246b02f Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Sun, 28 Mar 2021 21:16:59 +0200 Subject: Mild const-correctness improvements. Only touch a few things, the main focus is to improve code readability. --- st.c | 44 +++++++++++++++++++++++--------------------- st.h | 4 ++-- x.c | 6 +++--- 3 files changed, 28 insertions(+), 26 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index abbbe4b..ebdf360 100644 --- a/st.c +++ b/st.c @@ -186,18 +186,18 @@ static void tputc(Rune); static void treset(void); static void tscrollup(int, int); static void tscrolldown(int, int); -static void tsetattr(int *, int); -static void tsetchar(Rune, Glyph *, int, int); +static void tsetattr(const int *, int); +static void tsetchar(Rune, const Glyph *, int, int); static void tsetdirt(int, int); static void tsetscroll(int, int); 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 void tfulldirt(void); static void tcontrolcode(uchar ); static void tdectest(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 tstrsequence(uchar); @@ -226,10 +226,10 @@ static int iofd = 1; static int cmdfd; static pid_t pid; -static uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; +static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; ssize_t xwrite(int fd, const char *s, size_t len) @@ -269,12 +269,14 @@ xrealloc(void *p, size_t len) } 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)); - return s; + return p; } size_t @@ -518,7 +520,7 @@ selsnap(int *x, int *y, int direction) { int newx, newy, xt, yt; int delim, prevdelim; - Glyph *gp, *prevgp; + const Glyph *gp, *prevgp; switch (sel.snap) { case SNAP_WORD: @@ -591,7 +593,7 @@ getsel(void) { char *str, *ptr; int y, bufsize, lastx, linelen; - Glyph *gp, *last; + const Glyph *gp, *last; if (sel.ob.x == -1) return NULL; @@ -758,7 +760,7 @@ stty(char **args) } int -ttynew(char *line, char *cmd, char *out, char **args) +ttynew(const char *line, char *cmd, const char *out, char **args) { int m, s; @@ -1186,9 +1188,9 @@ tmoveto(int x, int y) } 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 */ 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ @@ -1300,7 +1302,7 @@ tdeleteline(int n) } int32_t -tdefcolor(int *attr, int *npar, int l) +tdefcolor(const int *attr, int *npar, int l) { int32_t idx = -1; uint r, g, b; @@ -1350,7 +1352,7 @@ tdefcolor(int *attr, int *npar, int l) } void -tsetattr(int *attr, int l) +tsetattr(const int *attr, int l) { int i; int32_t idx; @@ -1468,9 +1470,9 @@ tsetscroll(int t, int b) } 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) { if (priv) { @@ -2020,7 +2022,7 @@ void tdumpline(int n) { char buf[UTF_SIZ]; - Glyph *bp, *end; + const Glyph *bp, *end; bp = &term.line[n][0]; end = &bp[MIN(tlinelen(n), term.col) - 1]; diff --git a/st.h b/st.h index 3d351b6..fa2eddf 100644 --- a/st.h +++ b/st.h @@ -91,7 +91,7 @@ void tnew(int, int); void tresize(int, int); void tsetdirtattr(int); void ttyhangup(void); -int ttynew(char *, char *, char *, char **); +int ttynew(const char *, char *, const char *, char **); size_t ttyread(void); void ttyresize(int, int); void ttywrite(const char *, size_t, int); @@ -109,7 +109,7 @@ size_t utf8encode(Rune, char *); void *xmalloc(size_t); void *xrealloc(void *, size_t); -char *xstrdup(char *); +char *xstrdup(const char *); /* config.h globals */ extern char *utmp; diff --git a/x.c b/x.c index 8bf998e..7186040 100644 --- a/x.c +++ b/x.c @@ -156,7 +156,7 @@ static void xresize(int, int); static void xhints(void); static int xloadcolor(int, const char *, Color *); static int xloadfont(Font *, FcPattern *); -static void xloadfonts(char *, double); +static void xloadfonts(const char *, double); static void xunloadfont(Font *); static void xunloadfonts(void); static void xsetenv(void); @@ -952,7 +952,7 @@ xloadfont(Font *f, FcPattern *pattern) } void -xloadfonts(char *fontstr, double fontsize) +xloadfonts(const char *fontstr, double fontsize) { FcPattern *pattern; double fontval; @@ -960,7 +960,7 @@ xloadfonts(char *fontstr, double fontsize) if (fontstr[0] == '-') pattern = XftXlfdParse(fontstr, False, False); else - pattern = FcNameParse((FcChar8 *)fontstr); + pattern = FcNameParse((const FcChar8 *)fontstr); if (!pattern) die("can't open font %s\n", fontstr); -- cgit v1.2.3 From 8e310303903792c010d03c046ba75f8b18f7d3a7 Mon Sep 17 00:00:00 2001 From: Raheman Vaiya Date: Sun, 26 Dec 2021 18:57:04 +0100 Subject: Add support for OSC color sequences --- config.def.h | 8 +++--- st.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- st.h | 3 +++ x.c | 13 ++++++++++ 4 files changed, 100 insertions(+), 4 deletions(-) (limited to 'st.h') diff --git a/config.def.h b/config.def.h index 6f05dce..91ab8ca 100644 --- a/config.def.h +++ b/config.def.h @@ -120,6 +120,8 @@ static const char *colorname[] = { /* more colors can be added after 255 to use with DefaultXX */ "#cccccc", "#555555", + "gray90", /* default foreground colour */ + "black", /* default background colour */ }; @@ -127,9 +129,9 @@ 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; +unsigned int defaultfg = 258; +unsigned int defaultbg = 259; +unsigned int defaultcs = 256; static unsigned int defaultrcs = 257; /* diff --git a/st.c b/st.c index a9338e1..781dbf2 100644 --- a/st.c +++ b/st.c @@ -1842,6 +1842,42 @@ csireset(void) memset(&csiescseq, 0, sizeof(csiescseq)); } +void +osc4_color_response(int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(num, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num); + return; + } + + n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + +void +osc_color_response(int index, int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(index, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc color %d\n", index); + return; + } + + n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + void strhandle(void) { @@ -1880,6 +1916,45 @@ strhandle(void) } } return; + case 10: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultfg, 10); + else if (xsetcolorname(defaultfg, p)) + fprintf(stderr, "erresc: invalid foreground color: %s\n", p); + else + redraw(); + break; + case 11: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultbg, 11); + else if (xsetcolorname(defaultbg, p)) + fprintf(stderr, "erresc: invalid background color: %s\n", p); + else + redraw(); + break; + case 12: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultcs, 12); + else if (xsetcolorname(defaultcs, p)) + fprintf(stderr, "erresc: invalid cursor color: %s\n", p); + else + redraw(); + break; case 4: /* color set */ if (narg < 3) break; @@ -1887,7 +1962,10 @@ strhandle(void) /* FALLTHROUGH */ case 104: /* color reset, here p = NULL */ j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (xsetcolorname(j, p)) { + + if (!strcmp(p, "?")) + osc4_color_response(j); + else if (xsetcolorname(j, p)) { if (par == 104 && narg <= 1) return; /* color reset without parameter */ fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", diff --git a/st.h b/st.h index fa2eddf..519b9bd 100644 --- a/st.h +++ b/st.h @@ -111,6 +111,8 @@ void *xmalloc(size_t); void *xrealloc(void *, size_t); char *xstrdup(const char *); +int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b); + /* config.h globals */ extern char *utmp; extern char *scroll; @@ -123,3 +125,4 @@ extern char *termname; extern unsigned int tabspaces; extern unsigned int defaultfg; extern unsigned int defaultbg; +extern unsigned int defaultcs; diff --git a/x.c b/x.c index 89786b8..8a16faa 100644 --- a/x.c +++ b/x.c @@ -799,6 +799,19 @@ xloadcols(void) 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 xsetcolorname(int x, const char *name) { -- cgit v1.2.3 From 8629d9a1da72cc18568a8f146307b0e939b77ebf Mon Sep 17 00:00:00 2001 From: NRK Date: Fri, 7 Jan 2022 23:21:04 +0600 Subject: code-golfing: cleanup osc color related code * adds missing function prototype * move xgetcolor() prototype to win.h (that's where all the other x.c func prototype seems to be declared at) * check for snprintf error/truncation * reduces code duplication for osc 10/11/12 * unify osc_color_response() and osc4_color_response() into a single function the latter two was suggested by Quentin Rameau in his patch review on the hackers list. --- st.c | 90 ++++++++++++++++++++++++------------------------------------------- st.h | 2 -- win.h | 1 + 3 files changed, 33 insertions(+), 60 deletions(-) (limited to 'st.h') diff --git a/st.c b/st.c index f43cfd3..6ba467d 100644 --- a/st.c +++ b/st.c @@ -161,6 +161,7 @@ static void csidump(void); static void csihandle(void); static void csiparse(void); static void csireset(void); +static void osc_color_response(int, int, int); static int eschandle(uchar); static void strdump(void); static void strhandle(void); @@ -1835,39 +1836,28 @@ csireset(void) } void -osc4_color_response(int num) +osc_color_response(int num, int index, int is_osc4) { int n; char buf[32]; unsigned char r, g, b; - if (xgetcolor(num, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num); + 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]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - num, r, r, g, g, b, b); - - ttywrite(buf, n, 1); -} - -void -osc_color_response(int index, int num) -{ - int n; - char buf[32]; - unsigned char r, g, b; - - if (xgetcolor(index, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch osc color %d\n", 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); } - - n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - num, r, r, g, g, b, b); - - ttywrite(buf, n, 1); } void @@ -1875,6 +1865,11 @@ strhandle(void) { char *p = NULL, *dec; 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); strparse(); @@ -1909,43 +1904,22 @@ strhandle(void) } return; case 10: - if (narg < 2) - break; - - p = strescseq.args[1]; - - if (!strcmp(p, "?")) - osc_color_response(defaultfg, 10); - else if (xsetcolorname(defaultfg, p)) - fprintf(stderr, "erresc: invalid foreground color: %s\n", p); - else - tfulldirt(); - return; case 11: - if (narg < 2) - break; - - p = strescseq.args[1]; - - if (!strcmp(p, "?")) - osc_color_response(defaultbg, 11); - else if (xsetcolorname(defaultbg, p)) - fprintf(stderr, "erresc: invalid background color: %s\n", p); - else - tfulldirt(); - return; case 12: if (narg < 2) break; - p = strescseq.args[1]; - - if (!strcmp(p, "?")) - osc_color_response(defaultcs, 12); - else if (xsetcolorname(defaultcs, p)) - fprintf(stderr, "erresc: invalid cursor color: %s\n", p); - else + 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 */ if (narg < 3) @@ -1955,9 +1929,9 @@ strhandle(void) case 104: /* color reset */ j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (p && !strcmp(p, "?")) - osc4_color_response(j); - else if (xsetcolorname(j, p)) { + if (p && !strcmp(p, "?")) { + osc_color_response(j, 0, 1); + } else if (xsetcolorname(j, p)) { if (par == 104 && narg <= 1) return; /* color reset without parameter */ fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", diff --git a/st.h b/st.h index 519b9bd..fd3b0d8 100644 --- a/st.h +++ b/st.h @@ -111,8 +111,6 @@ void *xmalloc(size_t); void *xrealloc(void *, size_t); char *xstrdup(const char *); -int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b); - /* config.h globals */ extern char *utmp; extern char *scroll; diff --git a/win.h b/win.h index e6e4369..6de960d 100644 --- a/win.h +++ b/win.h @@ -30,6 +30,7 @@ void xdrawline(Line, int, int, int); void xfinishdraw(void); void xloadcols(void); int xsetcolorname(int, const char *); +int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *); void xseticontitle(char *); void xsettitle(char *); int xsetcursor(int); -- cgit v1.2.3