|
|
add horizontal and monocle layout and rework/cleanup drawing logic - sfeed_curses - sfeed curses UI (now part of sfeed, development is in sfeed) |
|
|
 |
git clone git://git.codemadness.org/sfeed_curses (git://git.codemadness.org) |
|
|
 |
Log |
|
|
 |
Files |
|
|
 |
Refs |
|
|
 |
README |
|
|
 |
LICENSE |
|
|
|
--- |
|
|
 |
commit 83f15d40dff4c353efba704e7c51f05e077179d2 |
|
|
 |
parent 18bd36ede3a9d2ea2f8dbad50a3ce0858d272584 |
|
|
 |
Author: Hiltjo Posthuma <hiltjo@codemadness.org> (mailto://) |
application/vnd.lotus-organizer |
|
|
Date: Wed, 10 Mar 2021 17:22:05 +0100 |
|
|
|
|
|
|
|
add horizontal and monocle layout and rework/cleanup drawing logic |
|
|
|
|
|
|
|
- Add the layouts horizontal and monocle. |
|
|
|
|
|
|
|
- The monocle layout replaces the mode of hiding the sidebar using 's'. This |
|
|
|
's' keybind now toggles between a monocle and non-monocle layout (vertical or |
|
|
|
horizontal). When a feed is read from stdin (no filenames) then the default |
|
|
|
layout will now be monocle also. |
|
|
|
|
|
|
|
- The monocle layout also works nicely on smaller portable screens (such as a |
|
|
|
Motorola Droid4) or on smaller terminals or if a more newsboat-like style is |
|
|
|
wanted. |
|
|
|
|
|
|
|
- Layouts can be changed with the keybinds '1', '2', '3', a preference can also |
|
|
|
be set at startup using the recently added SFEED_AUTOCMD feature, like so: |
|
|
|
SFEED_AUTOCMD=2 sfeed_curses. |
|
|
|
|
|
|
|
Diffstat: |
|
|
|
M sfeed_curses.1 | 22 +++++++++++++++++----- |
|
|
|
M sfeed_curses.c | 273 ++++++++++++++++++++++--------- |
|
|
|
M themes/mono.h | 1 + |
|
|
|
M themes/newsboat.h | 1 + |
|
|
|
M themes/templeos.h | 5 +++++ |
|
|
|
|
|
|
|
5 files changed, 222 insertions(+), 80 deletions(-) |
|
|
|
--- |
|
|
 |
diff --git a/sfeed_curses.1 b/sfeed_curses.1 |
|
|
|
@@ -1,4 +1,4 @@ |
|
|
|
-.Dd February 20, 2021 |
|
|
|
+.Dd March 10, 2021 |
|
|
|
.Dt SFEED_CURSES 1 |
|
|
|
.Os |
|
|
|
.Sh NAME |
|
|
|
@@ -78,13 +78,16 @@ Reload all feed files which were specified as arguments on startup. |
|
|
|
.It m |
|
|
|
Toggle mouse-mode. |
|
|
|
.It s |
|
|
|
-Toggle showing the feeds pane sidebar. |
|
|
|
+Toggle between monocle layout and the previous non-monocle layout. |
|
|
|
.It < |
|
|
|
-Use fixed sidebar width and decrease fixed width by 1 column. |
|
|
|
+Use a fixed sidebar size for the current layout and decrease the fixed width or |
|
|
|
+height by 1 column. |
|
|
|
.It > |
|
|
|
-Use fixed sidebar width and increase fixed width by 1 column. |
|
|
|
+Use a fixed sidebar size for the current layout and increase the fixed width or |
|
|
|
+height by 1 column. |
|
|
|
.It = |
|
|
|
-Reset sidebar width to automatic adjustment. |
|
|
|
+Reset the sidebar width or height to automatic adjustment for the current |
|
|
|
+layout. |
|
|
|
.It t |
|
|
|
Toggle showing only feeds with new items in the sidebar. |
|
|
|
.It a, e, @ |
|
|
|
@@ -128,6 +131,15 @@ Mark all items of the current loaded feed as unread. |
|
|
|
This will only work when |
|
|
|
.Ev SFEED_URL_FILE |
|
|
|
is set. |
|
|
|
+.It 1 |
|
|
|
+Set the current layout to a vertical mode. Showing a feeds sidebar to the left |
|
|
|
+and the feed items to the right. |
|
|
|
+.It 2 |
|
|
|
+Set the current layout to a horizontal mode. Showing a feeds sidebar on the top |
|
|
|
+and the feed items on the bottom. |
|
|
|
+.It 3 |
|
|
|
+Set the current layout to a monocle mode. Showing only one feeds or an feed |
|
|
|
+items pane at once. |
|
|
|
.It q, EOF |
|
|
|
Quit |
|
|
|
.El |
|
|
 |
diff --git a/sfeed_curses.c b/sfeed_curses.c |
|
|
|
@@ -25,12 +25,14 @@ |
|
|
|
#include "minicurses.h" |
|
|
|
#endif |
|
|
|
|
|
|
|
-#define LEN(a) sizeof((a))/sizeof((a)[0]) |
|
|
|
+#define LEN(a) sizeof((a))/sizeof((a)[0]) |
|
|
|
#define MAX(a,b) ((a) > (b) ? (a) : (b)) |
|
|
|
|
|
|
|
#define PAD_TRUNCATE_SYMBOL "\xe2\x80\xa6" /* symbol: "ellipsis" */ |
|
|
|
#define SCROLLBAR_SYMBOL_BAR "\xe2\x94\x82" /* symbol: "light vertical" */ |
|
|
|
#define SCROLLBAR_SYMBOL_TICK " " |
|
|
|
+#define LINEBAR_SYMBOL_BAR "\xe2\x94\x80" /* symbol: "light horizontal" */ |
|
|
|
+#define LINEBAR_SYMBOL_RIGHT "\xe2\x94\xa4" /* symbol: "light vertical and left" */ |
|
|
|
#define UTF_INVALID_SYMBOL "\xef\xbf\xbd" /* symbol: "replacement" */ |
|
|
|
|
|
|
|
/* color-theme */ |
|
|
|
@@ -43,6 +45,10 @@ enum { |
|
|
|
ATTR_RESET = 0, ATTR_BOLD_ON = 1, ATTR_FAINT_ON = 2, ATTR_REVERSE_ON = 7 |
|
|
|
}; |
|
|
|
|
|
|
|
+enum Layout { |
|
|
|
+ LayoutVertical = 0, LayoutHorizontal, LayoutMonocle, LayoutLast |
|
|
|
+}; |
|
|
|
+ |
|
|
|
enum Pane { PaneFeeds, PaneItems, PaneLast }; |
|
|
|
|
|
|
|
enum { |
|
|
|
@@ -100,6 +106,14 @@ struct statusbar { |
|
|
|
int dirty; /* needs draw update */ |
|
|
|
}; |
|
|
|
|
|
|
|
+struct linebar { |
|
|
|
+ int x; /* absolute x position on the screen */ |
|
|
|
+ int y; /* absolute y position on the screen */ |
|
|
|
+ int width; /* absolute width of the line */ |
|
|
|
+ int hidden; /* is visible or not */ |
|
|
|
+ int dirty; /* needs draw update */ |
|
|
|
+}; |
|
|
|
+ |
|
|
|
/* /UI */ |
|
|
|
|
|
|
|
struct item { |
|
|
|
@@ -130,7 +144,7 @@ struct feed { |
|
|
|
void alldirty(void); |
|
|
|
void cleanup(void); |
|
|
|
void draw(void); |
|
|
|
-int getsidebarwidth(void); |
|
|
|
+int getsidebarsize(void); |
|
|
|
void markread(struct pane *, off_t, off_t, int); |
|
|
|
void pane_draw(struct pane *); |
|
|
|
void sighandler(int); |
|
|
|
@@ -140,12 +154,15 @@ void urls_free(void); |
|
|
|
int urls_isnew(const char *); |
|
|
|
void urls_read(void); |
|
|
|
|
|
|
|
+static struct linebar linebar; |
|
|
|
static struct statusbar statusbar; |
|
|
|
static struct pane panes[PaneLast]; |
|
|
|
static struct scrollbar scrollbars[PaneLast]; /* each pane has a scrollbar */ |
|
|
|
static struct win win; |
|
|
|
static size_t selpane; |
|
|
|
-static int fixedsidebarwidth = -1; /* fixed sidebar width, < 0 is automatic */ |
|
|
|
+/* fixed sidebar size, < 0 is automatic */ |
|
|
|
+static int fixedsidebarsizes[LayoutLast] = { -1, -1, -1 }; |
|
|
|
+static int layout = LayoutVertical, prevlayout = LayoutVertical; |
|
|
|
static int onlynew = 0; /* show only new in sidebar */ |
|
|
|
static int usemouse = 1; /* use xterm mouse tracking */ |
|
|
|
|
|
|
|
@@ -817,36 +834,75 @@ pane_draw(struct pane *p) |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
+setlayout(int n) |
|
|
|
+{ |
|
|
|
+ if (layout != LayoutMonocle) |
|
|
|
+ prevlayout = layout; /* previous non-monocle layout */ |
|
|
|
+ layout = n; |
|
|
|
+} |
|
|
|
+ |
|
|
|
+void |
|
|
|
updategeom(void) |
|
|
|
{ |
|
|
|
- int w, x; |
|
|
|
- |
|
|
|
- panes[PaneFeeds].width = getsidebarwidth(); |
|
|
|
- if (win.width && panes[PaneFeeds].width >= win.width) |
|
|
|
- panes[PaneFeeds].width = win.width - 1; |
|
|
|
- panes[PaneFeeds].x = 0; |
|
|
|
- panes[PaneFeeds].y = 0; |
|
|
|
- /* reserve space for statusbar */ |
|
|
|
- panes[PaneFeeds].height = MAX(win.height - 1, 1); |
|
|
|
- |
|
|
|
- /* NOTE: updatesidebar() must happen before this function for the |
|
|
|
- remaining width */ |
|
|
|
- if (!panes[PaneFeeds].hidden) { |
|
|
|
- w = win.width - panes[PaneFeeds].width; |
|
|
|
- x = panes[PaneFeeds].x + panes[PaneFeeds].width; |
|
|
|
+ int barsize, h, w, x = 0, y = 0; |
|
|
|
+ |
|
|
|
+ panes[PaneFeeds].hidden = layout == LayoutMonocle && (selpane != PaneFeeds); |
|
|
|
+ panes[PaneItems].hidden = layout == LayoutMonocle && (selpane != PaneItems); |
|
|
|
+ linebar.hidden = layout != LayoutHorizontal; |
|
|
|
+ |
|
|
|
+ w = win.width; |
|
|
|
+ /* always reserve space for statusbar */ |
|
|
|
+ h = MAX(win.height - 1, 1); |
|
|
|
+ |
|
|
|
+ panes[PaneFeeds].x = x; |
|
|
|
+ panes[PaneFeeds].y = y; |
|
|
|
+ |
|
|
|
+ switch (layout) { |
|
|
|
+ case LayoutVertical: |
|
|
|
+ /* NOTE: updatesidebar() must happen before this function for the |
|
|
|
+ remaining width */ |
|
|
|
+ barsize = getsidebarsize(); |
|
|
|
+ if (w && barsize >= w) |
|
|
|
+ barsize = w - 1; |
|
|
|
+ |
|
|
|
+ panes[PaneFeeds].width = MAX(barsize, 0); |
|
|
|
+ x += panes[PaneFeeds].width; |
|
|
|
+ w -= panes[PaneFeeds].width; |
|
|
|
+ |
|
|
|
/* space for scrollbar if sidebar is visible */ |
|
|
|
w--; |
|
|
|
x++; |
|
|
|
- } else { |
|
|
|
- w = win.width; |
|
|
|
- x = 0; |
|
|
|
+ |
|
|
|
+ panes[PaneFeeds].height = MAX(h, 1); |
|
|
|
+ break; |
|
|
|
+ case LayoutHorizontal: |
|
|
|
+ barsize = getsidebarsize(); |
|
|
|
+ if (h && barsize >= h / 2) |
|
|
|
+ barsize = h / 2; |
|
|
|
+ |
|
|
|
+ panes[PaneFeeds].height = MAX(barsize, 1); |
|
|
|
+ |
|
|
|
+ h -= panes[PaneFeeds].height; |
|
|
|
+ y += panes[PaneFeeds].height; |
|
|
|
+ |
|
|
|
+ linebar.x = 0; |
|
|
|
+ linebar.y = y; |
|
|
|
+ linebar.width = win.width; |
|
|
|
+ |
|
|
|
+ h -= 1; |
|
|
|
+ y += 1; |
|
|
|
+ panes[PaneFeeds].width = MAX(w - 1, 0); |
|
|
|
+ break; |
|
|
|
+ case LayoutMonocle: |
|
|
|
+ panes[PaneFeeds].height = MAX(h, 1); |
|
|
|
+ panes[PaneFeeds].width = MAX(w - 1, 0); |
|
|
|
+ break; |
|
|
|
} |
|
|
|
|
|
|
|
+ panes[PaneItems].width = MAX(w - 1, 0); |
|
|
|
+ panes[PaneItems].height = MAX(h, 1); |
|
|
|
panes[PaneItems].x = x; |
|
|
|
- panes[PaneItems].width = MAX(w - 1, 0); /* rest and space for scrollbar */ |
|
|
|
- panes[PaneItems].height = panes[PaneFeeds].height; |
|
|
|
- panes[PaneItems].y = panes[PaneFeeds].y; |
|
|
|
- panes[PaneItems].hidden = !panes[PaneItems].width || !panes[PaneItems].height; |
|
|
|
+ panes[PaneItems].y = y; |
|
|
|
|
|
|
|
scrollbars[PaneFeeds].x = panes[PaneFeeds].x + panes[PaneFeeds].width; |
|
|
|
scrollbars[PaneFeeds].y = panes[PaneFeeds].y; |
|
|
|
@@ -856,7 +912,7 @@ updategeom(void) |
|
|
|
scrollbars[PaneItems].x = panes[PaneItems].x + panes[PaneItems].width; |
|
|
|
scrollbars[PaneItems].y = panes[PaneItems].y; |
|
|
|
scrollbars[PaneItems].size = panes[PaneItems].height; |
|
|
|
- scrollbars[PaneItems].hidden = panes[PaneItems].hidden; |
|
|
|
+ scrollbars[PaneItems].hidden = panes[PaneItems].width ? 0 : 1; |
|
|
|
|
|
|
|
/* statusbar below */ |
|
|
|
statusbar.width = win.width; |
|
|
|
@@ -1046,6 +1102,27 @@ uiprompt(int x, int y, char *fmt, ...) |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
+linebar_draw(struct linebar *b) |
|
|
|
+{ |
|
|
|
+ int i; |
|
|
|
+ |
|
|
|
+ if (!b->dirty) |
|
|
|
+ return; |
|
|
|
+ b->dirty = 0; |
|
|
|
+ if (b->hidden || !b->width) |
|
|
|
+ return; |
|
|
|
+ |
|
|
|
+ cursorsave(); |
|
|
|
+ cursormove(b->x, b->y); |
|
|
|
+ THEME_LINEBAR(); |
|
|
|
+ for (i = 0; i < b->width - 1; i++) |
|
|
|
+ ttywrite(LINEBAR_SYMBOL_BAR); |
|
|
|
+ ttywrite(LINEBAR_SYMBOL_RIGHT); |
|
|
|
+ attrmode(ATTR_RESET); |
|
|
|
+ cursorrestore(); |
|
|
|
+} |
|
|
|
+ |
|
|
|
+void |
|
|
|
statusbar_draw(struct statusbar *s) |
|
|
|
{ |
|
|
|
if (!s->dirty) |
|
|
|
@@ -1338,29 +1415,40 @@ feeds_reloadall(void) |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
-getsidebarwidth(void) |
|
|
|
+getsidebarsize(void) |
|
|
|
{ |
|
|
|
struct feed *feed; |
|
|
|
size_t i; |
|
|
|
- int len, width = 0; |
|
|
|
- |
|
|
|
- /* fixed sidebar width? else calculate an optimal size automatically */ |
|
|
|
- if (fixedsidebarwidth >= 0) |
|
|
|
- return fixedsidebarwidth; |
|
|
|
- |
|
|
|
- for (i = 0; i < nfeeds; i++) { |
|
|
|
- feed = &feeds[i]; |
|
|
|
- |
|
|
|
- len = snprintf(NULL, 0, " (%lu/%lu)", feed->totalnew, feed->total) + |
|
|
|
- colw(feed->name); |
|
|
|
- if (len > width) |
|
|
|
- width = len; |
|
|
|
- |
|
|
|
- if (onlynew && feed->totalnew == 0) |
|
|
|
- continue; |
|
|
|
+ int len, size; |
|
|
|
+ |
|
|
|
+ /* fixed sidebar size? else calculate an optimal size automatically */ |
|
|
|
+ if (fixedsidebarsizes[layout] >= 0) |
|
|
|
+ return fixedsidebarsizes[layout]; |
|
|
|
+ |
|
|
|
+ switch (layout) { |
|
|
|
+ case LayoutVertical: |
|
|
|
+ for (i = 0, size = 0; i < nfeeds; i++) { |
|
|
|
+ feed = &feeds[i]; |
|
|
|
+ len = snprintf(NULL, 0, " (%lu/%lu)", |
|
|
|
+ feed->totalnew, feed->total) + |
|
|
|
+ colw(feed->name); |
|
|
|
+ if (len > size) |
|
|
|
+ size = len; |
|
|
|
+ |
|
|
|
+ if (onlynew && feed->totalnew == 0) |
|
|
|
+ continue; |
|
|
|
+ } |
|
|
|
+ return size; |
|
|
|
+ case LayoutHorizontal: |
|
|
|
+ for (i = 0, size = 0; i < nfeeds; i++) { |
|
|
|
+ feed = &feeds[i]; |
|
|
|
+ if (onlynew && feed->totalnew == 0) |
|
|
|
+ continue; |
|
|
|
+ size++; |
|
|
|
+ } |
|
|
|
+ return size; |
|
|
|
} |
|
|
|
- |
|
|
|
- return width; |
|
|
|
+ return 0; |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
@@ -1370,15 +1458,24 @@ updatesidebar(void) |
|
|
|
struct row *row; |
|
|
|
struct feed *feed; |
|
|
|
size_t i, nrows; |
|
|
|
- int oldwidth; |
|
|
|
+ int oldvalue, newvalue; |
|
|
|
|
|
|
|
p = &panes[PaneFeeds]; |
|
|
|
- |
|
|
|
if (!p->rows) |
|
|
|
p->rows = ecalloc(sizeof(p->rows[0]), nfeeds + 1); |
|
|
|
|
|
|
|
- oldwidth = p->width; |
|
|
|
- p->width = getsidebarwidth(); |
|
|
|
+ switch (layout) { |
|
|
|
+ case LayoutVertical: |
|
|
|
+ oldvalue = p->width; |
|
|
|
+ newvalue = getsidebarsize(); |
|
|
|
+ p->width = newvalue; |
|
|
|
+ break; |
|
|
|
+ case LayoutHorizontal: |
|
|
|
+ oldvalue = p->height; |
|
|
|
+ newvalue = getsidebarsize(); |
|
|
|
+ p->height = newvalue; |
|
|
|
+ break; |
|
|
|
+ } |
|
|
|
|
|
|
|
nrows = 0; |
|
|
|
for (i = 0; i < nfeeds; i++) { |
|
|
|
@@ -1395,10 +1492,18 @@ updatesidebar(void) |
|
|
|
} |
|
|
|
p->nrows = nrows; |
|
|
|
|
|
|
|
- if (p->width != oldwidth) |
|
|
|
- updategeom(); |
|
|
|
- else |
|
|
|
+ switch (layout) { |
|
|
|
+ case LayoutVertical: |
|
|
|
+ case LayoutHorizontal: |
|
|
|
+ if (oldvalue != newvalue) |
|
|
|
+ updategeom(); |
|
|
|
+ else |
|
|
|
+ p->dirty = 1; |
|
|
|
+ break; |
|
|
|
+ default: |
|
|
|
p->dirty = 1; |
|
|
|
+ break; |
|
|
|
+ } |
|
|
|
|
|
|
|
if (!p->nrows) |
|
|
|
p->pos = 0; |
|
|
|
@@ -1429,6 +1534,7 @@ alldirty(void) |
|
|
|
panes[PaneItems].dirty = 1; |
|
|
|
scrollbars[PaneFeeds].dirty = 1; |
|
|
|
scrollbars[PaneItems].dirty = 1; |
|
|
|
+ linebar.dirty = 1; |
|
|
|
statusbar.dirty = 1; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -1440,8 +1546,8 @@ draw(void) |
|
|
|
size_t i; |
|
|
|
|
|
|
|
if (win.dirty) { |
|
|
|
- clearscreen(); |
|
|
|
win.dirty = 0; |
|
|
|
+ clearscreen(); |
|
|
|
} |
|
|
|
|
|
|
|
/* There is the same amount and indices of panes and scrollbars. */ |
|
|
|
@@ -1456,6 +1562,8 @@ draw(void) |
|
|
|
scrollbar_draw(&scrollbars[i]); |
|
|
|
} |
|
|
|
|
|
|
|
+ linebar_draw(&linebar); |
|
|
|
+ |
|
|
|
/* If item selection text changed then update the status text. */ |
|
|
|
if ((row = pane_row_get(&panes[PaneItems], panes[PaneItems].pos))) { |
|
|
|
item = (struct item *)row->data; |
|
|
|
@@ -1481,7 +1589,7 @@ mousereport(int button, int release, int x, int y) |
|
|
|
|
|
|
|
for (i = 0; i < LEN(panes); i++) { |
|
|
|
p = &panes[i]; |
|
|
|
- if (p->hidden) |
|
|
|
+ if (p->hidden || !p->width || !p->height) |
|
|
|
continue; |
|
|
|
|
|
|
|
if (!(x >= p->x && x < p->x + p->width && |
|
|
|
@@ -1510,6 +1618,11 @@ mousereport(int button, int release, int x, int y) |
|
|
|
/* redraw row: counts could be changed */ |
|
|
|
updatesidebar(); |
|
|
|
updatetitle(); |
|
|
|
+ |
|
|
|
+ if (layout == LayoutMonocle) { |
|
|
|
+ selpane = PaneItems; |
|
|
|
+ updategeom(); |
|
|
|
+ } |
|
|
|
} else if (i == PaneItems) { |
|
|
|
if (dblclick && !changedpane) { |
|
|
|
row = pane_row_get(p, p->pos); |
|
|
|
@@ -1788,6 +1901,9 @@ main(int argc, char *argv[]) |
|
|
|
urlfile = getenv("SFEED_URL_FILE"); /* can be NULL */ |
|
|
|
cmdenv = getenv("SFEED_AUTOCMD"); /* can be NULL */ |
|
|
|
|
|
|
|
+ setlayout(argc <= 1 ? LayoutMonocle : LayoutVertical); |
|
|
|
+ selpane = layout == LayoutMonocle ? PaneItems : PaneFeeds; |
|
|
|
+ |
|
|
|
panes[PaneFeeds].row_format = feed_row_format; |
|
|
|
panes[PaneFeeds].row_match = feed_row_match; |
|
|
|
panes[PaneItems].row_format = item_row_format; |
|
|
|
@@ -1825,14 +1941,6 @@ main(int argc, char *argv[]) |
|
|
|
if (argc == 1) |
|
|
|
feeds[0].fp = NULL; |
|
|
|
|
|
|
|
- if (argc > 1) { |
|
|
|
- panes[PaneFeeds].hidden = 0; |
|
|
|
- selpane = PaneFeeds; |
|
|
|
- } else { |
|
|
|
- panes[PaneFeeds].hidden = 1; |
|
|
|
- selpane = PaneItems; |
|
|
|
- } |
|
|
|
- |
|
|
|
if ((devnullfd = open("/dev/null", O_WRONLY)) == -1) |
|
|
|
die("open: /dev/null"); |
|
|
|
|
|
|
|
@@ -1918,15 +2026,21 @@ keyleft: |
|
|
|
if (selpane == PaneFeeds) |
|
|
|
break; |
|
|
|
selpane = PaneFeeds; |
|
|
|
+ if (layout == LayoutMonocle) |
|
|
|
+ updategeom(); |
|
|
|
break; |
|
|
|
keyright: |
|
|
|
case 'l': |
|
|
|
if (selpane == PaneItems) |
|
|
|
break; |
|
|
|
selpane = PaneItems; |
|
|
|
+ if (layout == LayoutMonocle) |
|
|
|
+ updategeom(); |
|
|
|
break; |
|
|
|
case '\t': |
|
|
|
selpane = selpane == PaneFeeds ? PaneItems : PaneFeeds; |
|
|
|
+ if (layout == LayoutMonocle) |
|
|
|
+ updategeom(); |
|
|
|
break; |
|
|
|
startpos: |
|
|
|
case 'g': |
|
|
|
@@ -2004,24 +2118,18 @@ nextpage: |
|
|
|
usemouse = !usemouse; |
|
|
|
mousemode(usemouse); |
|
|
|
break; |
|
|
|
- case 's': /* toggle sidebar */ |
|
|
|
- panes[PaneFeeds].hidden = !panes[PaneFeeds].hidden; |
|
|
|
- if (selpane == PaneFeeds && panes[selpane].hidden) |
|
|
|
- selpane = PaneItems; |
|
|
|
- updategeom(); |
|
|
|
- break; |
|
|
|
case '<': /* decrease fixed sidebar width */ |
|
|
|
case '>': /* increase fixed sidebar width */ |
|
|
|
- if (fixedsidebarwidth < 0) |
|
|
|
- fixedsidebarwidth = getsidebarwidth(); |
|
|
|
- if (ch == '<' && fixedsidebarwidth > 0) |
|
|
|
- fixedsidebarwidth--; |
|
|
|
+ if (fixedsidebarsizes[layout] < 0) |
|
|
|
+ fixedsidebarsizes[layout] = getsidebarsize(); |
|
|
|
+ if (ch == '<' && fixedsidebarsizes[layout] > 0) |
|
|
|
+ fixedsidebarsizes[layout]--; |
|
|
|
else if (ch != '<') |
|
|
|
- fixedsidebarwidth++; |
|
|
|
+ fixedsidebarsizes[layout]++; |
|
|
|
updategeom(); |
|
|
|
break; |
|
|
|
- case '=': /* reset fixed sidebar width to automatic size */ |
|
|
|
- fixedsidebarwidth = -1; |
|
|
|
+ case '=': /* reset fixed sidebar to automatic size */ |
|
|
|
+ fixedsidebarsizes[layout] = -1; |
|
|
|
updategeom(); |
|
|
|
break; |
|
|
|
case 't': /* toggle showing only new in sidebar */ |
|
|
|
@@ -2043,6 +2151,11 @@ nextpage: |
|
|
|
/* redraw row: counts could be changed */ |
|
|
|
updatesidebar(); |
|
|
|
updatetitle(); |
|
|
|
+ |
|
|
|
+ if (layout == LayoutMonocle) { |
|
|
|
+ selpane = PaneItems; |
|
|
|
+ updategeom(); |
|
|
|
+ } |
|
|
|
} else if (selpane == PaneItems && panes[selpane].nrows) { |
|
|
|
row = pane_row_get(p, p->pos); |
|
|
|
item = (struct item *)row->data; |
|
|
|
@@ -2083,6 +2196,16 @@ nextpage: |
|
|
|
markread(p, p->pos, p->pos, ch == 'r'); |
|
|
|
} |
|
|
|
break; |
|
|
|
+ case 's': /* toggle layout between monocle or non-monocle */ |
|
|
|
+ setlayout(layout == LayoutMonocle ? prevlayout : LayoutMonocle); |
|
|
|
+ updategeom(); |
|
|
|
+ break; |
|
|
|
+ case '1': /* vertical layout */ |
|
|
|
+ case '2': /* horizontal layout */ |
|
|
|
+ case '3': /* monocle layout */ |
|
|
|
+ setlayout(ch - '1'); |
|
|
|
+ updategeom(); |
|
|
|
+ break; |
|
|
|
case 4: /* EOT */ |
|
|
|
case 'q': goto end; |
|
|
|
} |
|
|
 |
diff --git a/themes/mono.h b/themes/mono.h |
|
|
|
@@ -7,6 +7,7 @@ |
|
|
|
#define THEME_SCROLLBAR_NORMAL() do { attrmode(ATTR_FAINT_ON); } while(0) |
|
|
|
#define THEME_SCROLLBAR_TICK_FOCUS() do { attrmode(ATTR_REVERSE_ON); } while(0) |
|
|
|
#define THEME_SCROLLBAR_TICK_NORMAL() do { attrmode(ATTR_REVERSE_ON); } while(0) |
|
|
|
+#define THEME_LINEBAR() do { attrmode(ATTR_FAINT_ON); } while(0) |
|
|
|
#define THEME_STATUSBAR() do { attrmode(ATTR_REVERSE_ON); } while(0) |
|
|
|
#define THEME_INPUT_LABEL() do { attrmode(ATTR_REVERSE_ON); } while(0) |
|
|
|
#define THEME_INPUT_NORMAL() do { } while(0) |
|
|
 |
diff --git a/themes/newsboat.h b/themes/newsboat.h |
|
|
|
@@ -7,6 +7,7 @@ |
|
|
|
#define THEME_SCROLLBAR_NORMAL() do { ttywrite("\x1b[34m"); } while(0) |
|
|
|
#define THEME_SCROLLBAR_TICK_FOCUS() do { ttywrite("\x1b[44m"); } while(0) /* blue bg */ |
|
|
|
#define THEME_SCROLLBAR_TICK_NORMAL() do { ttywrite("\x1b[44m"); } while(0) |
|
|
|
+#define THEME_LINEBAR() do { ttywrite("\x1b[34m"); } while(0) |
|
|
|
#define THEME_STATUSBAR() do { attrmode(ATTR_BOLD_ON); ttywrite("\x1b[93;44m"); } while(0) |
|
|
|
#define THEME_INPUT_LABEL() do { } while(0) |
|
|
|
#define THEME_INPUT_NORMAL() do { } while(0) |
|
|
 |
diff --git a/themes/templeos.h b/themes/templeos.h |
|
|
|
@@ -11,9 +11,14 @@ |
|
|
|
#define THEME_SCROLLBAR_NORMAL() do { SETFGCOLOR(0x00, 0x00, 0xaa); SETBGCOLOR(0xff, 0xff, 0xff); } while(0) |
|
|
|
#define THEME_SCROLLBAR_TICK_FOCUS() do { SETBGCOLOR(0x00, 0x00, 0xaa); SETFGCOLOR(0xff, 0xff, 0xff); } while(0) |
|
|
|
#define THEME_SCROLLBAR_TICK_NORMAL() do { SETBGCOLOR(0x00, 0x00, 0xaa); SETFGCOLOR(0xff, 0xff, 0xff); } while(0) |
|
|
|
+#define THEME_LINEBAR() do { SETFGCOLOR(0x00, 0x00, 0xaa); SETBGCOLOR(0xff, 0xff, 0xff); } while(0) |
|
|
|
#define THEME_STATUSBAR() do { ttywrite("\x1b[6m"); SETBGCOLOR(0x00, 0x00, 0xaa); SETFGCOLOR(0xff, 0xff, 0xff); } while(0) /* blink statusbar */ |
|
|
|
#define THEME_INPUT_LABEL() do { SETFGCOLOR(0x00, 0x00, 0xaa); SETBGCOLOR(0xff, 0xff, 0xff); } while(0) |
|
|
|
#define THEME_INPUT_NORMAL() do { SETFGCOLOR(0x00, 0x00, 0xaa); SETBGCOLOR(0xff, 0xff, 0xff); } while(0) |
|
|
|
|
|
|
|
#undef SCROLLBAR_SYMBOL_BAR |
|
|
|
#define SCROLLBAR_SYMBOL_BAR "\xe2\x95\x91" /* symbol: "double vertical" */ |
|
|
|
+#undef LINEBAR_SYMBOL_BAR |
|
|
|
+#define LINEBAR_SYMBOL_BAR "\xe2\x95\x90" /* symbol: "double horizontal" */ |
|
|
|
+#undef LINEBAR_SYMBOL_RIGHT |
|
|
|
+#define LINEBAR_SYMBOL_RIGHT "\xe2\x95\xa3" /* symbol: "double vertical and left" */ |
|