initial import
This commit is contained in:
		
						commit
						1076f2b6b3
					
				
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | MIT/X Consortium License | ||||||
|  | 
 | ||||||
|  | (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> | ||||||
|  | 
 | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a | ||||||
|  | copy of this software and associated documentation files (the "Software"), | ||||||
|  | to deal in the Software without restriction, including without limitation | ||||||
|  | the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||||
|  | and/or sell copies of the Software, and to permit persons to whom the  | ||||||
|  | Software is furnished to do so, subject to the following conditions: | ||||||
|  | 
 | ||||||
|  | The above copyright notice and this permission notice shall be included in  | ||||||
|  | all copies or substantial portions of the Software.  | ||||||
|  | 
 | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  | ||||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL  | ||||||
|  | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  | ||||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  | ||||||
|  | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER  | ||||||
|  | DEALINGS IN THE SOFTWARE. | ||||||
							
								
								
									
										23
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | # gridwm - grid window manager
 | ||||||
|  | #   (C)opyright MMVI Anselm R. Garbe
 | ||||||
|  | 
 | ||||||
|  | include config.mk | ||||||
|  | 
 | ||||||
|  | SRC      = wm.c | ||||||
|  | OBJ      = ${SRC:.c=.o} | ||||||
|  | 
 | ||||||
|  | all: gridwm | ||||||
|  | 	@echo finished | ||||||
|  | 
 | ||||||
|  | .c.o: | ||||||
|  | 	@echo CC $< | ||||||
|  | 	@${CC} -c ${CFLAGS} $< | ||||||
|  | 
 | ||||||
|  | ${OBJ}: wm.h | ||||||
|  | 
 | ||||||
|  | gridwm: ${OBJ} | ||||||
|  | 	@echo LD $@ | ||||||
|  | 	@${CC} -o $@ ${OBJ} ${X11LDFLAGS} | ||||||
|  | 
 | ||||||
|  | clean: | ||||||
|  | 	rm -f gridwm *.o | ||||||
							
								
								
									
										40
									
								
								README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								README
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | |||||||
|  | gridwm | ||||||
|  | ------ | ||||||
|  | 
 | ||||||
|  | gridwm is an automatic X11 window manager which arranges all windows in a grid. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Requirements | ||||||
|  | ------------ | ||||||
|  | In order to build gridwm you need the Xlib header files. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Installation | ||||||
|  | ------------ | ||||||
|  | Edit config.mk to match your local setup. gridwm is installed into | ||||||
|  | the /usr/local namespace by default. | ||||||
|  | 
 | ||||||
|  | Afterwards enter the following command to build and install gridwm (if | ||||||
|  | necessary as root): | ||||||
|  | 
 | ||||||
|  |     make clean install | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Running gridwm | ||||||
|  | -------------- | ||||||
|  | Add the following line to your .xinitrc to start gridwm using startx: | ||||||
|  | 
 | ||||||
|  |     exec gridwm | ||||||
|  | 
 | ||||||
|  | In order to connect gridwm to a specific display, make sure that | ||||||
|  | the DISPLAY environment variable is set correctly, e.g.: | ||||||
|  | 
 | ||||||
|  |     DISPLAY=foo.bar:1 exec wmii | ||||||
|  | 
 | ||||||
|  | This will start gridwm on display :1 of the host foo.bar. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Configuration | ||||||
|  | ------------- | ||||||
|  | The configuration of gridwm is done by customizing the config.h | ||||||
|  | source file. | ||||||
							
								
								
									
										29
									
								
								config.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								config.mk
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  | # Customize to fit your system
 | ||||||
|  | 
 | ||||||
|  | # paths
 | ||||||
|  | PREFIX = /usr/local | ||||||
|  | CONFPREFIX = ${PREFIX}/etc | ||||||
|  | MANPREFIX = ${PREFIX}/share/man | ||||||
|  | 
 | ||||||
|  | X11INC = /usr/X11R6/include | ||||||
|  | X11LIB = /usr/X11R6/lib | ||||||
|  | 
 | ||||||
|  | VERSION = 0.0 | ||||||
|  | 
 | ||||||
|  | # includes and libs
 | ||||||
|  | LIBS = -L${PREFIX}/lib -L/usr/lib -lc | ||||||
|  | X11LIBS = -L${X11LIB} -lX11 | ||||||
|  | 
 | ||||||
|  | # Linux/BSD
 | ||||||
|  | CFLAGS = -g -Wall -I. -I${PREFIX}/include -I/usr/include -I${X11INC} \
 | ||||||
|  | 	-DVERSION=\"${VERSION}\" | ||||||
|  | LDFLAGS = -g ${LIBS} | ||||||
|  | X11LDFLAGS = ${LDFLAGS} ${X11LIBS} | ||||||
|  | 
 | ||||||
|  | # Solaris
 | ||||||
|  | #CFLAGS = -fast -xtarget=ultra ${INCLUDES} -DVERSION=\"${VERSION}\"
 | ||||||
|  | #LIBS += -lnsl -lsocket
 | ||||||
|  | 
 | ||||||
|  | AR = ar cr | ||||||
|  | CC = cc | ||||||
|  | RANLIB = ranlib | ||||||
							
								
								
									
										16
									
								
								gridwm.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								gridwm.1
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | .TH GRIDWM 1 gridwm-0.0 | ||||||
|  | .SH NAME | ||||||
|  | gridwm \- grid window manager | ||||||
|  | .SH SYNOPSIS | ||||||
|  | .B gridwm | ||||||
|  | .RB [ \-v ] | ||||||
|  | .SH DESCRIPTION | ||||||
|  | .SS Overview | ||||||
|  | .B gridwm | ||||||
|  | is an automatic window manager for X11. | ||||||
|  | .SS Options | ||||||
|  | .TP | ||||||
|  | .B \-v | ||||||
|  | prints version information to stdout, then exits. | ||||||
|  | .SH SEE ALSO | ||||||
|  | .BR gridmenu (1) | ||||||
							
								
								
									
										264
									
								
								wm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								wm.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,264 @@ | |||||||
|  | /*
 | ||||||
|  |  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> | ||||||
|  |  * See LICENSE file for license details. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | 
 | ||||||
|  | #include <X11/cursorfont.h> | ||||||
|  | #include <X11/Xatom.h> | ||||||
|  | #include <X11/Xproto.h> | ||||||
|  | 
 | ||||||
|  | #include "wm.h" | ||||||
|  | 
 | ||||||
|  | Display *dpy; | ||||||
|  | Window root; | ||||||
|  | XRectangle rect; | ||||||
|  | int screen, sel_screen; | ||||||
|  | Atom wm_atom[WMLast]; | ||||||
|  | Atom net_atom[NetLast]; | ||||||
|  | Cursor cursor[CurLast]; | ||||||
|  | unsigned int kmask, numlock_mask; | ||||||
|  | Pixmap pmap; | ||||||
|  | 
 | ||||||
|  | enum { WM_PROTOCOL_DELWIN = 1 }; | ||||||
|  | 
 | ||||||
|  | static Bool other_wm_running; | ||||||
|  | static int (*x_error_handler) (Display *, XErrorEvent *); | ||||||
|  | static char version[] = "gridwm - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n"; | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | usage() | ||||||
|  | { | ||||||
|  | 	fputs("usage: gridwm [-v]\n", stderr); | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | error(char *errstr, ...) { | ||||||
|  | 	va_list ap; | ||||||
|  | 	va_start(ap, errstr); | ||||||
|  | 	vfprintf(stderr, errstr, ap); | ||||||
|  | 	va_end(ap); | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | scan_wins() | ||||||
|  | { | ||||||
|  | 	unsigned int i, num; | ||||||
|  | 	Window *wins; | ||||||
|  | 	XWindowAttributes wa; | ||||||
|  | 	Window d1, d2; | ||||||
|  | 
 | ||||||
|  | 	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*/; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if(wins) | ||||||
|  | 		XFree(wins); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | win_property(Window w, Atom a, Atom t, long l, unsigned char **prop) | ||||||
|  | { | ||||||
|  | 	Atom real; | ||||||
|  | 	int format; | ||||||
|  | 	unsigned long res, extra; | ||||||
|  | 	int status; | ||||||
|  | 
 | ||||||
|  | 	status = XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format, | ||||||
|  | 			&res, &extra, prop); | ||||||
|  | 
 | ||||||
|  | 	if(status != Success || *prop == 0) { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	if(res == 0) { | ||||||
|  | 		free((void *) *prop); | ||||||
|  | 	} | ||||||
|  | 	return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | win_proto(Window w) | ||||||
|  | { | ||||||
|  | 	Atom *protocols; | ||||||
|  | 	long res; | ||||||
|  | 	int protos = 0; | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	res = win_property(w, wm_atom[WMProtocols], XA_ATOM, 20L, | ||||||
|  | 			((unsigned char **) &protocols)); | ||||||
|  | 	if(res <= 0) { | ||||||
|  | 		return protos; | ||||||
|  | 	} | ||||||
|  | 	for(i = 0; i < res; i++) { | ||||||
|  | 		if(protocols[i] == wm_atom[WMDelete]) | ||||||
|  | 			protos |= WM_PROTOCOL_DELWIN; | ||||||
|  | 	} | ||||||
|  | 	free((char *) protocols); | ||||||
|  | 	return protos; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * There's no way to check accesses to destroyed windows, thus | ||||||
|  |  * those cases are ignored (especially on UnmapNotify's). | ||||||
|  |  * Other types of errors call Xlib's default error handler, which | ||||||
|  |  * calls exit(). | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | error_handler(Display *dpy, XErrorEvent *error) | ||||||
|  | { | ||||||
|  | 	if(error->error_code == BadWindow | ||||||
|  | 			|| (error->request_code == X_SetInputFocus | ||||||
|  | 				&& error->error_code == BadMatch) | ||||||
|  | 			|| (error->request_code == X_PolyText8 | ||||||
|  | 				&& error->error_code == BadDrawable) | ||||||
|  | 			|| (error->request_code == X_PolyFillRectangle | ||||||
|  | 				&& error->error_code == BadDrawable) | ||||||
|  | 			|| (error->request_code == X_PolySegment | ||||||
|  | 				&& error->error_code == BadDrawable) | ||||||
|  | 			|| (error->request_code == X_ConfigureWindow | ||||||
|  | 				&& error->error_code == BadMatch) | ||||||
|  | 			|| (error->request_code == X_GrabKey | ||||||
|  | 				&& error->error_code == BadAccess)) | ||||||
|  | 		return 0; | ||||||
|  | 	fprintf(stderr, "gridwm: fatal error: request code=%d, error code=%d\n", | ||||||
|  | 			error->request_code, error->error_code); | ||||||
|  | 	return x_error_handler(dpy, error); /* may call exit() */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Startup Error handler to check if another window manager | ||||||
|  |  * is already running. | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | startup_error_handler(Display *dpy, XErrorEvent *error) | ||||||
|  | { | ||||||
|  | 	other_wm_running = True; | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | init_lock_keys() | ||||||
|  | { | ||||||
|  | 	XModifierKeymap *modmap; | ||||||
|  | 	KeyCode numlock; | ||||||
|  | 	int i; | ||||||
|  | 	static int masks[] = { | ||||||
|  | 		ShiftMask, LockMask, ControlMask, Mod1Mask, | ||||||
|  | 		Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	numlock_mask = 0; | ||||||
|  | 	modmap = XGetModifierMapping(dpy); | ||||||
|  | 	numlock = XKeysymToKeycode(dpy, XStringToKeysym("Num_Lock")); | ||||||
|  | 
 | ||||||
|  | 	if(modmap && modmap->max_keypermod > 0) { | ||||||
|  | 		int max = (sizeof(masks) / sizeof(int)) * modmap->max_keypermod; | ||||||
|  | 		for(i = 0; i < max; i++) | ||||||
|  | 			if(numlock && (modmap->modifiermap[i] == numlock)) | ||||||
|  | 				numlock_mask = masks[i / modmap->max_keypermod]; | ||||||
|  | 	} | ||||||
|  | 	XFreeModifiermap(modmap); | ||||||
|  | 
 | ||||||
|  | 	kmask = 255 & ~(numlock_mask | LockMask); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | cleanup() | ||||||
|  | { | ||||||
|  | 	/*
 | ||||||
|  | 	Client *c; | ||||||
|  | 	for(c=client; c; c=c->next) | ||||||
|  | 		reparent_client(c, root, c->sel->rect.x, c->sel->rect.y); | ||||||
|  | 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); | ||||||
|  | 	*/ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | main(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	XSetWindowAttributes wa; | ||||||
|  | 	unsigned int mask; | ||||||
|  | 	Window w; | ||||||
|  | 
 | ||||||
|  | 	/* command line args */ | ||||||
|  | 	for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) { | ||||||
|  | 		switch (argv[i][1]) { | ||||||
|  | 		case 'v': | ||||||
|  | 			fprintf(stdout, "%s", version); | ||||||
|  | 			exit(0); | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			usage(); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	dpy = XOpenDisplay(0); | ||||||
|  | 	if(!dpy) | ||||||
|  | 		error("gridwm: cannot connect X server\n"); | ||||||
|  | 
 | ||||||
|  | 	screen = DefaultScreen(dpy); | ||||||
|  | 	root = RootWindow(dpy, screen); | ||||||
|  | 
 | ||||||
|  | 	/* check if another WM is already running */ | ||||||
|  | 	other_wm_running = False; | ||||||
|  | 	XSetErrorHandler(startup_error_handler); | ||||||
|  | 	/* this causes an error if some other WM is running */ | ||||||
|  | 	XSelectInput(dpy, root, SubstructureRedirectMask); | ||||||
|  | 	XSync(dpy, False); | ||||||
|  | 
 | ||||||
|  | 	if(other_wm_running) | ||||||
|  | 		error("gridwm: another window manager is already running\n"); | ||||||
|  | 
 | ||||||
|  | 	rect.x = rect.y = 0; | ||||||
|  | 	rect.width = DisplayWidth(dpy, screen); | ||||||
|  | 	rect.height = DisplayHeight(dpy, screen); | ||||||
|  | 	sel_screen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); | ||||||
|  | 
 | ||||||
|  | 	XSetErrorHandler(0); | ||||||
|  | 	x_error_handler = XSetErrorHandler(error_handler); | ||||||
|  | 
 | ||||||
|  | 	/* init atoms */ | ||||||
|  | 	wm_atom[WMState] = XInternAtom(dpy, "WM_STATE", False); | ||||||
|  | 	wm_atom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); | ||||||
|  | 	wm_atom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); | ||||||
|  | 	net_atom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); | ||||||
|  | 	net_atom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); | ||||||
|  | 
 | ||||||
|  | 	XChangeProperty(dpy, root, net_atom[NetSupported], XA_ATOM, 32, | ||||||
|  | 			PropModeReplace, (unsigned char *) net_atom, NetLast); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	/* init cursors */ | ||||||
|  | 	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); | ||||||
|  | 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); | ||||||
|  | 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); | ||||||
|  | 
 | ||||||
|  | 	init_lock_keys(); | ||||||
|  | 
 | ||||||
|  | 	pmap = XCreatePixmap(dpy, root, rect.width, rect.height, | ||||||
|  | 			DefaultDepth(dpy, screen)); | ||||||
|  | 
 | ||||||
|  | 	wa.event_mask = SubstructureRedirectMask | EnterWindowMask | LeaveWindowMask; | ||||||
|  | 	wa.cursor = cursor[CurNormal]; | ||||||
|  | 	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); | ||||||
|  | 
 | ||||||
|  | 	scan_wins(); | ||||||
|  | 
 | ||||||
|  | 	cleanup(); | ||||||
|  | 	XCloseDisplay(dpy); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										57
									
								
								wm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								wm.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | |||||||
|  | /*
 | ||||||
|  |  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> | ||||||
|  |  * See LICENSE file for license details. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <X11/Xlib.h> | ||||||
|  | #include <X11/Xutil.h> | ||||||
|  | 
 | ||||||
|  | /* WM atoms */ | ||||||
|  | enum { WMState, WMProtocols, WMDelete, WMLast }; | ||||||
|  | 
 | ||||||
|  | /* NET atoms */ | ||||||
|  | enum { NetSupported, NetWMName, NetLast }; | ||||||
|  | 
 | ||||||
|  | /* Cursor */ | ||||||
|  | enum { CurNormal, CurResize, CurMove, CurInput, CurLast }; | ||||||
|  | 
 | ||||||
|  | /* Rects */ | ||||||
|  | enum { RFloat, RGrid, RLast }; | ||||||
|  | 
 | ||||||
|  | typedef struct Client Client; | ||||||
|  | typedef struct Tag Tag; | ||||||
|  | 
 | ||||||
|  | struct Client { | ||||||
|  | 	Tag *tag; | ||||||
|  | 	char name[256]; | ||||||
|  | 	int proto; | ||||||
|  | 	Window win; | ||||||
|  | 	Window trans; | ||||||
|  | 	Window title; | ||||||
|  | 	GC gc; | ||||||
|  | 	XSizeHints size; | ||||||
|  | 	XRectangle r[RLast]; | ||||||
|  | 	Client *next; | ||||||
|  | 	Client *tnext; | ||||||
|  | 	Client *tprev; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct Tag { | ||||||
|  | 	char name[256]; | ||||||
|  | 	Client *clients; | ||||||
|  | 	Client *sel; | ||||||
|  | 	XRectangle r; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | extern Display *dpy; | ||||||
|  | extern Window root; | ||||||
|  | extern XRectangle rect; | ||||||
|  | extern int screen, sel_screen; | ||||||
|  | extern unsigned int kmask, numlock_mask; | ||||||
|  | extern Atom wm_atom[WMLast]; | ||||||
|  | extern Atom net_atom[NetLast]; | ||||||
|  | extern Cursor cursor[CurLast]; | ||||||
|  | extern Pixmap pmap; | ||||||
|  | 
 | ||||||
|  | /* wm.c */ | ||||||
|  | extern void error(char *errstr, ...); | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Anselm R. Garbe
						Anselm R. Garbe