about summary refs log tree commit diff stats
path: root/dwm.h
blob: f7bebb05ef5899664b2d3ea452164afcda0eb58f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
 * See LICENSE file for license details.
 */

#include <X11/Xlib.h>
#include CONFIG

/* mask shorthands, used in event.c and client.c */
#define ButtonMask	(ButtonPressMask | ButtonReleaseMask)
#define MouseMask	(ButtonMask | PointerMotionMask)

typedef union Arg Arg;
typedef struct Client Client;
typedef struct DC DC;
typedef struct Fnt Fnt;

union Arg {
	const char **argv;
	int i;
};

/* atoms */
enum { NetSupported, NetWMName, NetLast };
enum { WMProtocols, WMDelete, WMLast };

/* cursor */
enum { CurNormal, CurResize, CurMove, CurLast };

/* windowcorners */
typedef enum { TopLeft, TopRight, BotLeft, BotRight } Corner;

struct Fnt {
	int ascent;
	int descent;
	int height;
	XFontSet set;
	XFontStruct *xfont;
};

struct DC { /* draw context */
	int x, y, w, h;
	unsigned long bg;
	unsigned long fg;
	unsigned long border;
	Drawable drawable;
	Fnt font;
	GC gc;
};

struct Client {
	char name[256];
	char *tags[TLast];
	int proto;
	int x, y, w, h;
	int tx, ty, tw, th; /* title */
	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
	int grav;
	unsigned int border;
	long flags; 
	Bool isfloat;
	Bool ismax;
	Client *next;
	Client *prev;
	Window win;
	Window title;
};

extern char *tags[TLast], stext[1024];
extern int tsel, screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
extern void (*handler[LASTEvent])(XEvent *);
extern void (*arrange)(Arg *);
extern Atom wmatom[WMLast], netatom[NetLast];
extern Bool running, issel;
extern Client *clients, *sel;
extern Cursor cursor[CurLast];
extern DC dc;
extern Display *dpy;
extern Window root, barwin;

/* client.c */
extern void ban(Client *c);
extern void focus(Client *c);
extern void focusnext(Arg *arg);
extern void focusprev(Arg *arg);
extern Client *getclient(Window w);
extern Client *getctitle(Window w);
extern void gravitate(Client *c, Bool invert);
extern void higher(Client *c);
extern void killclient(Arg *arg);
extern void lower(Client *c);
extern void manage(Window w, XWindowAttributes *wa);
extern void resize(Client *c, Bool sizehints, Corner sticky);
extern void setsize(Client *c);
extern void settitle(Client *c);
extern void togglemax(Arg *arg);
extern void unmanage(Client *c);
extern void zoom(Arg *arg);

/* draw.c */
extern void drawall();
extern void drawstatus();
extern void drawtitle(Client *c);
extern unsigned long getcolor(const char *colstr);
extern void setfont(const char *fontstr);
extern unsigned int textw(char *text);

/* event.c */
extern void grabkeys();

/* main.c */
extern int getproto(Window w);
extern void quit(Arg *arg);
extern void sendevent(Window w, Atom a, long value);
extern int xerror(Display *dsply, XErrorEvent *ee);

/* tag.c */
extern void appendtag(Arg *arg);
extern void dofloat(Arg *arg);
extern void dotile(Arg *arg);
extern Client *getnext(Client *c);
extern Client *getprev(Client *c);
extern void replacetag(Arg *arg);
extern void settags(Client *c);
extern void togglemode(Arg *arg);
extern void view(Arg *arg);
extern void viewnext(Arg *arg);
extern void viewprev(Arg *arg);

/* util.c */
extern void *emallocz(unsigned int size);
extern void eprint(const char *errstr, ...);
extern void spawn(Arg *arg);
/span>transliterated from tb_utf8_char_to_unicode in https://github.com/nsf/termbox fn to-code-point in: code-point-utf8 -> _/eax: code-point { var g/ebx: int <- copy in # if single byte, just return it { compare g, 0xff break-if-> var result/eax: code-point <- copy g return result } # var len/edx: int <- utf8-length in # extract bits from first byte var b/eax: byte <- copy-byte g var result/edi: code-point <- copy b { compare len, 2 break-if-!= result <- and 0x1f } { compare len, 3 break-if-!= result <- and 0x0f } { compare len, 4 break-if-!= result <- and 0x07 } # extract bits from remaining bytes g <- shift-right 8 var i/ecx: int <- copy 1 { compare i, len break-if->= var b/eax: byte <- copy-byte g b <- and 0x3f result <- shift-left 6 result <- or b g <- shift-right 8 i <- increment loop } return result } # transliterated from tb_utf8_unicode_to_char in https://github.com/nsf/termbox # https://wiki.tcl-lang.org/page/UTF%2D8+bit+by+bit explains the algorithm fn to-utf8 in: code-point -> _/eax: code-point-utf8 { var c/eax: int <- copy in var num-trailers/ecx: int <- copy 0 var first/edx: int <- copy 0 $to-utf8:compute-length: { # single byte: just return it compare c, 0x7f { break-if-> var g/eax: code-point-utf8 <- copy c return g } # 2 bytes compare c, 0x7ff { break-if-> num-trailers <- copy 1 first <- copy 0xc0 break $to-utf8:compute-length } # 3 bytes compare c, 0xffff { break-if-> num-trailers <- copy 2 first <- copy 0xe0 break $to-utf8:compute-length } # 4 bytes compare c, 0x1fffff { break-if-> num-trailers <- copy 3 first <- copy 0xf0 break $to-utf8:compute-length } # more than 4 bytes: unsupported compare c, 0x1fffff { break-if-> abort "unsupported code point" return 0 } } # emit trailer bytes, 6 bits from 'in', first two bits '10' var result/edi: code-point-utf8 <- copy 0 { compare num-trailers, 0 break-if-<= var tmp/esi: int <- copy c tmp <- and 0x3f tmp <- or 0x80 result <- shift-left 8 result <- or tmp # update loop state c <- shift-right 6 num-trailers <- decrement loop } # emit engine result <- shift-left 8 result <- or c result <- or first # return result } # single-byte code point have identical code-point-utf8s fn test-to-utf8-single-byte { var in-int/ecx: int <- copy 0 { compare in-int, 0x7f break-if-> var in/eax: code-point <- copy in-int var out/eax: code-point-utf8 <- to-utf8 in var out-int/eax: int <- copy out check-ints-equal out-int, in-int, "F - test-to-utf8-single-byte" in-int <- increment loop } } # byte | byte | byte | byte # smallest 2-byte utf-8 fn test-to-utf8-two-bytes-min { var in/eax: code-point <- copy 0x80 # 10 00-0000 var out/eax: code-point-utf8 <- to-utf8 in var out-int/eax: int <- copy out check-ints-equal out-int, 0x80c2, "F - to-utf8/2a" # 110 0-0010 10 00-0000 } # largest 2-byte utf-8 fn test-to-utf8-two-bytes-max { var in/eax: code-point <- copy 0x7ff # 1-1111 11-1111 var out/eax: code-point-utf8 <- to-utf8 in var out-int/eax: int <- copy out check-ints-equal out-int, 0xbfdf, "F - to-utf8/2b" # 110 1-1111 10 11-1111 } # smallest 3-byte utf-8 fn test-to-utf8-three-bytes-min { var in/eax: code-point <- copy 0x800 # 10-0000 00-0000 var out/eax: code-point-utf8 <- to-utf8 in var out-int/eax: int <- copy out check-ints-equal out-int, 0x80a0e0, "F - to-utf8/3a" # 1110 0000 10 10-0000 10 00-0000 } # largest 3-byte utf-8 fn test-to-utf8-three-bytes-max { var in/eax: code-point <- copy 0xffff # 1111 11-1111 11-1111 var out/eax: code-point-utf8 <- to-utf8 in var out-int/eax: int <- copy out check-ints-equal out-int, 0xbfbfef, "F - to-utf8/3b" # 1110 1111 10 11-1111 10 11-1111 } # smallest 4-byte utf-8 fn test-to-utf8-four-bytes-min { var in/eax: code-point <- copy 0x10000 # 1-0000 00-0000 00-0000 var out/eax: code-point-utf8 <- to-utf8 in var out-int/eax: int <- copy out check-ints-equal out-int, 0x808090f0, "F - to-utf8/4a" # 1111-0 000 10 01-0000 10 00-0000 10 00-0000 } # largest 4-byte utf-8 fn test-to-utf8-four-bytes-max { var in/eax: code-point <- copy 0x1fffff # 111 11-1111 11-1111 11-1111 var out/eax: code-point-utf8 <- to-utf8 in var out-int/eax: int <- copy out check-ints-equal out-int, 0xbfbfbff7, "F - to-utf8/4b" # 1111-0 111 10 11-1111 10 11-1111 10 11-1111 } # read the next code-point-utf8 from a stream of bytes fn read-code-point-utf8 in: (addr stream byte) -> _/eax: code-point-utf8 { # if at eof, return EOF { var eof?/eax: boolean <- stream-empty? in compare eof?, 0/false break-if-= return 0xffffffff } var c/eax: byte <- read-byte in var num-trailers/ecx: int <- copy 0 $read-code-point-utf8:compute-length: { # single byte: just return it compare c, 0xc0 { break-if->= var g/eax: code-point-utf8 <- copy c return g } compare c, 0xfe { break-if-< var g/eax: code-point-utf8 <- copy c return g } # 2 bytes compare c, 0xe0 { break-if->= num-trailers <- copy 1 break $read-code-point-utf8:compute-length } # 3 bytes compare c, 0xf0 { break-if->= num-trailers <- copy 2 break $read-code-point-utf8:compute-length } # 4 bytes compare c, 0xf8 { break-if->= num-trailers <- copy 3 break $read-code-point-utf8:compute-length } abort "utf-8 encodings larger than 4 bytes are not yet supported" return 0 } # prepend trailer bytes var result/edi: code-point-utf8 <- copy c var num-byte-shifts/edx: int <- copy 1 { compare num-trailers, 0 break-if-<= var tmp/eax: byte <- read-byte in var tmp2/eax: int <- copy tmp tmp2 <- shift-left-bytes tmp2, num-byte-shifts result <- or tmp2 # update loop state num-byte-shifts <- increment num-trailers <- decrement loop } return result } fn test-read-code-point-utf8 { var s: (stream byte 0x30) var s2/ecx: (addr stream byte) <- address s write s2, "aΒc世d界e" var c/eax: code-point-utf8 <- read-code-point-utf8 s2 var n/eax: int <- copy c check-ints-equal n, 0x61, "F - test code-point-utf8/0" var c/eax: code-point-utf8 <- read-code-point-utf8 s2 var n/eax: int <- copy c check-ints-equal n, 0x92ce/greek-capital-letter-beta, "F - test code-point-utf8/1" var c/eax: code-point-utf8 <- read-code-point-utf8 s2 var n/eax: int <- copy c check-ints-equal n, 0x63, "F - test code-point-utf8/2" var c/eax: code-point-utf8 <- read-code-point-utf8 s2 var n/eax: int <- copy c check-ints-equal n, 0x96b8e4, "F - test code-point-utf8/3" var c/eax: code-point-utf8 <- read-code-point-utf8 s2 var n/eax: int <- copy c check-ints-equal n, 0x64, "F - test code-point-utf8/4" var c/eax: code-point-utf8 <- read-code-point-utf8 s2 var n/eax: int <- copy c check-ints-equal n, 0x8c95e7, "F - test code-point-utf8/5" var c/eax: code-point-utf8 <- read-code-point-utf8 s2 var n/eax: int <- copy c check-ints-equal n, 0x65, "F - test code-point-utf8/6" } fn utf8-length g: code-point-utf8 -> _/edx: int { { compare g, 0xff break-if-> return 1 } { compare g, 0xffff break-if-> return 2 } { compare g, 0xffffff break-if-> return 3 } return 4 } # needed because available primitives only shift by a literal/constant number of bits fn shift-left-bytes n: int, k: int -> _/eax: int { var i/ecx: int <- copy 0 var result/eax: int <- copy n { compare i, k break-if->= compare i, 4 # only 4 bytes in 32 bits break-if->= result <- shift-left 8 i <- increment loop } return result } fn test-shift-left-bytes-0 { var result/eax: int <- shift-left-bytes 1, 0 check-ints-equal result, 1, "F - shift-left-bytes 0" } fn test-shift-left-bytes-1 { var result/eax: int <- shift-left-bytes 1, 1 check-ints-equal result, 0x100, "F - shift-left-bytes 1" } fn test-shift-left-bytes-2 { var result/eax: int <- shift-left-bytes 1, 2 check-ints-equal result, 0x10000, "F - shift-left-bytes 2" } fn test-shift-left-bytes-3 { var result/eax: int <- shift-left-bytes 1, 3 check-ints-equal result, 0x1000000, "F - shift-left-bytes 3" } fn test-shift-left-bytes-4 { var result/eax: int <- shift-left-bytes 1, 4 check-ints-equal result, 0, "F - shift-left-bytes 4" } fn test-shift-left-bytes-5 { var result/eax: int <- shift-left-bytes 1, 5 check-ints-equal result, 0, "F - shift-left-bytes >4" } # write a code-point-utf8 to a stream of bytes # this is like write-to-stream, except we skip leading 0 bytes fn write-code-point-utf8 out: (addr stream byte), g: code-point-utf8 { $write-code-point-utf8:body: { var c/eax: int <- copy g append-byte out, c # first byte is always written c <- shift-right 8 compare c, 0 break-if-= $write-code-point-utf8:body append-byte out, c c <- shift-right 8 compare c, 0 break-if-= $write-code-point-utf8:body append-byte out, c c <- shift-right 8 compare c, 0 break-if-= $write-code-point-utf8:body append-byte out, c } }