summary refs log tree commit diff stats
path: root/widgets
Commit message (Collapse)AuthorAgeFilesLines
* Ring bell when new messages arrive 0.2.0Ben Burwell2019-07-293-0/+20
| | | | | | | | Add a "new-message-bell" option to the UI section of aerc.conf. A new hook into the message store allows the msglist widget to detect new messages being added to the displayed list. When new messages are delivered, and the new-message-bell option is enabled (as it is by default), the terminal will beep.
* Add index option to change-tabJeffas2019-07-271-0/+10
| | | | | | | This allows selection of a tab using its index. It attempts to parse the given argument as a number, if it fails then it uses it as a name. Also supports relative indexes using prefixed + or -.
* Add :detach commandGalen Abell2019-07-271-0/+20
| | | | | | | Add a command for removing attachments from a composed message. Syntax is :detach [path], with path being an optional argument specifying the path of one existing attachment. If no path is specified, the first attachment is removed.
* Fix review message not filling entire spaceGalen Abell2019-07-271-1/+1
| | | | | | Adding an attachment, switching to a different tab, and switching back to the review message caused the "filled space" in the review message to disappear, since there was one too many rows in the layout.
* Add tab completion to textinputsJeffas2019-07-261-7/+1
| | | | | | | | | | | | | This adds tab completion to textinput components. They can be configured with a completion function. This function is called when the user presses <tab>. The first completion is initially shown to the user inserted into the text. Repeated presses of <tab> or <backtab> cycle through the completions list. The completions list is invalidated when any other non-tab-like key is pressed. Also changed is some logic for current completion generation so that all available commands are returned when <tab> is pressed with no current text and similarly for arguments of commands.
* Add command history and cyclingGalen Abell2019-07-263-6/+32
| | | | | | Aerc will keep track of the previous 1000 commands, which the user can cycle through using the arrow keys while in the ex-line. Pressing up will move backwards in history while pressing down will move forward.
* Support configurable header layout in compose widgetDaniel Bridges2019-07-264-152/+191
|
* Move msgstore map to dirstoreJeffas2019-07-262-25/+35
| | | | | | This map represents a mapping from directory names to their associated messagestores anyway so they should be under dirstore. This simply moves them there and adds some methods required to interact with them.
* Add new-email triggerJeffas2019-07-263-5/+19
| | | | | | | | | | | | | | | | | This patch sets up the trigger config section of aerc.conf. Each trigger has its own function which is called from the place where it is triggered. Currently only the new-email trigger is implemented. The triggers make use of format strings. For instance, in the new-email trigger this allows the user to select the trigger command and also the information extracted from the command and placed into their command. To actually execute the trigger commands the keypresses are simulated. Further triggers can be implemented in the future. Formatting of the command is moved to a new package.
* Show the directory being selected in grayJeffas2019-07-251-0/+3
|
* Add change tab commandJeffas2019-07-231-0/+22
| | | | | | | | | | This command allows the user to change tab by giving the tab name. This can be tab completed too. The previous tab is stored in the tabs module so that when a new tab is created it is still possible to go to the previous one. Normal invocation is :ct folder Previous tab is :ct -
* Fix alternatives configDrew DeVault2019-07-191-2/+5
|
* Add [a]ttach to the review message promptsDrew DeVault2019-07-191-1/+1
|
* Add Unix socket for communicating with aercDrew DeVault2019-07-192-0/+47
|
* Implement :filter, :clearKevin Kuehler2019-07-192-14/+17
| | | | Signed-off-by: Kevin Kuehler <keur@ocf.berkeley.edu>
* Add :attach command for composeGalen Abell2019-07-191-17/+129
| | | | | | Allow users to add attachments to emails in the Compose view. Syntax is :attach <path>, where path is a valid file. Attachments will show up in the pre-send review screen.
* Add option to always show mimetype in viewerJeffas2019-07-171-4/+6
| | | | | | | | | | A user may want to be able to see what mimetype they are viewing, so that they can determine what program it may be opened in or for some other reason. The config option is under the [viewer] section and is called 'always-show-mime'. It defaults to false to preserve the current behaviour.
* Remove passing of showHeaders explicitlyJeffas2019-07-171-12/+12
| | | | | Where it is needed the configs are already available so just extract the value from these.
* Ensure new partswitcher doesn't start on multipartJeffas2019-07-171-0/+2
|
* Display user specified headers in viewer if presentDaniel Bridges2019-07-171-40/+61
|
* Show currently pressed keys in statuslineJeffas2019-07-172-1/+17
| | | | | | This patch adds the currently pressed keys to the statusline. This is useful when keybindings are multiple keys long and you might forget which keys are already pressed.
* Revert "Ensure new partswitcher doesn't start on multipart"Drew DeVault2019-07-171-1/+0
| | | | This reverts commit 41390bc3e1e557eff15e8159767f206b3b74ea30.
* When reviewing an email don't pass characters onJeffas2019-07-171-1/+4
| | | | | This stops characters being passed to the focused box when reviewing an email. To edit headers the user should go back to the edit page.
* Ensure new partswitcher doesn't start on multipartJeffas2019-07-171-0/+1
|
* Don't initialize an invalid pty sizeDrew DeVault2019-07-131-0/+3
|
* Add clickable tabsJeffas2019-07-111-0/+2
| | | | | | | | | | | This introduces a new interface `Clickable`. I'd imagine this would be implemented for most widgets eventually and would allow for programs run in the terminal to also have their mouse events forwarded to them. For the tabs it was relatively simple to check that the position of the click is within the boxes for the tabs. For other components I'd imagine that some state representing their currently drawn bounding box would be useful.
* Add backtab to tutorial navigationJeffas2019-07-111-1/+3
| | | | | | | | This allows users to use backtab (Shift+tab) to go back through the fields in the tutorial, like C-K. This then mimics the other methods in having a forward and backward variant. Also documented this in the wizard help paragraph.
* Fix crashes when operating on empty folder (#216)Daniel Bridges2019-07-103-5/+13
|
* Factor IMAP-specific structs out of UI modelsBen Burwell2019-07-083-15/+11
| | | | | | | Before, we were using several IMAP-specific concepts to represent information being displayed in the UI. Factor these structures out of the IMAP package to make it easier for other backends to provide the required information.
* Factor UI models out of the worker message packageBen Burwell2019-07-085-17/+18
| | | | | | | | Before, the information needed to display different parts of the UI was tightly coupled to the specific messages being sent back and forth to the backend worker. Separating out a models package allows us to be more specific about exactly what a backend is able to and required to provide for the UI.
* Make :pipe command more genericDrew DeVault2019-07-053-11/+18
|
* Sort out dirstore once and for allDrew DeVault2019-07-041-0/+1
|
* dirlist: simplify nextPrev() considerablyReto Brunner2019-07-041-25/+11
| | | | | | | Assuming we always have a sorted dirlist (other code depends on that already), we don't need to loop over the dirStore. Any filtering done should be performed elsewhere
* dirlist: remove the additional filtering in Draw()Reto Brunner2019-07-041-7/+0
|
* dirlist: sync dirstore in filterDirsByFoldersConfigReto Brunner2019-07-041-9/+7
| | | | | Also sets the public List() method to return the unfiltered list of directories directly from the store.
* Add IMAP folder tab completionGregory Mullen2019-07-041-1/+5
| | | | | Credit for this fix goes to Reto; I guess if we're not gonna be mutt we should probabaly do things correctly.
* Use go-message implementation of GenerateMessageIDBen Burwell2019-07-041-2/+1
| | | | | Now that this is available in the upstream, we no longer need to maintain a parallel implementation.
* Revert "Remove dirs field and references to it"Drew DeVault2019-07-021-11/+10
| | | | This reverts commit 0e55637aac92e748267559b7aa91a188a17c386f.
* Remove dirs field and references to itRobert Günzler2019-06-301-10/+11
| | | | | This fixes prev/next-folder that broke after 546dfcd76dd228e0605359e9985f0b6a5672e8fa
* Add new lib/dirstore to source completions fromGregory Mullen2019-06-291-4/+7
|
* Implement basic tab completion supportGregory Mullen2019-06-293-8/+26
| | | | | Tab completion currently only works on commands. Contextual completion will be added in the future.
* Reopening mailcontent file to fix #166Stefan Rakel2019-06-271-1/+7
| | | | | | Because editors like vim use backupfiles and rename them to the original name, the file handle used can point to the wrong file. Reopening the file should fix this.
* Fix jumping around in searchDrew DeVault2019-06-261-10/+5
|
* Implement :search, :next-result, :prev-resultDrew DeVault2019-06-261-0/+1
|
* account-wizard: look up imap and smtp server by SRV records (#100)Daniel Lublin2019-06-251-1/+42
|
* Fix Cc & Bcc handling in repliesDrew DeVault2019-06-212-7/+11
|
* account-wizard: automatically replace imap.* with smtp.*Noah Loomans2019-06-181-1/+6
| | | | | | | | | Many email providers use the imap sub-domain for imap and the smtp sub-domain for smtp. FastMail is an example of this[1]. This is a small quality-of-life improvement which automatically replaces imap.* with smtp.* when going from the imap screen to the smtp screen in the wizard [1]: https://www.fastmail.com/help/technical/servernamesandports.html
* Set empty message in dirlist if no folder exist.Reto Brunner2019-06-142-18/+28
|
* imap: respect the folder config optionReto Brunner2019-06-142-12/+32
|
* Fix automatic scrolling when messages arrive/leaveDrew DeVault2019-06-111-2/+2
|
kloc.org> 2006-08-24 09:25:10 +0200 changing tag indicator through underline' href='/acidbong/suckless/dwm/commit/main.c?h=3.0&id=2e834e941f695481894123e0665416f96333653b'>2e834e9 ^
6651dd7 ^
b5159df ^
b5159df ^

adaa28a ^




ca65478 ^
adaa28a ^



bf35794 ^

3399650 ^
ca65478 ^
0ff8065 ^
352e1b4 ^

3399650 ^
0ff8065 ^


352e1b4 ^
3399650 ^
0ff8065 ^
c09bf8d ^
080a38d ^
352e1b4 ^
3399650 ^



ca65478 ^
3399650 ^








e6cbe9c ^
3399650 ^

adaa28a ^
ca65478 ^
727449d ^
1076f2b

6651dd7 ^
bf35794 ^
b597fa4 ^
dba2306 ^

ca65478 ^
dba2306 ^
dc5d967 ^




1d7674b ^

dba2306 ^

dc5d967 ^
b597fa4 ^
4641aa2 ^

1076f2b
ca65478 ^
61a1910 ^
b5159df ^
dc5d967 ^
1076f2b
4970ef9 ^
ac24f13 ^
4970ef9 ^
1076f2b
4970ef9 ^

d42c3ba ^
1076f2b

86d1224 ^
e571de8 ^
1076f2b

dba2306 ^

86d1224 ^
1076f2b
f60c597 ^
dba2306 ^

1076f2b
b6ad663 ^
f60c597 ^
dba2306 ^
2ffdc19 ^
b5159df ^
c0705ee ^
dba2306 ^
1076f2b
4e2c5b5 ^
0680c76 ^
b6ad663 ^
727449d ^
e3fd306 ^
0e5c819 ^
95e8d12 ^

e571de8 ^
478f6f9 ^


61a1910 ^
478f6f9 ^

61a1910 ^
478f6f9 ^
61a1910 ^
35e96b8 ^
478f6f9 ^


35e96b8 ^
478f6f9 ^


2210ea7 ^

61a1910 ^

0e5c819 ^
478f6f9 ^
0e5c819 ^
478f6f9 ^

439e15d ^
1076f2b

1076f2b

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
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
                                                                    


                                        
                
                  
                   

                   
                   
                   
                       
                           
                       


                       



                 
                                                                             
                                                 




                                      
                     




                       
            
 
                                                   
                            

           
               
                            


                                             
         



                                               
                                                   

                                      
                                    


                                            
                                                                           
                          
                     
 
 
           
            
                            
                             
                             
 
                    






                                                                                           
                                                     





                            
           
             












                                                                             



                                                                
                               






                                                                                                                    
                                 
                               

                                                                         

                                                                        

                    


                                                
                   





                                                   
                      
                      
                                                                                               


                                        
                        
                          
                 

                
                
                                       







                                                                                       
                                     

                        
                      

                      
                                   

                                                                                  
                                                                         
                               
                                                                        

 




                                                           
                                              



                       

            
   
                    
                                      

                                 
 


                                                                                             
                                               
                              
                                
                                                    
                                              
                        



                      
                                         








                                                   
                          

 
    
                
                                 

 
                                                                              
                                                                           
                                              

   
                                       
                                      




                                                                                     

                                                                             

                                                                             
                                                  
                                                       

 
   
                              
                
                   
                  
 
                                                     
                                                                                         
                                   
         

                                            
                                

                              
                                                     
                                    

                                       

                                      
                                                                          
                                                          
                          

                                                                           
 
                          
                               
                                              
                          
                
                     
               
 
                                                                
                          
                    
                      
                        
                             

                                                  
                                 


                                                                  
                                                  

                                                 
                                                                                 
                                
                                                                                  
                                                               


                                               
                                                         


                                               

                                                                                                                           

                                                                            
                         
                                     
                 

                                      
         

                           

                 
/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
 * See LICENSE file for license details.
 */

#include "dwm.h"
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>

/* extern */

char stext[1024];
Bool *seltag;
int bx, by, bw, bh, bmw, masterd, screen, sx, sy, sw, sh, wax, way, waw, wah;
unsigned int master, nmaster, ntags, numlockmask;
Atom wmatom[WMLast], netatom[NetLast];
Bool running = True;
Bool issel = True;
Client *clients = NULL;
Client *sel = NULL;
Client *stack = NULL;
Cursor cursor[CurLast];
Display *dpy;
DC dc = {0};
Window root, barwin;

/* static */

static int (*xerrorxlib)(Display *, XErrorEvent *);
static Bool otherwm, readin;

static void
cleanup(void) {
	close(STDIN_FILENO);
	while(stack) {
		resize(stack, True, TopLeft);
		unmanage(stack);
	}
	if(dc.font.set)
		XFreeFontSet(dpy, dc.font.set);
	else
		XFreeFont(dpy, dc.font.xfont);
	XUngrabKey(dpy, AnyKey, AnyModifier, root);
	XFreePixmap(dpy, dc.drawable);
	XFreeGC(dpy, dc.gc);
	XDestroyWindow(dpy, barwin);
	XFreeCursor(dpy, cursor[CurNormal]);
	XFreeCursor(dpy, cursor[CurResize]);
	XFreeCursor(dpy, cursor[CurMove]);
	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
	XSync(dpy, False);
	free(seltag);
}

static void
scan(void) {
	unsigned int i, num;
	Window *wins, d1, d2;
	XWindowAttributes wa;

	wins = NULL;
	if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
		for(i = 0; i < num; i++) {
			if(!XGetWindowAttributes(dpy, wins[i], &wa))
				continue;
			if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
				continue;
			if(wa.map_state == IsViewable)
				manage(wins[i], &wa);
		}
	}
	if(wins)
		XFree(wins);
}

static void
setup(void) {
	int i, j;
	unsigned int mask;
	Window w;
	XModifierKeymap *modmap;
	XSetWindowAttributes wa;

	/* init atoms */
	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
	wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
			PropModeReplace, (unsigned char *) netatom, NetLast);
	/* init cursors */
	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
	/* init modifier map */
	modmap = XGetModifierMapping(dpy);
	for (i = 0; i < 8; i++) {
		for (j = 0; j < modmap->max_keypermod; j++) {
			if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock))
				numlockmask = (1 << i);
		}
	}
	XFreeModifiermap(modmap);
	/* select for events */
	wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
		| EnterWindowMask | LeaveWindowMask;
	wa.cursor = cursor[CurNormal];
	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
	grabkeys();
	initrregs();
	for(ntags = 0; tags[ntags]; ntags++);
	seltag = emallocz(sizeof(Bool) * ntags);
	seltag[0] = True;
	/* style */
	dc.norm[ColBG] = getcolor(NORMBGCOLOR);
	dc.norm[ColFG] = getcolor(NORMFGCOLOR);
	dc.sel[ColBG] = getcolor(SELBGCOLOR);
	dc.sel[ColFG] = getcolor(SELFGCOLOR);
	dc.status[ColBG] = getcolor(STATUSBGCOLOR);
	dc.status[ColFG] = getcolor(STATUSFGCOLOR);
	setfont(FONT);
	/* geometry */
	bmw = textw(TILESYMBOL) > textw(FLOATSYMBOL) ?  textw(TILESYMBOL) : textw(FLOATSYMBOL);
	sx = sy = 0;
	sw = DisplayWidth(dpy, screen);
	sh = DisplayHeight(dpy, screen);
	master = MASTER;
	nmaster = NMASTER;
	/* bar */
	bx = sx;
	by = sy;
	bw = sw;
	dc.h = bh = dc.font.height + 2;
	wa.override_redirect = 1;
	wa.background_pixmap = ParentRelative;
	wa.event_mask = ButtonPressMask | ExposureMask;
	barwin = XCreateWindow(dpy, root, bx, by, bw, bh, 0, DefaultDepth(dpy, screen),
			CopyFromParent, DefaultVisual(dpy, screen),
			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
	XDefineCursor(dpy, barwin, cursor[CurNormal]);
	XMapRaised(dpy, barwin);
	strcpy(stext, "dwm-"VERSION);
	/* windowarea */
	wax = sx;
	way = sy + bh;
	wah = sh - bh;
	waw = sw;
	/* pixmap for everything */
	dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
	dc.gc = XCreateGC(dpy, root, 0, 0);
	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
	/* multihead support */
	issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
}

/*
 * Startup Error handler to check if another window manager
 * is already running.
 */
static int
xerrorstart(Display *dsply, XErrorEvent *ee) {
	otherwm = True;
	return -1;
}

/* extern */

int
getproto(Window w) {
	int i, format, protos, status;
	unsigned long extra, res;
	Atom *protocols, real;

	protos = 0;
	status = XGetWindowProperty(dpy, w, wmatom[WMProtocols], 0L, 20L, False,
			XA_ATOM, &real, &format, &res, &extra, (unsigned char **)&protocols);
	if(status != Success || protocols == 0)
		return protos;
	for(i = 0; i < res; i++)
		if(protocols[i] == wmatom[WMDelete])
			protos |= PROTODELWIN;
	free(protocols);
	return protos;
}

void
sendevent(Window w, Atom a, long value) {
	XEvent e;

	e.type = ClientMessage;
	e.xclient.window = w;
	e.xclient.message_type = a;
	e.xclient.format = 32;
	e.xclient.data.l[0] = value;
	e.xclient.data.l[1] = CurrentTime;
	XSendEvent(dpy, w, False, NoEventMask, &e);
	XSync(dpy, False);
}

void
quit(Arg *arg) {
	readin = running = False;
}

/* There's no way to check accesses to destroyed windows, thus those cases are
 * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs
 * default error handler, which may call exit.
 */
int
xerror(Display *dpy, XErrorEvent *ee) {
	if(ee->error_code == BadWindow
	|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
	|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
	|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
	|| (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
	|| (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
	|| (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
	|| (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
		return 0;
	fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
		ee->request_code, ee->error_code);
	return xerrorxlib(dpy, ee); /* may call exit */
}

int
main(int argc, char *argv[]) {
	char *p;
	int r, xfd;
	fd_set rd;

	if(argc == 2 && !strncmp("-v", argv[1], 3)) {
		fputs("dwm-"VERSION", (C)opyright MMVI-MMVII Anselm R. Garbe\n", stdout);
		exit(EXIT_SUCCESS);
	}
	else if(argc != 1)
		eprint("usage: dwm [-v]\n");
	setlocale(LC_CTYPE, "");
	dpy = XOpenDisplay(0);
	if(!dpy)
		eprint("dwm: cannot open display\n");
	xfd = ConnectionNumber(dpy);
	screen = DefaultScreen(dpy);
	root = RootWindow(dpy, screen);
	otherwm = False;
	XSetErrorHandler(xerrorstart);
	/* this causes an error if some other window manager is running */
	XSelectInput(dpy, root, SubstructureRedirectMask);
	XSync(dpy, False);
	if(otherwm)
		eprint("dwm: another window manager is already running\n");

	XSync(dpy, False);
	XSetErrorHandler(NULL);
	xerrorxlib = XSetErrorHandler(xerror);
	XSync(dpy, False);
	setup();
	drawstatus();
	scan();

	/* main event loop, also reads status text from stdin */
	XSync(dpy, False);
	procevent();
	readin = True;
	while(running) {
		FD_ZERO(&rd);
		if(readin)
			FD_SET(STDIN_FILENO, &rd);
		FD_SET(xfd, &rd);
		if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) {
			if(errno == EINTR)
				continue;
			eprint("select failed\n");
		}
		if(FD_ISSET(STDIN_FILENO, &rd)) {
			switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) {
			case -1:
				strncpy(stext, strerror(errno), sizeof stext - 1);
				stext[sizeof stext - 1] = '\0';
				readin = False;
				break;
			case 0:
				strncpy(stext, "EOF", 4);
				readin = False;
				break;
			default:
				for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0');
				for(p = stext + strlen(stext) - 1; p >= stext && *p != '\n'; --p);
				if(p > stext)
					strncpy(stext, p + 1, sizeof stext);
			}
			drawstatus();
		}
		if(FD_ISSET(xfd, &rd))
			procevent();
	}
	cleanup();
	XCloseDisplay(dpy);
	return 0;
}