Alopex

Check-in [835dfddbe2]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:converted shorthand letters to human readable "script" language
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | master
Files: files | file ages | folders
SHA3-256:835dfddbe2e7698bde494ac09a6a3d6dd2fd4a76502505717ad00d0573a09a65
User & Date: jesse@mccluresk9.com 2014-03-20 20:37:59
Context
2014-03-20
20:49
fixed window marking check-in: 6dda45587d user: jesse@mccluresk9.com tags: trunk, master
20:37
converted shorthand letters to human readable "script" language check-in: 835dfddbe2 user: jesse@mccluresk9.com tags: trunk, master
18:07
stack bar windows properly check-in: 2fe58d9125 user: jesse@mccluresk9.com tags: trunk, master
Changes

Changes to doc/alopex-1.tex.

50
51
52
53
54
55
56
57
58
59
60
61















62
63
64
65
66
67
68
segments.  The first two segments are always displayed in the first
container's bar: the first before the tag indicators, the second
immediately after the tag indicators.  The third segment is displayed at
the right side of the second container's bar (or the right of the first
container if there is only one visible).  The fourth segment is
displayed at the right side of the last visible container.

Plain text is printed as is into the above-specified status bar region.
Text within curly-braces is interpreted as a special indicator.  These
indicators can specify a foreground color, set a font, display an icon
or paint the foreground color with an icon mask.  Further documentation
and examples can be found on the github wiki.
















\section{Author}
Copyright \copyright 2012-2014 Jesse McClure \\
License GPLv3: GNU GPL version 3 \URL{http://gnu.org/licenses/gpl.html} \\
This is free software: you are free to change and redistribute it. \\
There is NO WARRANTY, to the extent permitted by law.








|
|
|
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
segments.  The first two segments are always displayed in the first
container's bar: the first before the tag indicators, the second
immediately after the tag indicators.  The third segment is displayed at
the right side of the second container's bar (or the right of the first
container if there is only one visible).  The fourth segment is
displayed at the right side of the last visible container.

Plain text is printed as-is into the above-specified status bar region.
Text within curly-braces is interpreted as a special command.  These
commands can specify a foreground color, set a font, display an icon
or paint the foreground color with an icon mask.


\subsection{Status Commands}

\begin{description}
\item[\Opt{R G B A}]
	Set color with Red Green Blue and Alpha values specified as floating
	point numbers from 0 to 1
\item[\OptArg{i}{#}]
	Draw icon number # in full color
\item[\OptArg{I}{#}]
	Use icon number # as mask for the currently selected color
\item[\Opt{f}]
	Select default font
\item[\Opt{F}]
	Select bold font

\section{Author}
Copyright \copyright 2012-2014 Jesse McClure \\
License GPLv3: GNU GPL version 3 \URL{http://gnu.org/licenses/gpl.html} \\
This is free software: you are free to change and redistribute it. \\
There is NO WARRANTY, to the extent permitted by law.

Changes to doc/alopex.1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
68
69
70
71
72
73
74
75
76
77
78
79


















80
81
82
83
84
85
86
'\" t
.\" Manual page created with latex2man on Thu Feb 13 14:02:38 EST 2014
.\" NOTE: This file is generated, DO NOT EDIT.
.de Vb
.ft CW
.nf
..
.de Ve
.ft R

.fi
..
.TH "ALOPEX" "1" "13 February 2014" "window manager " "window manager "
.SH NAME

.PP
Alopex
\- A Tabbed, Tiling Window Manager with Fur 
.PP
.SH SYNOPSIS
................................................................................
segments. The first two segments are always displayed in the first 
container\&'s bar: the first before the tag indicators, the second 
immediately after the tag indicators. The third segment is displayed at 
the right side of the second container\&'s bar (or the right of the first 
container if there is only one visible). The fourth segment is 
displayed at the right side of the last visible container. 
.PP
Plain text is printed as is into the above\-specified status bar region. 
Text within curly\-braces is interpreted as a special indicator. These 
indicators can specify a foreground color, set a font, display an icon 
or paint the foreground color with an icon mask. Further documentation 
and examples can be found on the github wiki. 


















.PP
.SH AUTHOR

Copyright (C)2012\-2014 Jesse McClure 
.br
License GPLv3: GNU GPL version 3 \fBhttp://gnu.org/licenses/gpl.html\fP
.br

|










|







 







|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
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
'\" t
.\" Manual page created with latex2man on Thu Mar 20 14:23:46 EDT 2014
.\" NOTE: This file is generated, DO NOT EDIT.
.de Vb
.ft CW
.nf
..
.de Ve
.ft R

.fi
..
.TH "ALOPEX" "1" "20 March 2014" "window manager " "window manager "
.SH NAME

.PP
Alopex
\- A Tabbed, Tiling Window Manager with Fur 
.PP
.SH SYNOPSIS
................................................................................
segments. The first two segments are always displayed in the first 
container\&'s bar: the first before the tag indicators, the second 
immediately after the tag indicators. The third segment is displayed at 
the right side of the second container\&'s bar (or the right of the first 
container if there is only one visible). The fourth segment is 
displayed at the right side of the last visible container. 
.PP
Plain text is printed as\-is into the above\-specified status bar region. 
Text within curly\-braces is interpreted as a special command. These 
commands can specify a foreground color, set a font, display an icon 
or paint the foreground color with an icon mask. 
.PP
.SS STATUS COMMANDS
.PP
.TP
\fBR G B A\fP
 Set color with Red Green Blue and Alpha values specified as floating 
point numbers from 0 to 1 
.TP
\fBi\fP\fI#\fP
 Draw icon number # in full color 
.TP
\fBI\fP\fI#\fP
 Use icon number # as mask for the currently selected color 
.TP
\fBf\fP
 Select default font 
.TP
\fBF\fP
 Select bold font 
.PP
.SH AUTHOR

Copyright (C)2012\-2014 Jesse McClure 
.br
License GPLv3: GNU GPL version 3 \fBhttp://gnu.org/licenses/gpl.html\fP
.br

Changes to share/config.

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
134
135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
*.Rule.01.Class:			Float
*.Rule.01.Flags:			float
*.Rule.02.Class:			Firefox
*.Rule.02.Tags:			2

!----- Binds -----!
! Each key can have up to five bindings using different modifiers
! TODO allow for no modifiers? (for media keys)
! Each key is numbered from 00-99
! See "Commands" description in a man page or github wiki for
!  a description of the command language used for bindings

! Modifier definitions
*.Bind.Mod.First:			Super
*.Bind.Mod.Second:		Super Alt
*.Bind.Mod.Third:			Super Shift
*.Bind.Mod.Fourth:		Super Control
*.Bind.Mod.Fifth:			Alt
! General bindings
*.Bind.00.Key:			q
*.Bind.00.Third:		Q
*.Bind.01.Key:			Return
*.Bind.01.First:		!urxvt
*.Bind.02.Key:			w
*.Bind.02.First:		!firefox
*.Bind.03.Key:			F4
*.Bind.03.Fifth:		wq
! Tiling mode
*.Bind.50.Key:			space
*.Bind.50.First:		l
*.Bind.50.Second:		lx
*.Bind.50.Third:		lm
! Floating / Fullscren:
*.Bind.51.Key:			f
*.Bind.51.First:		F
*.Bind.51.Third:		wF
! Focus / Move



*.Bind.60.Key:			Tab
*.Bind.60.First:		fp
*.Bind.60.Third:		ff
*.Bind.60.Fifth:		v
*.Bind.61.Key:			h
*.Bind.61.First:		fh
*.Bind.61.Second:		mh
*.Bind.62.Key:			j
*.Bind.62.First:		fj
*.Bind.62.Second:		mj
*.Bind.63.Key:			k
*.Bind.63.First:		fk
*.Bind.63.Second:		mk
*.Bind.64.Key:			l
*.Bind.64.First:		fl
*.Bind.64.Second:		ml
! Modify Settings

*.Bind.70.Key:			x
*.Bind.70.First:		bx
*.Bind.70.Second:		bS
*.Bind.70.Third:		bX
*.Bind.70.Fourth:		bH

*.Bind.71.Key:			i
*.Bind.71.First:		si
*.Bind.71.Second:		gi
*.Bind.71.Third:		ni
*.Bind.72.Key:			d
*.Bind.72.First:		sd
*.Bind.72.Second:		gd
*.Bind.72.Third:		nd
*.Bind.73.Key:			r
*.Bind.73.First:		sr
*.Bind.73.Second:		gr
*.Bind.73.Third:		nr
! Tag bindings

*.Bind.81.Key:			1
*.Bind.81.First:		tx1
*.Bind.81.Second:		tt1
*.Bind.81.Third:		wtx1
*.Bind.81.Fourth:		wtt1
*.Bind.82.Key:			2
*.Bind.82.First:		tx2
*.Bind.82.Second:		tt2
*.Bind.82.Third:		wtx2
*.Bind.82.Fourth:		wtt2
*.Bind.83.Key:			3
*.Bind.83.First:		tx3
*.Bind.83.Second:		tt3
*.Bind.83.Third:		wtx3
*.Bind.83.Fourth:		wtt3
*.Bind.84.Key:			4
*.Bind.84.First:		tx4
*.Bind.84.Second:		tt4
*.Bind.84.Third:		wtx4
*.Bind.84.Fourth:		wtt4
! Window marks:
*.Bind.92.Key:			F2
*.Bind.92.First:		w2f
*.Bind.92.Second:		z2
*.Bind.93.Key:			F3
*.Bind.93.First:		w3f
*.Bind.93.Second:		z3

!! vim: ft=xdefaults







<



>








|

|

|

|


|
|
|


|
|

>
>
>

|
|
|

|
|

|
|

|
|

|
|

>

|
|
|
|
>

|
|
|

|
|
|

|
|
|

>

|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|





|



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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
*.Rule.01.Class:			Float
*.Rule.01.Flags:			float
*.Rule.02.Class:			Firefox
*.Rule.02.Tags:			2

!----- Binds -----!
! Each key can have up to five bindings using different modifiers

! Each key is numbered from 00-99
! See "Commands" description in a man page or github wiki for
!  a description of the command language used for bindings
!  NOTE: the wiki is currently outdated
! Modifier definitions
*.Bind.Mod.First:			Super
*.Bind.Mod.Second:		Super Alt
*.Bind.Mod.Third:			Super Shift
*.Bind.Mod.Fourth:		Super Control
*.Bind.Mod.Fifth:			Alt
! General bindings
*.Bind.00.Key:			q
*.Bind.00.Third:		quit
*.Bind.01.Key:			Return
*.Bind.01.First:		exec urxvt
*.Bind.02.Key:			w
*.Bind.02.First:		exec firefox
*.Bind.03.Key:			F4
*.Bind.03.Fifth:		kill
! Tiling mode
*.Bind.50.Key:			space
*.Bind.50.First:		layout
*.Bind.50.Second:		layout default
*.Bind.50.Third:		layout monocle
! Floating / Fullscren:
*.Bind.51.Key:			f
*.Bind.51.First:		float
*.Bind.51.Third:		fullscreen
! Focus / Move
! focus (top|bottom|up|down)
! move (top|bottom|up|down)
! win # move (above|below)
*.Bind.60.Key:			Tab
*.Bind.60.First:		focus previous
*.Bind.60.Third:		focus floater
*.Bind.60.Fifth:		view
*.Bind.61.Key:			h
*.Bind.61.First:		focus top
*.Bind.61.Third:		move top
*.Bind.62.Key:			j
*.Bind.62.First:		focus down
*.Bind.62.Third:		move down
*.Bind.63.Key:			k
*.Bind.63.First:		focus up
*.Bind.63.Third:		move up
*.Bind.64.Key:			l
*.Bind.64.First:		focus bottom
*.Bind.64.Third:		move bottom
! Modify Settings
! bar (top|bottom|show|hide|toggle) [all]
*.Bind.70.Key:			x
*.Bind.70.First:		bar toggle
*.Bind.70.Second:		bar show all
*.Bind.70.Third:		bar toggle all
*.Bind.70.Fourth:		bar hide all
! (split|gap|number) (increase|decrease|set|reset) [#]
*.Bind.71.Key:			i
*.Bind.71.First:		split increase 1
*.Bind.71.Second:		gap increase 1
*.Bind.71.Third:		number increase 1
*.Bind.72.Key:			d
*.Bind.72.First:		split decrease 1
*.Bind.72.Second:		gap decrease 1
*.Bind.72.Third:		number decrease 1
*.Bind.73.Key:			r
*.Bind.73.First:		split reset
*.Bind.73.Second:		gap reset
*.Bind.73.Third:		number reset
! Tag bindings
! [win [#]] tag (toggle|set|add|remove) #
*.Bind.81.Key:			1
*.Bind.81.First:		tag set 1
*.Bind.81.Second:		tag toggle 1
*.Bind.81.Third:		win tag set 1
*.Bind.81.Fourth:		win tag toggle 1
*.Bind.82.Key:			2
*.Bind.82.First:		tag set 2
*.Bind.82.Second:		tag toggle 2
*.Bind.82.Third:		win tag set 2
*.Bind.82.Fourth:		win tag toggle 2
*.Bind.83.Key:			3
*.Bind.83.First:		tag set 3
*.Bind.83.Second:		tag toggle 3
*.Bind.83.Third:		win tag set 3
*.Bind.83.Fourth:		win tag toggle 3
*.Bind.84.Key:			4
*.Bind.84.First:		tag set 4
*.Bind.84.Second:		tag toggle 4
*.Bind.84.Third:		win tag set 4
*.Bind.84.Fourth:		win tag toggle 4
! Window marks:
*.Bind.92.Key:			F2
*.Bind.92.First:		w2f
*.Bind.92.Second:		z2
*.Bind.93.Key:			F3
*.Bind.93.First:		win 3f
*.Bind.93.Second:		z3

!! vim: ft=xdefaults

Changes to src/actions.c.

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
134
135
136
137
138
139
140




141
142

143
144

145
146

147
148

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167



168
169
170
171

172
173
174
175
176
177
178
179
180
181
182
183


184
185
186
187
188
189
190

191
192
193
194
195
196


197
198
199
200

201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218

219
220
221

222
223


224
225
226
227
228
229
230


231
232
233
234
235
236


237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302

303











304
305
306
307
308

309






310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325















326
327
328
329
330
331


332
333
334
335
#include "actions.h"

extern Bool tile_check(Monitor *, Client *);
extern int send_message(Client *, int, int);


int command(const char *cmd) {
	if (cmd[0] == '!') return spawn(cmd+1);
	const char *wrd;
	for (wrd = cmd; wrd; wrd = strchr(wrd,' ')) {
		if (wrd[0] == ' ') word((++wrd));

		else word(wrd);
	}

	return 0;
}

int float_full(Client *t) {
	if (t) {




















		if (t->flags & WIN_FLOAT) t->flags &= ~WIN_FULL;
		else t->flags |= WIN_FLOAT;
	}


	else if ( (t=winmarks[1]) ) {
		if (t->flags & WIN_FULL_TEST) t->flags &= ~WIN_FULL;
		else t->flags |= WIN_FULL;
	}
	else {
		return 1;
	}
	return 0;
}

int focus(Client *t, const char *s) {
	if (t) {
		winmarks[0] = winmarks[1];
		winmarks[1] = t;
		return 0;
	}
	Container *C;
	Client *c, *a, *b;
	if (!(c=winmarks[1])) return 1;
	switch (*s) {
		case 'f':

			for (a = winmarks[1]->next; a; a = a->next)
				if (a->flags & WIN_FLOAT) break;
			if (!a) for (a = clients; a; a = a->next)
				if (a->flags & WIN_FLOAT) break;
			if (!a) return 1;
			winmarks[0] = winmarks[1];
			winmarks[1] = a;
			break;
		case 'h':


			for (C = m->container; C && C->next; C = C->next) {
				if (C->next == m->focus) {
					winmarks[0] = winmarks[1];
					winmarks[1] = C->top;
				}
			}
			break;
		case 'j':


			for (a = c->next; a; a = a->next)
				if (tile_check(m, a)) break;
			if (a) {
				winmarks[0] = winmarks[1];
				winmarks[1] = a;
			}
			break;
		case 'k':


			for (a = clients; a && a != c; a = a->next)
				if (tile_check(m, a)) b = a;
			if (b) {
				winmarks[0] = winmarks[1];
				winmarks[1] = b;
			}
			break;
		case 'l':


			if (m->focus->next && m->focus->next->top) {
				winmarks[0] = winmarks[1];
				winmarks[1] = m->focus->next->top;
			}
			break;
		case 'p':


			if (winmarks[0] && (winmarks[0]->tags & m->tags)) {
				/* focus previous */
				a = winmarks[0];
				winmarks[0] = winmarks[1];
				winmarks[1] = a;
			}
			else { /* focus first container, or next container ... */
				C = m->container;
				if (C->top == winmarks[1]) C = C->next;
				if (C->top)
					a = C->top;
				else /* ... only one container -> focus another client */
					for (a = clients; a; a = a->next)
						if (a != winmarks[1] && tile_check(m, a)) break;
				if (a) {
					winmarks[0] = winmarks[1];
					winmarks[1] = a;
				}
			}
			break;
		default: return 1;
	}
	return 0;
}

int killclient(Client *c) {
	if (!c) return 1;
	return send_message(c, WM_PROTOCOLS, WM_DELETE_WINDOW);
}

int layout(const char *s) {
	switch (s[0]) {
		case 'r': m->mode = RSTACK; break;
		case 'b': m->mode = BSTACK; break;
		case 'm': m->mode = MONOCLE; break;
		case 'x': m->mode = conf.mode; break;

		default: if ( (++m->mode) == LAST_MODE ) m->mode = 0;




	}
}

int mark_client(Client *t, const char *s) {
	int n = atoi(s);
	if (n > 1 && n < 10) winmarks[n] = t;
	else if (n == 1) { winmarks[0] = winmarks[1]; winmarks[1] = t; }
	return 0;
}

int mod_bar(const char *s) {


	Container *C;
	Bar *b;
	if (!m->focus || !(b=m->focus->bar)) return 1;
	switch (s[0]) {
		case 's': b->opts &= ~BAR_HIDE; break;
		case 'h': b->opts |= BAR_HIDE; break;
		case 'x': b->opts ^= BAR_HIDE; break;
		case 't': b->opts &= ~BAR_BOTTOM; break;
		case 'b': b->opts |= BAR_BOTTOM; break;




		case 'S': for (C = m->container; C; C = C->next)
			C->bar->opts &= ~BAR_HIDE; break;

		case 'H': for (C = m->container; C; C = C->next)
			C->bar->opts |= BAR_HIDE; break;

		case 'X': for (C = m->container; C; C = C->next)
			C->bar->opts ^= BAR_HIDE; break;

		case 'T': for (C = m->container; C; C = C->next)
			C->bar->opts &= ~BAR_BOTTOM; break;

		case 'B': for (C = m->container; C; C = C->next)
			C->bar->opts |= BAR_BOTTOM; break;
	}
}

int mod_container(const char *s) {
fprintf(stderr,"MOD CONTAINER %s\n",s);
	if (!m->focus) return 1;
	int n, *t, r;
	switch (s[0]) {
		case 'n': t = &m->focus->n; r = m->focus->nn; break;
		case 's': t = &m->split; r = conf.split; break;
		case 'g': t = &m->gap; r = conf.gap; break;
	}
	switch (s[1]) {
		case 'i': *t += 1; break;
		case 'd': *t -= 1; break;
		case 'r': *t = r; break;
		default: n = atoi(&s[1]); *t = n; break;



	}
}

int monitor(const char *s) {

	int n1, n2, n3, n4;
	if (*s == 'm') { /* margins */
		if (s[1] == 'r')
			m->margin = conf.margin;
		else {
			sscanf(s,"m%d,%d,%d,%d", &n1, &n2, &n3, &n4);
			m->margin.top = n1;
			m->margin.bottom = n2;
			m->margin.left = n3;
			m->margin.right = n4;
		}
	}


	else if (*s == 's') { /* swap tags */
		sscanf(s,"s%d,%d", &n1, &n2);
		Monitor *M, *a = NULL, *b = NULL;
		for (M = mons, n3 = 1; M; n3++, M = M->next) {
			if (n1 == n3) a = M;
			else if (n2 == n3) b = M;
		}

		if (a && b) {
			n4 = a->tags;
			a->tags = b->tags;
			b->tags = n4;
		}
	}


	else if (*s == 'c') { /* cycle through monitors */
		m = m->next;
		if (!m) m = mons;
	}

	else { /* focus another monitor */
		n1 = atoi(s);
		Monitor *M;
		for (M = mons; n1 > 0 && M; n1--, M = M->next) m = M;
	}

	return 0;
}

int move(Client *t, const char *s) {
	Client *c, *a, *b;
	if (!(c=winmarks[1])) return 1;
	if (t) { /* move focused relative to t */
		if (!(m->focus && m->focus->top)) return 1;
		if (c == t) return 2;
		switch (s[0]) {
			case 'a': pull_client(c); push_client(c, t); break;
			case 'b': pull_client(c); push_client(c, t->next); break;
		}

	}
	else { /* move focused in direction */
		switch (s[0]) {

			case 'h': pull_client(c); push_client(c, clients); break;
			case 'j':


				for (a = c->next; a; a = a->next)
					if (tile_check(m, a)) break;
				if (a) for (a = a->next; a; a = a->next)
					if (tile_check(m, a)) break;
				pull_client(c); push_client(c, a);
				break;
			case 'k':


				for (a = clients; a && a != c; a = a->next)
					if (tile_check(m, a)) b = a;
				if (b) { pull_client(c); push_client(c, b); }
				break;
			case 'l': pull_client(c); push_client(c, NULL); break;
		}


	}
}

int pull_client(Client *c) {
	Client *cur, *pre = NULL;
	for (cur = clients; cur != c; cur = cur->next) pre = cur;
	if (pre) pre->next = cur->next;
	else clients = cur->next;
	cur->next = NULL;
	return 0;
}

int push_client(Client *insert, Client *before) {
	Client *cur, *pre = NULL;
	for (cur = clients; cur != before; cur = cur->next) pre = cur;
	if (pre) pre->next = insert;
	else clients = insert;
	insert->next = cur;
	return 0;
}


int spawn(const char *cmd) {
	if (cmd[0] == '\0') return 0;
	if (!fork()) {
		setsid();
		close(ConnectionNumber(dpy));
		if (conf.stat) fclose(conf.stat);
		if (conf.statfd) close(conf.statfd);
		char **arg = NULL, *tok = NULL, *tmp = strdup(cmd);
		tok = strtok(tmp," ");
		int i;
		for (i = 0; tok; i++) {
			arg = realloc(arg, (i+1) * sizeof(char *));
			arg[i] = strdup(tok);
			tok = strtok(NULL," ");
		}
		free(tmp);
		arg = realloc(arg, (i+1) * sizeof(char *));
		arg[i] = NULL;
		execvp(arg[0], (char * const *) arg);
	}
	return 0;
}

int tag(Client *t, const char *s) {

	int tag = atoi(s+1);
	if (!tag || tag > 15) return 1;
	tag = (1<<(tag-1));
	int *n;
	if (!t) n = &m->tags;
	else n = &t->tags;
	switch (*s) {
		case 'x': *n = (*n & 0xFFFF0000) | tag; break;
		case 't': *n ^= tag; break;
		case 'a': *n |= tag; break;
		case 'r': *n &= ~tag; break;
		default: return 1;
	}
}


/*
a c e  hijk   opqr  u wxy
ABCDE GHIJKLMNOP RSTUVWXYZ
*/
int word(const char *word) {

	const char *s = word;











	/* get target */
	Client *t = winmarks[1], *wt = NULL;
	int n;
	if (s[0] == 'w') {
		s++;

		if ( !(n=atoi(s)) ) n = 1;






		if (n > 0 && n < 10) wt = winmarks[n];
		if (!wt) return 1;
		while (*s >= '0' && *s <= '9') s++;
	}
	/* process command */
	switch (s[0]) {
		case 'b': mod_bar(&s[1]); break;
		case 'd': monitor(&s[1]); break;
		case 'f': focus(wt, &s[1]); break;
		case 'F': float_full(wt); break;
		case 'g': case 'n': case 's': mod_container(s);  break;
		case 'l': layout(&s[1]); break;
		case 'm': move(wt, &s[1]); break;
		case 'q': killclient(t); break;
		case 'Q': running = False; break;
		case 't': tag(wt, &s[1]); break;















		case 'v': n = (m->tags<<16) & 0xFFFF0000;
			n |= (m->tags>>16) & 0xFFFF;
			m->tags = n;
			break;
		case 'z': mark_client(t, &s[1]); break;
	}


	tile();
	return 0;
}








|
|
|
|
>
|
<
>



<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
|
|
|
|
<
<
|
<
<
<
|



|



|
<
<
>
|
|
|
|
|
|
|
<
<
>
>
|
|
|
|
|
|
<
<
>
>
|
|
|
|
|
|
<
<
>
>
|
|
|
|
|
|
<
<
>
>
|
|
|
|
<
<
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<

<


|
|
|


<
<
<
<
<
<
>
|
>
>
>
>
|
|
<
|
|


<


<
>
>


|
<
<
<
<
<
<
>
>
>
>
|
|
>
|
|
>
|
|
>
|
|
>
|
|

<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
>
>
>



<
>
|
|
|
|
|
|
|
|
|
|
<
<
>
>
|
|
|
|
|
|
<
>
|
|
|
|
<
<
>
>
|
|
|
<
>
|
|
|
|
<
>
|


|

|
|
|
<
|



>

|
<
>
|
<
>
>
|
|
|
|
|
<
<
>
>
|
|
|
<
<
|
>
>



|





<


|





<


>
|
<





<
<
<
<
<
<
<
<
<
<
<


<


|
>
|
|




|
|



<



<
<
<
<
<
|
>
|
>
>
>
>
>
>
>
>
>
>
>


<
<
<
>
|
>
>
>
>
>
>

|
<


<
<
<
<
<
<
<
<
<
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
<
<

>
>

<


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
134

135
136
137
138

139
140

141
142
143
144
145






146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164













165
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181
182
183
184


185
186
187
188
189
190
191
192

193
194
195
196
197


198
199
200
201
202

203
204
205
206
207

208
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223

224
225

226
227
228
229
230
231
232


233
234
235
236
237


238
239
240
241
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257

258
259
260
261

262
263
264
265
266











267
268

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283

284
285
286





287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302



303
304
305
306
307
308
309
310
311
312

313
314










315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333


334
335
336
337

338
339
#include "actions.h"

extern Bool tile_check(Monitor *, Client *);
extern int send_message(Client *, int, int);


int command(const char *cmd) {
	//if (cmd[0] == '!') return spawn(cmd+1);
	char *tok, *sptr, *str;
	str = strdup(cmd);
	for (tok = strtok_r(str, ";", &sptr); tok;
			tok = strtok_r(NULL, ";", &sptr))
		word(tok);

	free(str);
	return 0;
}


void conftile(Client *t, const char **arg) {
	if (!m->focus || !arg[0]) return;
	int n, *opt = NULL, r;
	switch (arg[0][0]) {
		case 'n': opt = &m->focus->n; r = m->focus->nn; break;
		case 's': opt = &m->split; r = conf.split; break;
		case 'g': opt = &m->gap; r = conf.gap; break;
	}
	if (!opt || !arg[1]) return;
	if (arg[2]) n = atoi(arg[2]);
	else n = 1;
	switch (arg[1][0]) {
		case 'i': *opt += n; break;
		case 'd': *opt -= n; break;
		case 'r': *opt = r; break;
		case 's': *opt = n; break;
	}
}

void floater(Client *t, const char **arg) {
	if (!t && !(t=winmarks[1])) return;
	if (t->flags & WIN_FLOAT) t->flags &= ~WIN_FULL;
	else t->flags |= WIN_FLOAT;
}

void fullscreen(Client *t, const char **arg) {
	if (!t && !(t=winmarks[1])) return;
	if (t->flags & WIN_FULL_TEST) t->flags &= ~WIN_FULL;
	else t->flags |= WIN_FULL;
}






void focus(Client *t, const char **arg) {
	if (t) {
		winmarks[0] = winmarks[1];
		winmarks[1] = t;
		return;
	}
	Container *C;
	Client *c, *a, *b;
	if (!(c=winmarks[1])) return;


	if (strncasecmp(arg[0],"flo",3)==0) { /* focus floating */
		for (a = winmarks[1]->next; a; a = a->next)
			if (a->flags & WIN_FLOAT) break;
		if (!a) for (a = clients; a; a = a->next)
			if (a->flags & WIN_FLOAT) break;
		if (!a) return;
		winmarks[0] = winmarks[1];
		winmarks[1] = a;


	}
	else if (strncasecmp(arg[0],"top",3)==0) { /* focus top */
		for (C = m->container; C && C->next; C = C->next) {
			if (C->next == m->focus) {
				winmarks[0] = winmarks[1];
				winmarks[1] = C->top;
			}
		}


	}
	else if (strncasecmp(arg[0],"dow",3)==0) { /* focus down */
		for (a = c->next; a; a = a->next)
			if (tile_check(m, a)) break;
		if (a) {
			winmarks[0] = winmarks[1];
			winmarks[1] = a;
		}


	}
	else if (strncasecmp(arg[0],"up",2)==0) { /* focus up */
		for (a = clients; a && a != c; a = a->next)
			if (tile_check(m, a)) b = a;
		if (b) {
			winmarks[0] = winmarks[1];
			winmarks[1] = b;
		}


	}
	else if (strncasecmp(arg[0],"bot",3)==0) { /* focus bottom */
		if (m->focus->next && m->focus->next->top) {
			winmarks[0] = winmarks[1];
			winmarks[1] = m->focus->next->top;
		}


	}
	else if (strncasecmp(arg[0],"pre",3)==0) { /* focus previous */
		if (winmarks[0] && (winmarks[0]->tags & m->tags)) {
			/* focus previous */
			a = winmarks[0];
			winmarks[0] = winmarks[1];
			winmarks[1] = a;
		}
		else { /* focus first container, or next container ... */
			C = m->container;
			if (C->top == winmarks[1]) C = C->next;
			if (C->top)
				a = C->top;
			else /* ... only one container -> focus another client */
				for (a = clients; a; a = a->next)
					if (a != winmarks[1] && tile_check(m, a)) break;
			if (a) {
				winmarks[0] = winmarks[1];
				winmarks[1] = a;
			}
		}


	}

}

void killclient(Client *c, const char **arg) {
	if (!c) return;
	send_message(c, WM_PROTOCOLS, WM_DELETE_WINDOW);
}







void layout(Client *c, const char **arg) {
	if (!arg[0]) { if ( (++m->mode) == LAST_MODE ) m->mode = 0; }
	else if (strncasecmp(arg[0],"rst",3)==0) m->mode = RSTACK;
	else if (strncasecmp(arg[0],"bst",3)==0) m->mode = BSTACK;
	else if (strncasecmp(arg[0],"mon",3)==0) m->mode = MONOCLE;
	else if (strncasecmp(arg[0],"def",3)==0) m->mode = conf.mode;
}


void mark_client(Client *t, const char **arg) {
	int n = atoi(arg[0]);
	if (n > 1 && n < 10) winmarks[n] = t;
	else if (n == 1) { winmarks[0] = winmarks[1]; winmarks[1] = t; }

}


void mod_bar(Client *t, const char **arg) {
	if (!arg[0]) return;
	Container *C;
	Bar *b;
	if (!m->focus || !(b=m->focus->bar)) return;






	int all = 0;
	if (arg[1] && strncasecmp(arg[1],"all",3)==0) all = 1;
	if (all) {
		if (strncasecmp(arg[0],"sho",3)==0)
			for (C = m->container; C; C = C->next)
				C->bar->opts &= ~BAR_HIDE;
		else if (strncasecmp(arg[0],"hid",3)==0)
			for (C = m->container; C; C = C->next)
				C->bar->opts |= BAR_HIDE;
		else if (strncasecmp(arg[0],"tog",3)==0)
			for (C = m->container; C; C = C->next)
				C->bar->opts ^= BAR_HIDE;
		else if (strncasecmp(arg[0],"top",3)==0)
			for (C = m->container; C; C = C->next)
				C->bar->opts &= ~BAR_BOTTOM;
		else if (strncasecmp(arg[0],"bot",3)==0)
			for (C = m->container; C; C = C->next)
				C->bar->opts |= BAR_BOTTOM;
	}













	else {
		if (strncasecmp(arg[0],"sho",3)==0) b->opts &= ~BAR_HIDE;
		else if (strncasecmp(arg[0],"hid",3)==0) b->opts |= BAR_HIDE;
		else if (strncasecmp(arg[0],"tog",3)==0) b->opts ^= BAR_HIDE;
		else if (strncasecmp(arg[0],"top",3)==0) b->opts &= ~BAR_BOTTOM;
		else if (strncasecmp(arg[0],"bot",3)==0) b->opts |= BAR_BOTTOM;
	}
}


void monitor(Client *t, const char **arg) {
//	int n1, n2, n3, n4;
//	if (*s == 'm') { /* margins */
//		if (s[1] == 'r')
//			m->margin = conf.margin;
//		else {
//			sscanf(s,"m%d,%d,%d,%d", &n1, &n2, &n3, &n4);
//			m->margin.top = n1;
//			m->margin.bottom = n2;
//			m->margin.left = n3;
//			m->margin.right = n4;


//		}
//	}
//	else if (*s == 's') { /* swap tags */
//		sscanf(s,"s%d,%d", &n1, &n2);
//		Monitor *M, *a = NULL, *b = NULL;
//		for (M = mons, n3 = 1; M; n3++, M = M->next) {
//			if (n1 == n3) a = M;
//			else if (n2 == n3) b = M;

//		}
//		if (a && b) {
//			n4 = a->tags;
//			a->tags = b->tags;
//			b->tags = n4;


//		}
//	}
//	else if (*s == 'c') { /* cycle through monitors */
//		m = m->next;
//		if (!m) m = mons;

//	}
//	else { /* focus another monitor */
//		n1 = atoi(s);
//		Monitor *M;
//		for (M = mons; n1 > 0 && M; n1--, M = M->next) m = M;

//	}
//	return 0;
}

void move(Client *t, const char **arg) {
	Client *c, *a, *b;
	if (!(c=winmarks[1]) || !arg || !arg[0]) return;
	if (t) { /* move focused window relative to t */
		if (!(m->focus && m->focus->top) || c == t) return;

		switch (arg[0][0]) {
			case 'a': pull_client(c); push_client(c, t); break;
			case 'b': pull_client(c); push_client(c, t->next); break;
		}
		return;
	}
	/* else move focused in direction */

	if (strncasecmp(arg[0],"top",3)==0) {
		pull_client(c); push_client(c, clients);

	}
	else if (strncasecmp(arg[0],"dow",3)==0) {
		for (a = c->next; a; a = a->next)
			if (tile_check(m, a)) break;
		if (a) for (a = a->next; a; a = a->next)
			if (tile_check(m, a)) break;
		pull_client(c); push_client(c, a);


	}
	else if (strncasecmp(arg[0],"up",3)==0) {
		for (a = clients; a && a != c; a = a->next)
			if (tile_check(m, a)) b = a;
		if (b) { pull_client(c); push_client(c, b); }


	}
	else if (strncasecmp(arg[0],"up",3)==0) {
		pull_client(c); push_client(c, NULL);
	}
}

void pull_client(Client *c) {
	Client *cur, *pre = NULL;
	for (cur = clients; cur != c; cur = cur->next) pre = cur;
	if (pre) pre->next = cur->next;
	else clients = cur->next;
	cur->next = NULL;

}

void push_client(Client *insert, Client *before) {
	Client *cur, *pre = NULL;
	for (cur = clients; cur != before; cur = cur->next) pre = cur;
	if (pre) pre->next = insert;
	else clients = insert;
	insert->next = cur;

}

void spawn(Client *t, const char **arg) {
	if (!arg || !arg[0]) return;

	if (!fork()) {
		setsid();
		close(ConnectionNumber(dpy));
		if (conf.stat) fclose(conf.stat);
		if (conf.statfd) close(conf.statfd);











		execvp(arg[0], (char * const *) arg);
	}

}

void tag(Client *t, const char **arg) {
	if (!arg || !arg[0] || !arg[1]) return;
	int tag = atoi(arg[1]);
	if (!tag || tag > 15) return;
	tag = (1<<(tag-1));
	int *n;
	if (!t) n = &m->tags;
	else n = &t->tags;
	switch (arg[0][0]) { /* set toggle add remove */
		case 's': *n = (*n & 0xFFFF0000) | tag; break;
		case 't': *n ^= tag; break;
		case 'a': *n |= tag; break;
		case 'r': *n &= ~tag; break;

	}
}






void word(const char *word) {
	char **arg = NULL, *tok, *sptr, *tmp;
	const char **parg;
	int i, n;
	tmp = strdup(word);
	tok = strtok_r(tmp, " ", &sptr);
	for (i = 0; tok; i++) {
		arg = realloc(arg, (i+1) * sizeof(char *));
		arg[i] = tok;
		tok = strtok_r(NULL," ", &sptr);
	}
	arg = realloc(arg, (i+1) * sizeof(char *));
	arg[i] = NULL;
	parg = (const char **) arg;
	/* get target */
	Client *t = winmarks[1], *wt = NULL;



	if ( (strncasecmp(arg[0],"win",3)==0) && arg[1] ) {
		if ( !(n=atoi(arg[1])) ) {
			n = 1;
			parg = (const char **) &arg[1];
		}
		else {
			parg = (const char **) &arg[2];
		}
		if (n > 0 && n < 10) wt = winmarks[n];
		if (!wt) return;

	}
	/* process command */










	if (strncasecmp(parg[0],"bar",3) == 0) mod_bar(wt,&parg[1]);
	else if (strncasecmp(parg[0],"mon",3) == 0) monitor(wt,&parg[1]);
	else if (strncasecmp(parg[0],"foc",3) == 0) focus(wt,&parg[1]);
	else if (strncasecmp(parg[0],"flo",3) == 0) floater(wt,&parg[1]);
	else if (strncasecmp(parg[0],"ful",3) == 0) fullscreen(wt,&parg[1]);
	else if (strncasecmp(parg[0],"spl",3) == 0) conftile(wt,&parg[0]);
	else if (strncasecmp(parg[0],"gap",3) == 0) conftile(wt,&parg[0]);
	else if (strncasecmp(parg[0],"num",3) == 0) conftile(wt,&parg[0]);
	else if (strncasecmp(parg[0],"lay",3) == 0) layout(wt,&parg[1]);
	else if (strncasecmp(parg[0],"exe",3) == 0) spawn(wt,&parg[1]);
	else if (strncasecmp(parg[0],"mov",3) == 0) move(wt,&parg[1]);
	else if (strncasecmp(parg[0],"kil",3) == 0) killclient(wt,&parg[1]);
	else if (strncasecmp(parg[0],"qui",3) == 0) running = False;
	else if (strncasecmp(parg[0],"tag",3) == 0) tag(wt,&parg[1]);
	else if (strncasecmp(parg[0],"mar",3) == 0) mark_client(wt, &parg[1]);
	else if (strncasecmp(parg[0],"vie",3) == 0) {
		n = (m->tags<<16) & 0xFFFF0000;
		n |= (m->tags>>16) & 0xFFFF;
		m->tags = n;


	}
	free(arg);
	free(tmp);
	tile();

}

Changes to src/actions.h.

1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19

#ifndef __ACTIONS_H__
#define __ACTIONS_H__

extern int command(const char *);

extern int float_full(Client *);
extern int focus(Client *, const char *);
extern int killclient(Client *);
extern int layout(const char *);
extern int mod_bar(const char *);
extern int mod_container(const char *);
extern int move(Client *, const char *);
extern int pull_client(Client *);
extern int push_client(Client *, Client *);
extern int spawn(const char *);
extern int tag(Client *, const char *);
extern int word(const char *);

#endif /* __ACTIONS_H__ */





>
|
|
|
<
|
|
|
|
|
|
|
|


1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19

#ifndef __ACTIONS_H__
#define __ACTIONS_H__

extern int command(const char *);
extern void conftile(Client *, const char **);
extern void float_full(Client *, const char **);
extern void focus(Client *, const char **);
extern void killclient(Client *, const char **);

extern void layout(Client *, const char **);
extern void mod_bar(Client *, const char **);
extern void move(Client *, const char **);
extern void pull_client(Client *);
extern void push_client(Client *, Client *);
extern void spawn(Client *, const char **);
extern void tag(Client *, const char **);
extern void word(const char *);

#endif /* __ACTIONS_H__ */

Changes to src/xlib.c.

332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
	running = True;
	atoms_init();
	return 0;
}

int xlib_free() {
	Client *c;
	for (c = clients; c; c = c->next) killclient(c);
	XUngrabKey(dpy, AnyKey, AnyModifier, root);
	XUngrabButton(dpy, AnyButton, AnyModifier, root);
	XFlush(dpy);
	config_free();
	FT_Done_FreeType(ftlib);
	XCloseDisplay(dpy);
	return 0;







|







332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
	running = True;
	atoms_init();
	return 0;
}

int xlib_free() {
	Client *c;
	for (c = clients; c; c = c->next) killclient(c, NULL);
	XUngrabKey(dpy, AnyKey, AnyModifier, root);
	XUngrabButton(dpy, AnyButton, AnyModifier, root);
	XFlush(dpy);
	config_free();
	FT_Done_FreeType(ftlib);
	XCloseDisplay(dpy);
	return 0;