about summary refs log tree commit diff stats
path: root/dwm.html
blob: c8608ca20cec009cc7cb2f1851aededd1cd9e531 (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
<html>
	<head>
		<title>dwm - dynamic window manager</title>
		<meta name="author" content="Anselm R. Garbe">
		<meta name="generator" content="ed">
		<meta name="copyright" content="(C)opyright 2006 by Anselm R. Garbe">
		<link rel="dwm icon" href="favicon.ico" type="image/x-icon" />
		<style type="text/css">
			body {
				color: #000000;
				font-family: sans-serif;
				margin: 20px 20px 20px 20px;
			}
		</style>
	</head>
	<body>
		<center>
			<img src="dwm.png"/><br />
			<h3>dynamic window manager</h3>
		</center>
		<h3>Description</h3>
		<p>
		dwm is a dynamic window manager for X11.
		</p>
		<h4>Background</h4>
		<p>
		As founder and main developer of wmii I came to the conclusion that
		wmii is too clunky for my needs. I don't need so many funky features
		and all this hype about remote control through a 9P service, I only
		want to manage my windows in a simple, but dynamic way. wmii never got
		finished because I listened to users, who proposed arbitrary ideas I
		considered useful. This resulted in an extreme <a
		href="http://www.jwz.org/doc/cadt.html">CADT</a> development model,
		which was a mistake. Thus the philosophy of dwm is simply <i>to fit my
		needs</i> (maybe yours as well). That's it.
		</p>
		<h4>Differences to ion, larswm, and wmii</h4>
		<p>
		In contrast to ion, larswm, and wmii, dwm is much smaller, faster and simpler.
		</p>
		<ul>
			<li>
			dwm has no Lua integration, no 9P support, no editable
			tagbars, no shell-based configuration, no remote control, and comes
			without any additional tools like printing the selection or warping
			the mouse.
			</li>
			<li>
			dwm is only a single binary, it's source code is intended to never
			exceed 2000 SLOC.
			</li>
			<li>
			dwm is based on tagging and dynamic window management (however
			simpler than ion, wmii or larswm). It manages windows in
			tiling and floating modes. Either mode can be applied dynamically,
			depending on the application in use and the task performed.
			</li>
			<li>
			dwm doesn't distinguishes between layers, there is no floating or
			tiled layer. Wether the clients of currently selected tag are in
			tiled mode or not, you can re-arrange all clients on the fly.
			Popup- and fixed-size windows are treated floating, however. 
			</li>
			<li>
			dwm is customized through editing its source code, that makes it
			extremely fast and secure - it does not process any input data
			which hasn't been known at compile time, except window title names
			and status text read from standard input. You don't have to learn
			Lua/sh/ruby or some weird configuration file format (like X
			resource files), beside C to customize it for your needs,
			you <b>only</b> have to learn C (at least editing header files).
			</li>
			<li>
			Because dwm is customized through editing its source code, it's
			pointless to make binary packages of it. This keeps its userbase
			small and elitist. No novices asking stupid questions.
			</li>
			<li>
			dwm uses 1-pixel borders to provide the maximum of screen real
			estate to clients. Small titlebars are only drawn in front of
			unfocused clients.
			</li>
			<li>
			dwm reads from standard input to print arbitrary status text (like
			the date, load, battery charge). That's much simpler than
			larsremote, wmiir and what not...
			</li>
			<li>
			It can be downloaded and distributed under the conditions
			of the <a href="http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm?f=f10eb1139362;file=LICENSE;style=raw">MIT/X Consortium license</a>.
			</li>
			<li>
			Optionally you can install <b>dmenu</b> to extend dwm with a wmii-alike menu.
			</li>
		</ul>
		<h4>Links</h4>
		<ul>
			<li><a href="http://10kloc.org/cgi-bin/man/man2html?query=dwm">Man page</a></li>
			<li><a href="http://10kloc.org/shots/dwm-20060810a.png">Screenshot of tiled mode</a> (20060810)</li>
			<li><a href="http://10kloc.org/shots/dwm-20060810b.png">Screenshotof floating mode</a> (20060810)</li>
			<li><a href="http://10kloc.org/download/poster.ps">A4 poster (PostScript)</a></li>
			<li>Mailing List: <a href="http://10kloc.org/cgi-bin/mailman/listinfo/dwm">dwm at wmii dot de</a> <a href="http://10kloc.org/pipermail/dwm/">(Archives)</a>&nbsp;<a href="http://dir.gmane.org/gmane.comp.window-managers.dwm">(GMANE Archive)</a></li>
			<li>IRC channel: <code>#dwm</code> at <code>irc.oftc.net</code></li>
		</ul>
		<h3>Download</h3>
		<ul>
			<li><a href="http://10kloc.org/download/dwm-1.0.tar.gz">dwm 1.0</a> (15kb) (20060824)</li>
			<li><a href="http://10kloc.org/download/dmenu-0.5.tar.gz">dmenu 0.5</a> (7kb) (20060824)</li>
		</ul>
		<h3>Development</h3>
		<p>
		dwm is actively developed in parallel to wmii. You can <a href="http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm">browse</a> its source code repository or get a copy using <a href="http://www.selenic.com/mercurial/">Mercurial</a> with following command:
		</p>
		<p>
		<code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm</code>
		</p>
		<p>
		<code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dmenu</code>
		</p>
		<h3>Miscellaneous</h3>
		<p>
		You can purchase this <a href="https://www.spreadshirt.net/shop.php?op=article&article_id=3298632&view=403">tricot</a>
		if you like dwm and the dwm logo, which has been designed by Anselm.
		</p>
		<p><small>--Anselm</small></p>
	</body>
</html>
s="p">{ beginning, before_tag, colon, before_value, value, bracketed_value, quoted_value, escape_in_quoted, done }; /* Stream Object * ------------ * * The target is the structured stream down which the * parsed results will go. * * all the static stuff below should go in here to make it reentrant */ struct _HTStream { const HTStreamClass *isa; HTStructured *target; char *par_value[PAR_COUNT]; enum tokenstate state; char param[BIG + 1]; int param_number; int param_count; }; /* Decode one hex character */ char from_hex(char c) { return (char) ((c >= '0') && (c <= '9') ? c - '0' : (c >= 'A') && (c <= 'F') ? c - 'A' + 10 : (c >= 'a') && (c <= 'f') ? c - 'a' + 10 : 0); } /* State machine * ------------- * * On entry, * me->state is a valid state (see WSRC_init) * c is the next character * On exit, * returns 1 Done with file * 0 Continue. me->state is updated if necessary. * -1 Syntax error error */ /* Treat One Character * ------------------- */ static void WSRCParser_put_character(HTStream *me, int c) { switch (me->state) { case beginning: if (c == '(') me->state = before_tag; break; case before_tag: if (c == ')') { me->state = done; return; /* Done with input file */ } else if (c == ':') { me->param_count = 0; me->state = colon; } /* Ignore other text */ break; case colon: if (WHITE(c)) { me->param[me->param_count++] = 0; /* Terminate */ for (me->param_number = 0; par_name[me->param_number]; me->param_number++) { if (0 == strcmp(par_name[me->param_number], me->param)) { break; } } if (!par_name[me->param_number]) { /* Unknown field */ CTRACE((tfp, "HTWSRC: Unknown field `%s' in source file\n", me->param)); me->param_number = PAR_UNKNOWN; me->state = before_value; /* Could be better ignore */ return; } me->state = before_value; } else { if (me->param_count < PARAM_MAX) me->param[me->param_count++] = (char) c; } break; case before_value: if (c == ')') { me->state = done; return; /* Done with input file */ } if (WHITE(c)) return; /* Skip white space */ me->param_count = 0; if (c == '"') { me->state = quoted_value; break; } me->state = (c == '"') ? quoted_value : (c == '(') ? bracketed_value : value; me->param[me->param_count++] = (char) c; /* Don't miss first character */ break; case value: if (WHITE(c)) { me->param[me->param_count] = 0; StrAllocCopy(me->par_value[me->param_number], me->param); me->state = before_tag; } else { if (me->param_count < PARAM_MAX) me->param[me->param_count++] = (char) c; } break; case bracketed_value: if (c == ')') { me->param[me->param_count] = 0; StrAllocCopy(me->par_value[me->param_number], me->param); me->state = before_tag; break; } if (me->param_count < PARAM_MAX) me->param[me->param_count++] = (char) c; break; case quoted_value: if (c == '"') { me->param[me->param_count] = 0; StrAllocCopy(me->par_value[me->param_number], me->param); me->state = before_tag; break; } if (c == '\\') { /* Ignore escape but switch state */ me->state = escape_in_quoted; break; } /* Fall through! */ case escape_in_quoted: if (me->param_count < PARAM_MAX) me->param[me->param_count++] = (char) c; me->state = quoted_value; break; case done: /* Ignore anything after EOF */ return; } /* switch me->state */ } /* Open Cache file * =============== * * Bugs: Maybe for filesystem-challenged platforms (MSDOS for example) we * should make a hash code for the filename. */ #ifdef CACHE_FILE_PREFIX static BOOL write_cache(HTStream *me) { FILE *fp; char *cache_file_name = NULL; char *www_database; int result = NO; if (!me->par_value[PAR_DATABASE_NAME] || !me->par_value[PAR_IP_NAME] ) return NO; www_database = HTEscape(me->par_value[PAR_DATABASE_NAME], URL_XALPHAS); HTSprintf0(&cache_file_name, "%sWSRC-%s:%s:%.100s.txt", CACHE_FILE_PREFIX, me->par_value[PAR_IP_NAME], (me->par_value[PAR_TCP_PORT] ? me->par_value[PAR_TCP_PORT] : "210"), www_database); if ((fp = fopen(cache_file_name, TXT_W)) != 0) { result = YES; if (me->par_value[PAR_DESCRIPTION]) fputs(me->par_value[PAR_DESCRIPTION], fp); else fputs("Description not available\n", fp); fclose(fp); } FREE(www_database); FREE(cache_file_name); return result; } #endif /* Output equivalent HTML * ---------------------- * */ static void give_parameter(HTStream *me, int p) { PUTS(par_name[p]); if (me->par_value[p]) { PUTS(": "); PUTS(me->par_value[p]); PUTS("; "); } else { PUTS(gettext(" NOT GIVEN in source file; ")); } } /* Generate Outout * =============== */ static void WSRC_gen_html(HTStream *me, int source_file) { if (me->par_value[PAR_DATABASE_NAME]) { char *shortname = 0; int l; StrAllocCopy(shortname, me->par_value[PAR_DATABASE_NAME]); l = (int) strlen(shortname); if (l > 4 && !strcasecomp(shortname + l - 4, ".src")) { shortname[l - 4] = 0; /* Chop of .src -- boring! */ } START(HTML_HEAD); PUTC('\n'); START(HTML_TITLE); PUTS(shortname); PUTS(source_file ? gettext(" WAIS source file") : INDEX_SEGMENT); END(HTML_TITLE); PUTC('\n'); END(HTML_HEAD); START(HTML_H1); PUTS(shortname); PUTS(source_file ? gettext(" description") : INDEX_SEGMENT); END(HTML_H1); PUTC('\n'); FREE(shortname); } START(HTML_DL); /* Definition list of details */ if (source_file) { START(HTML_DT); PUTS(gettext("Access links")); MAYBE_END(HTML_DT); START(HTML_DD); if (me->par_value[PAR_IP_NAME] && me->par_value[PAR_DATABASE_NAME]) { char *WSRC_address = NULL; char *www_database; www_database = HTEscape(me->par_value[PAR_DATABASE_NAME], URL_XALPHAS); HTSprintf0(&WSRC_address, "%s//%s%s%s/%s", STR_WAIS_URL, me->par_value[PAR_IP_NAME], me->par_value[PAR_TCP_PORT] ? ":" : "", (me->par_value[PAR_TCP_PORT] ? me->par_value[PAR_TCP_PORT] : ""), www_database); HTStartAnchor(me->target, NULL, WSRC_address); PUTS(gettext("Direct access")); END(HTML_A); /** Proxy will be used if defined, so let user know that - FM **/ PUTS(gettext(" (or via proxy server, if defined)")); FREE(www_database); FREE(WSRC_address); } else { give_parameter(me, PAR_IP_NAME); give_parameter(me, PAR_DATABASE_NAME); } MAYBE_END(HTML_DD); } /* end if source_file */ if (me->par_value[PAR_MAINTAINER]) { START(HTML_DT); PUTS(gettext("Maintainer")); MAYBE_END(HTML_DT); START(HTML_DD); PUTS(me->par_value[PAR_MAINTAINER]); MAYBE_END(HTML_DD); } if (me->par_value[PAR_IP_NAME]) { START(HTML_DT); PUTS(gettext("Host")); MAYBE_END(HTML_DT); START(HTML_DD); PUTS(me->par_value[PAR_IP_NAME]); MAYBE_END(HTML_DD); } END(HTML_DL); if (me->par_value[PAR_DESCRIPTION]) { START(HTML_PRE); /* Preformatted description */ PUTS(me->par_value[PAR_DESCRIPTION]); END(HTML_PRE); } (*me->target->isa->_free) (me->target); return; } /* generate html */ static void WSRCParser_put_string(HTStream *context, const char *str) { const char *p; for (p = str; *p; p++) WSRCParser_put_character(context, *p); } static void WSRCParser_write(HTStream *context, const char *str, int l) { const char *p; const char *e = str + l; for (p = str; p < e; p++) WSRCParser_put_character(context, *p); } static void WSRCParser_free(HTStream *me) { WSRC_gen_html(me, YES); #ifdef CACHE_FILE_PREFIX write_cache(me); #endif { int p; for (p = 0; par_name[p]; p++) { /* Clear out old values */ FREE(me->par_value[p]); } } FREE(me); } static void WSRCParser_abort(HTStream *me, HTError e GCC_UNUSED) { WSRCParser_free(me); } /* Stream subclass -- method routines * --------------- */ static HTStreamClass WSRCParserClass = { "WSRCParser", WSRCParser_free, WSRCParser_abort, WSRCParser_put_character, WSRCParser_put_string, WSRCParser_write }; /* Converter from WAIS Source to whatever * -------------------------------------- */ HTStream *HTWSRCConvert(HTPresentation *pres, HTParentAnchor *anchor, HTStream *sink) { HTStream *me = (HTStream *) malloc(sizeof(*me)); if (!me) outofmem(__FILE__, "HTWSRCConvert"); assert(me != NULL); me->isa = &WSRCParserClass; me->target = HTML_new(anchor, pres->rep_out, sink); { int p; for (p = 0; p < PAR_COUNT; p++) { /* Clear out parameter values */ me->par_value[p] = 0; } } me->state = beginning; return me; }