You are not logged in.
Raziel23 wrote:because it change the toggleview behaviour and thus it will not be include to the official code.
Isn't a patch supposed to change behaviour? In any case, it's always worth a shot - especially if other people find it usefull too.
In my opinion, the patch accentuates the "tags != workspaces" behavior the DWM developers encourage. It changes the way master windows are handled in a reasonable way: If I'm calling a client from another tag, there's a good chance I want it to be in focus. The "nmaster" patch also changed the way the master area is handled, and that got merged into the main code, but is just switched off by default. So there's a chance it could get merged. Like Unia says, even if it doesn't get merged, it's still worth it to put the patch out there for other DWM fans.
Offline
@jasonwryan: @Unia: @ANOKNUSA: Thank you for your feedback. You have encouraged me that I should send this patch to the mailing list. You are right that even if it will not be included to the main code, then more people will see it and maybe find it useful.
Offline
Hey guys.
I think I need some help here.
I'm using dwm 6.0 and want to display the statusbar on both of my two monitors with no respect for the focus. I applied the statusmon patch from [1] with one exception: Instead of having
drawtext(stext, dc.norm, False);
I use
drawcoloredtext(stext);
because of [2]:
@@ -753,19 +753,19 @@ drawbar(Monitor *m) {
dc.x = x;
dc.w = m->ww - x;
}
- drawtext(stext, dc.norm, False);
+ drawcoloredtext(stext);
= = =
Problem:
On monitor 2, the statusbar is visible the whole time. On monitor 1 the statusbar is only visible if the monitor got the focus.
I didn't find any solution, maybe you can help me out with that?
(FYI: I also applied 01-focusonclick, 02-moveresize, 03-save_floats, 04-uselessgaps, 05-statuscolors)
Edit: my diff from the statusallmons patch
$ cat patches/06-dwm-6.0-statusallmons.diff
diff --git a/dwm.c b/dwm.c
index 914fb2e..0dbfe87 100644
--- a/dwm.c
+++ b/dwm.c
@@ -736,17 +736,13 @@ drawbar(Monitor *m) {
drawtext(m->ltsymbol, dc.colors[0], True);
dc.x += dc.w;
x = dc.x;
- if(m == selmon) { /* status is only drawn on selected monitor */
- dc.w = TEXTW(stext);
- dc.x = m->ww - dc.w;
- if(dc.x < x) {
- dc.x = x;
- dc.w = m->ww - x;
- }
- drawcoloredtext(stext);
+ dc.w = TEXTW(stext);
+ dc.x = m->ww - dc.w;
+ if(dc.x < x) {
+ dc.x = x;
+ dc.w = m->ww - x;
}
- else
- dc.x = m->ww;
+ drawcoloredtext(stext);
if((dc.w = dc.x - x) > bh) {
dc.x = x;
if(m->sel) {
@@ -2079,9 +2075,11 @@ updatetitle(Client *c) {
void
updatestatus(void) {
+ Monitor *m;
if(!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION);
- drawbar(selmon);
+ for(m = mons; m; m = m->next)
+ drawbar(m);
}
void
- - -
[1]: http://dwm.suckless.org/patches/dwm-6.0 … lmons.diff
[2]: http://dwm.suckless.org/patches/dwm-5.9 … olors.diff
Last edited by gridcol (2013-05-25 18:56:28)
Offline
Offline
I do not see any problem in statusallmons patch. And when compiling everything is fine?
Thank you for your reply. Everything is fine, no warnings or anything else.
I really don't get it, why the patch works fine for monitor 2 and my primary monitor still needs focus to display the status bar.
Last edited by gridcol (2013-05-25 21:07:56)
Offline
Ah.. silly me.
I used conky in the status bar and this caused the unwanted effect. Without conky (just the "dwm-..."), the status bar is on both monitors. I still have to figure out how to do the trick with conky, but I'll try this on my own first.
Thanks for your time
Edit:
Figured it out by reading this thread.
Changing
dc.w = selmon->ww - dc.x;
to
dc.w = mons->ww - dc.x;
which came from the statuscolors patch[1], does the trick.
The statusbar is dispayed on all monitors, everytime, no matter which content.
Thanks to DrKillPatient from #797
[1] http://dwm.suckless.org/patches/dwm-5.9 … olors.diff
Last edited by gridcol (2013-05-25 21:40:11)
Offline
I decided I wanted fonts that looked similar to those I have in my other applications (thus, similar to GTK). I looked into the Pango patch that's floating around the internet but it's an ugly implementation: there's a mixture of "normal" X colors and XftColors and getcolor() is completely messed up imo.
On my GitHub, you can find a Pango patch that is cleaner. It's functionally no different from the original, though. https://github.com/Unia/DWM/blob/master … pango.diff
I'm however failing to get statuscolors to work nice. It applies, and I do have the colors in the statusbar, but the alignment is off and various elements overlap. I've been looking at it for the past two days but so far I haven't managed to get it to work. I would appreciate it if someone could take a look at it: https://github.com/Unia/DWM/blob/master … olors.diff
Cheers!
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
Unia, you replaced TEXTW with textnw on lines 52/53. Look at the definition of TEXTW on line 56 (of a clean dwm 6.0). That's most likely why your alignment is off.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Unia, you replaced TEXTW with textnw on lines 52/53. Look at the definition of TEXTW on line 56 (of a clean dwm 6.0). That's most likely why your alignment is off.
Nope, it's not. This is default statuscolors behaviour to prevent gaps. In other words, this behaviour worked fine on my XFT patched DWM and also on regular DWM. (ofcourse, I tested this to be sure and it's indeed not the cause)
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
I remember that I had the same problem with pango-patch and statuscolors, until I found
this patch from @firecat53 Pango working with statuscolors and statuscolors with pango
Cheers
Offline
I remember that I had the same problem with pango-patch and statuscolors, until I found
this patch from @firecat53 Pango working with statuscolors and statuscolors with pangoCheers
Thanks, that brings me closer already. Now there's a new issue that I again can not seem to solve: the bar on the right is cut off. See this screenshot:
EDIT: The only difference in my Pango patch and Firecat's is that I solely use XftColors instead of a mixture between "normal" XColors and XftColors. Other than that, the patches are identical. I don't think the issue is in there though, since on my previous setup which was XFT, statuscolors worked too. I already tried changing the new drawcoloredtext() function, but none of my changes work (it's been too many to remember what exactly I have tried).
Here's the patch I'm currently using:
--- dwm.c.orig 2013-05-30 19:30:19.870598469 +0200
+++ dwm.c 2013-05-30 20:45:55.990493906 +0200
@@ -51,6 +51,7 @@
* MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
#define LENGTH(X) (sizeof X / sizeof X[0])
+#define MAXCOLORS 9
#ifndef MAX
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#endif
@@ -107,8 +108,7 @@ struct Client {
typedef struct {
int x, y, w, h;
- XftColor norm[ColLast];
- XftColor sel[ColLast];
+ XftColor colors[MAXCOLORS][ColLast];
Drawable drawable;
GC gc;
PangoContext *pgc;
@@ -198,8 +198,9 @@ static void die(const char *errstr, ...)
static Monitor *dirtomon(int dir);
static void drawbar(Monitor *m);
static void drawbars(void);
-static void drawsquare(Bool filled, Bool empty, Bool invert, XftColor col[ColLast]);
-static void drawtext(const char *text, XftColor col[ColLast], Bool invert);
+static void drawcoloredtext(char *text);
+static void drawsquare(Bool filled, Bool empty, XftColor col[ColLast]);
+static void drawtext(const char *text, XftColor col[ColLast], Bool pad);
static void enternotify(XEvent *e);
static void expose(XEvent *e);
static void focus(Client *c);
@@ -789,14 +790,13 @@ drawbar(Monitor *m) {
dc.x = 0;
for(i = 0; i < LENGTH(tags); i++) {
dc.w = TEXTW(tags[i].name);
- col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm;
- drawtext(tags[i].name, col, urg & 1 << i);
- drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
- occ & 1 << i, urg & 1 << i, col);
+ col = dc.colors[(m->tagset[m->seltags] & 1 << i) ? 1 : (urg & 1 << i ? 2:0)];
+ drawtext(tags[i].name, col, True);
+ drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, occ & 1 << i, col);
dc.x += dc.w;
}
dc.w = blw = TEXTW(m->ltsymbol);
- drawtext(m->ltsymbol, dc.norm, False);
+ drawtext(m->ltsymbol, dc.colors[0], True);
dc.x += dc.w;
x = dc.x;
if(m == selmon) { /* status is only drawn on selected monitor */
@@ -806,19 +806,19 @@ drawbar(Monitor *m) {
dc.x = x;
dc.w = m->ww - x;
}
- drawtext(stext, dc.norm, False);
+ drawcoloredtext(stext);
}
else
dc.x = m->ww;
if((dc.w = dc.x - x) > bh) {
dc.x = x;
if(m->sel) {
- col = m == selmon ? dc.sel : dc.norm;
- drawtext(m->sel->name, col, False);
- drawsquare(m->sel->isfixed, m->sel->isfloating, False, col);
+ col = dc.colors[m == selmon ? 1 : 0];
+ drawtext(m->sel->name, col, True);
+ drawsquare(m->sel->isfixed, m->sel->isfloating, col);
}
else
- drawtext(NULL, dc.norm, False);
+ drawtext(NULL, dc.colors[0], False);
}
XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0);
XSync(dpy, False);
@@ -833,10 +833,43 @@ drawbars(void) {
}
void
-drawsquare(Bool filled, Bool empty, Bool invert, XftColor col[ColLast]) {
+drawcoloredtext(char *text) {
+ Bool first = True;
+ char *buf = text, *ptr = buf, c = 1;
+ XftColor *col = dc.colors[0];
+ int i, ox = dc.x;
+
+ while(*ptr) {
+ for(i = 0; *ptr < 0 || *ptr > NUMCOLORS; i++, ptr++)
+ if(!*ptr)
+ break;
+ c = *ptr;
+ *ptr = 0;
+ if(i) {
+ dc.w = selmon->ww - dc.x;
+ drawtext(buf, col, True);
+ dc.x += textnw(buf, i) + textnw(&c , 1);
+ if(first)
+ dc.x += (dc.font.ascent + dc.font.descent) / 2;
+ first = False;
+ }
+ else if(first)
+ ox = dc.x += textnw(&c, 1);
+ *ptr = c;
+ col = dc.colors[c - 1];
+ buf = ++ptr;
+ }
+ if(!first)
+ dc.x -= (dc.font.ascent + dc.font.descent) / 2;
+ drawtext(buf, col, True);
+ dc.x = ox;
+}
+
+void
+drawsquare(Bool filled, Bool empty, XftColor col[ColLast]) {
int x;
- XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG].pixel);
+ XSetForeground(dpy, dc.gc, col[ColFG].pixel);
x = (dc.font.ascent + dc.font.descent + 2) / 4;
if(filled)
XFillRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x+1, x+1);
@@ -845,17 +878,17 @@ drawsquare(Bool filled, Bool empty, Bool
}
void
-drawtext(const char *text, XftColor col[ColLast], Bool invert) {
+drawtext(const char *text, XftColor col[ColLast], Bool pad) {
char buf[256];
int i, x, y, h, len, olen;
XftDraw *d;
- XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG].pixel);
+ XSetForeground(dpy, dc.gc, col[ColBG].pixel);
XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h);
if(!text)
return;
olen = strlen(text);
- h = dc.font.ascent + dc.font.descent;
+ h = pad ? (dc.font.ascent + dc.font.descent) : 0;
y = dc.y + (dc.h / 2) - (h / 2);
x = dc.x + (h / 2);
/* shorten text if necessary */
@@ -869,7 +902,7 @@ drawtext(const char *text, XftColor col[
d = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen));
pango_layout_set_text(dc.plo, text, len);
- pango_xft_render_layout(d, (col==dc.norm?dc.norm:dc.sel)+(invert?ColBG:ColFG), dc.plo, x * PANGO_SCALE, y * PANGO_SCALE);
+ pango_xft_render_layout(d, (XftColor *)&col[ColFG].pixel, dc.plo, x * PANGO_SCALE, y * PANGO_SCALE);
}
void
@@ -915,7 +948,7 @@ focus(Client *c) {
detachstack(c);
attachstack(c);
grabbuttons(c, True);
- XSetWindowBorder(dpy, c->win, dc.sel[ColBorder].pixel);
+ XSetWindowBorder(dpy, c->win, dc.colors[1][ColBorder].pixel);
setfocus(c);
}
else
@@ -1188,7 +1221,7 @@ manage(Window w, XWindowAttributes *wa)
wc.border_width = c->bw;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
- XSetWindowBorder(dpy, w, dc.norm[ColBorder].pixel);
+ XSetWindowBorder(dpy, w, dc.colors[0][ColBorder].pixel);
configure(c); /* propagates border_width, if size doesn't change */
updatewindowtype(c);
updatesizehints(c);
@@ -1656,12 +1689,11 @@ setup(void) {
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
/* init appearance */
- dc.norm[ColBorder] = getcolor(normbordercolor);
- dc.norm[ColBG] = getcolor(normbgcolor);
- dc.norm[ColFG] = getcolor(normfgcolor);
- dc.sel[ColBorder] = getcolor(selbordercolor);
- dc.sel[ColBG] = getcolor(selbgcolor);
- dc.sel[ColFG] = getcolor(selfgcolor);
+ for(int i = 0; i < NUMCOLORS; i++) {
+ dc.colors[i][ColBorder] = getcolor(colors[i][ColBorder]);
+ dc.colors[i][ColFG] = getcolor(colors[i][ColFG]);
+ dc.colors[i][ColBG] = getcolor(colors[i][ColBG]);
+ }
dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, NULL);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
@@ -1827,7 +1859,7 @@ unfocus(Client *c, Bool setfocus) {
if(!c)
return;
grabbuttons(c, False);
- XSetWindowBorder(dpy, c->win, dc.norm[ColBorder].pixel);
+ XSetWindowBorder(dpy, c->win, dc.colors[0][ColBorder].pixel);
if(setfocus)
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
}
Last edited by Unia (2013-05-30 23:24:33)
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
When I use Firecat's patches everything works as expected, so something must be off with my patches. When I compare mine with his, I don't see any big differences though. Could someone else give it a shot?
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
I ditched statuscolors in favor of Pango's builtin markups. I can use <span foreground=\"red\">This text is red</span> to colorize my statusbar. This also enables me to use italics, for example.
EDIT4: Fixed, nevermind.
Last edited by Unia (2013-06-01 22:33:26)
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
emacs always cannot be at right coordinates in DWM .
In config.h, there is
static const char *emacs[] = {"emacs", "--geometry", "177x38+0+378", NULL };
{ MODKEY, XK_e, spawn, {.v = emacs } }
The layout is:
{ "><>", NULL }
The --geometry is functional however the emacs always shrinks after started which leaving an offset to screen bottom.
Regards!
e^(π⋅i) + 1 = 0
Offline
Don't do this. You have a standalone thread already, spamming the dwm threads is just rude.
Offline
For some reason (although the tiling method works) this layout that I have been working on causes DWM to crash when switching to an empty tag view.
What am I doing wrong?
--- a/dwm.c
+++ b/dwm.c
@@ -267,6 +267,7 @@ static void spawn(const Arg *arg);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static int textnw(const char *text, unsigned int len);
+static void tcl(Monitor *);
static void tile(Monitor *);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
@@ -2003,6 +2004,72 @@ textnw(const char *text, unsigned int len) {
}
void
+tcl(Monitor * m)
+{
+ int x, y, h, w, mw, sw, bdw;
+ unsigned int i, n;
+ Client * c;
+
+ for (n = 0, c = nexttiled(m->clients); c;
+ c = nexttiled(c->next), n++);
+
+ c = nexttiled(m->clients);
+ mw = m->mfacts[m->curtag] * m->ww;
+ sw = (m->ww - mw) / 2;
+ bdw = (2 * c->bw);
+ resize(c, n < 3 ? m->wx : m->wx + sw - bdw, m->wy, n == 1 ? m->ww : mw - bdw, m->wh - bdw, False);
+
+ if (--n == 0)
+ {
+ return;
+ }
+
+ w = (m->ww - mw) / ((n > 1) + 1);
+ c = nexttiled(c->next);
+
+ if (n > 1)
+ {
+ x = m->wx + ((n > 1) ? mw + sw - (2 * bdw) : mw);
+ y = m->wy;
+ h = m->wh / (n / 2);
+
+ if (h < bh)
+ {
+ h = m->wh;
+ }
+
+ for (i = 0; c && i < n / 2; c = nexttiled(c->next), i++)
+ {
+ resize(c, x - bdw, y, w + (2 * bdw), (i + 1 == n / 2) ? m->wy + m->wh - y - bdw : h - bdw, False);
+
+ if (h != m->wh)
+ {
+ y = c->y + HEIGHT(c);
+ }
+ }
+ }
+
+ x = (n + 1 / 2) == 1 ? mw - bdw : m->wx;
+ y = m->wy;
+ h = m->wh / ((n + 1) / 2);
+
+ if (h < bh)
+ {
+ h = m->wh;
+ }
+
+ for (i = 0; c; c = nexttiled(c->next), i++)
+ {
+ resize(c, (i + 1 == (n + 1) / 2) ? x - bdw : x, y, (i + 1 == (n + 1) / 2) ? w + bdw : w, (i + 1 == (n + 1) / 2) ? m->wy + m->wh - y - bdw : h - bdw, False);
+
+ if (h != m->wh)
+ {
+ y = c->y + HEIGHT(c);
+ }
+ }
+}
+
+void
tile(Monitor *m) {
Client *c;
int x, y, h, w, mw;
Last edited by ctruett (2013-06-16 09:52:46)
Supergirl: But fortunately I printed out everything I could find, not just the beginner's guide.
Supergirl: I printed out internet.
Offline
I didn't try it but in your tcl method you do the following:
c = nexttiled(m->clients);
mw = m->mfacts[m->curtag] * m->ww;
sw = (m->ww - mw) / 2;
bdw = (2 * c->bw);
If there are no clients present on the tag c will be NULL, resulting in a NULL pointer exception. That is only a guess, though.
Offline
What sort of layout is it? Care to elaborate more?
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
What sort of layout is it? Care to elaborate more?
Sure. Here is what I have been working on the past few days:
Two windows, looks like normal "tile" layout: http://imagebin.org/261544
...but open three or more and you get this one: imagebin.org/261545
...with five windows open: http://imagebin.org/261549
The center column (master) is resizable through the usual methods.
This is originally inspired by / based on a tcl.c someone posted on the mailing list.
Supergirl: But fortunately I printed out everything I could find, not just the beginner's guide.
Supergirl: I printed out internet.
Offline
Pretty sweet, especially if you have a bigger monitor! Have you solved your issues now? I think pks' solution solves it.
One last question, why does that bar move that you have in your statusbar and what is it for?
If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres
Offline
Nice layout indeed! Please upload it to the suckless wiki as soon as it works!
Offline
Ok, here is a working version. I also pushed an entry to the wiki about five minutes ago.
Save this file in the same dir as dwm.c, add
#include "tcl.h"
before your layouts in config.h and use
tcl
as the layout name.
If someone would give me some suggestions (or do it yourself and send me a pull request) on how I can fix "uselessgaps" functionality with this layout that would be great.
One last question, why does that bar move that you have in your statusbar and what is it for?
That is just a small floating terminal window that ran my screenshot script.
Last edited by ctruett (2013-06-17 07:00:29)
Supergirl: But fortunately I printed out everything I could find, not just the beginner's guide.
Supergirl: I printed out internet.
Offline
If someone would give me some suggestions (or do it yourself and send me a pull request) on how I can fix "uselessgaps" functionality with this layout that would be great.
Here is a diff of dwm.c for uselessgaps
--- ../../../.dwm-backup/src/dwm-6.0/dwm.c 2013-06-09 01:53:24.170389000 +0530
+++ dwm.c 2013-06-19 00:54:26.613981386 +0530
@@ -293,6 +293,7 @@ static Display *dpy;
static DC dc;
static Monitor *mons = NULL, *selmon = NULL;
static Window root;
+static int globalborder;
/* configuration, allows nested code to access above variables */
#include "config.h"
@@ -1425,11 +1426,18 @@ resize(Client *c, int x, int y, int w, i
void
resizeclient(Client *c, int x, int y, int w, int h) {
XWindowChanges wc;
+
+ if(c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) { globalborder = 0 ; }
+ else {
+ if (selmon->lt[selmon->sellt]->arrange == monocle) { globalborder = 0 - borderpx ; }
+ else { globalborder = gappx ; }
+ }
+
- c->oldx = c->x; c->x = wc.x = x;
- c->oldy = c->y; c->y = wc.y = y;
- c->oldw = c->w; c->w = wc.width = w;
- c->oldh = c->h; c->h = wc.height = h;
+ c->oldx = c->x; c->x = wc.x = x + globalborder ;
+ c->oldy = c->y; c->y = wc.y = y + globalborder ;
+ c->oldw = c->w; c->w = wc.width = w - 2 * globalborder ;
+ c->oldh = c->h; c->h = wc.height = h - 2 * globalborder ;
wc.border_width = c->mon->lt[c->mon->sellt]->arrange == monocle && !c->isfloating ? 0 : c->bw;
if(selmon->wx == c->x && selmon->wy == c->y && selmon->ww - 2 * c->bw == c->w && selmon->wh - 2 * c->bw == c->h && !c->isfloating && !c->isfullscreen) {
wc.border_width = 0;
Add globalborder to HEIGHT calculation in every layout. In this case
tcl.h
...
...
if (h != m->wh)
y = c->y + HEIGHT(c) + 2 * globalborder;
...
...
Define gappx in config.h
static const unsigned int gappx = 3;
Never argue with stupid people,They will drag you down to their level and then beat you with experience.--Mark Twain
@github
Offline
Hey thanks! I'm noticing that there is some inconsistency in spacing when using my layout with gaps: the vertical spacing between windows on the right side seems to be larger than it should be. If anyone else notices this, let me know! I could just be imagining things.
Supergirl: But fortunately I printed out everything I could find, not just the beginner's guide.
Supergirl: I printed out internet.
Offline