summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO16
-rwxr-xr-xPKGBUILD8
-rwxr-xr-xrtorrent-0.9.8_color.patch479
-rwxr-xr-xrtorrent-0.9.8_compact_display.patch55
-rwxr-xr-xrtorrent-0.9.8_vi_keybinding_tjwoosta.patch184
5 files changed, 730 insertions, 12 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 22c632ceab5f..6c72f37f4916 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = rtorrent-vi-color
pkgdesc = Ncurses BitTorrent client based on libTorrent with vi like keybindings and color patch.
- pkgver = 0.9.7
+ pkgver = 0.9.8
pkgrel = 1
url = http://libtorrent.rakshasa.no
install = rtorrent-vi-color.install
@@ -13,13 +13,13 @@ pkgbase = rtorrent-vi-color
depends = libsigc++
provides = rtorrent
conflicts = rtorrent
- source = rtorrent-vi-color-0.9.7.tar.gz::https://github.com/rakshasa/rtorrent/archive/v0.9.7.tar.gz
- source = rtorrent-0.9.7_vi_keybinding_tjwoosta.patch
- source = rtorrent-0.9.7_color.patch
- source = rtorrent-0.9.7_compact_display.patch
- sha1sums = 6c4f13288b36a868ca777f3ae5a39928ddbf6426
- sha1sums = 491be68e005124bd61efcaab5dcfc0ddb3a2059a
- sha1sums = f32cc1c0622155f4c47d99fbb52f0e918476188f
+ source = rtorrent-vi-color-0.9.8.tar.gz::https://github.com/rakshasa/rtorrent/archive/v0.9.8.tar.gz
+ source = rtorrent-0.9.8_vi_keybinding_tjwoosta.patch
+ source = rtorrent-0.9.8_color.patch
+ source = rtorrent-0.9.8_compact_display.patch
+ sha1sums = 897ab36a4e6769df2984930cae0991da83818237
+ sha1sums = 732f4b6b9d0a699018fe5e5a974c430c0d09d061
+ sha1sums = a086d12ed3f57d766ee0752b23cb025f1127dde4
sha1sums = 58e625a458033d85ac642c39213455c41ab63b9f
pkgname = rtorrent-vi-color
diff --git a/PKGBUILD b/PKGBUILD
index 6f171c2c7c2a..e44012a57aa7 100755
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -8,7 +8,7 @@
pkgname="rtorrent-vi-color"
_pkgname="rtorrent"
-pkgver=0.9.7
+pkgver=0.9.8
pkgrel=1
pkgdesc='Ncurses BitTorrent client based on libTorrent with vi like keybindings and color patch.'
url="http://libtorrent.rakshasa.no"
@@ -22,9 +22,9 @@ source=("${pkgname}-${pkgver}.tar.gz::https://github.com/rakshasa/${_pkgname}/ar
"${_pkgname}-${pkgver}_vi_keybinding_tjwoosta.patch"
"${_pkgname}-${pkgver}_color.patch"
"${_pkgname}-${pkgver}_compact_display.patch")
-sha1sums=('6c4f13288b36a868ca777f3ae5a39928ddbf6426'
- '491be68e005124bd61efcaab5dcfc0ddb3a2059a'
- 'f32cc1c0622155f4c47d99fbb52f0e918476188f'
+sha1sums=('897ab36a4e6769df2984930cae0991da83818237'
+ '732f4b6b9d0a699018fe5e5a974c430c0d09d061'
+ 'a086d12ed3f57d766ee0752b23cb025f1127dde4'
'58e625a458033d85ac642c39213455c41ab63b9f')
build() {
diff --git a/rtorrent-0.9.8_color.patch b/rtorrent-0.9.8_color.patch
new file mode 100755
index 000000000000..0b426b8c53bd
--- /dev/null
+++ b/rtorrent-0.9.8_color.patch
@@ -0,0 +1,479 @@
+diff --git a/src/command_network.cc b/src/command_network.cc
+index 092287a..4f71e83 100644
+--- a/src/command_network.cc
++++ b/src/command_network.cc
+@@ -235,6 +235,26 @@ initialize_command_network() {
+ torrent::FileManager* fileManager = torrent::file_manager();
+ core::CurlStack* httpStack = control->core()->http_stack();
+
++ CMD2_ANY ("colors.color_inactive_fg", std::bind(&ui::Root::get_color_inactive_fg, control->ui()));
++ CMD2_ANY_VALUE_V ("colors.color_inactive_fg.set", std::bind(&ui::Root::set_color_inactive_fg, control->ui(), std::placeholders::_2));
++ CMD2_ANY ("colors.color_inactive_bg", std::bind(&ui::Root::get_color_inactive_bg, control->ui()));
++ CMD2_ANY_VALUE_V ("colors.color_inactive_bg.set", std::bind(&ui::Root::set_color_inactive_bg, control->ui(), std::placeholders::_2));
++
++ CMD2_ANY ("colors.color_dead_fg", std::bind(&ui::Root::get_color_dead_fg, control->ui()));
++ CMD2_ANY_VALUE_V ("colors.color_dead_fg.set", std::bind(&ui::Root::set_color_dead_fg, control->ui(), std::placeholders::_2));
++ CMD2_ANY ("colors.color_dead_bg", std::bind(&ui::Root::get_color_dead_bg, control->ui()));
++ CMD2_ANY_VALUE_V ("colors.color_dead_bg.set", std::bind(&ui::Root::set_color_dead_bg, control->ui(), std::placeholders::_2));
++
++ CMD2_ANY ("colors.color_active_fg", std::bind(&ui::Root::get_color_active_fg, control->ui()));
++ CMD2_ANY_VALUE_V ("colors.color_active_fg.set", std::bind(&ui::Root::set_color_active_fg, control->ui(), std::placeholders::_2));
++ CMD2_ANY ("colors.color_active_bg", std::bind(&ui::Root::get_color_active_bg, control->ui()));
++ CMD2_ANY_VALUE_V ("colors.color_active_bg.set", std::bind(&ui::Root::set_color_active_bg, control->ui(), std::placeholders::_2));
++
++ CMD2_ANY ("colors.color_finished_fg", std::bind(&ui::Root::get_color_finished_fg, control->ui()));
++ CMD2_ANY_VALUE_V ("colors.color_finished_fg.set", std::bind(&ui::Root::set_color_finished_fg, control->ui(), std::placeholders::_2));
++ CMD2_ANY ("colors.color_finished_bg", std::bind(&ui::Root::get_color_finished_bg, control->ui()));
++ CMD2_ANY_VALUE_V ("colors.color_finished_bg.set", std::bind(&ui::Root::set_color_finished_bg, control->ui(), std::placeholders::_2));
++
+ CMD2_ANY_STRING ("encoding.add", std::bind(&apply_encoding_list, std::placeholders::_2));
+
+ // Isn't port_open used?
+diff --git a/src/display/canvas.cc b/src/display/canvas.cc
+index fc24bbc..6021e8c 100644
+--- a/src/display/canvas.cc
++++ b/src/display/canvas.cc
+@@ -111,6 +111,12 @@ Canvas::initialize() {
+
+ if (!m_isDaemon) {
+ initscr();
++ start_color();
++ use_default_colors();
++ init_pair(4, -1, -1);
++ init_pair(3, -1, -1);
++ init_pair(2, -1, -1);
++ init_pair(1, -1, -1);
+ raw();
+ noecho();
+ nodelay(stdscr, TRUE);
+diff --git a/src/display/window_download_list.cc b/src/display/window_download_list.cc
+index 6b4936d..16cfd85 100644
+--- a/src/display/window_download_list.cc
++++ b/src/display/window_download_list.cc
+@@ -37,6 +37,7 @@
+ #include "config.h"
+
+ #include <rak/algorithm.h>
++#include <torrent/rate.h>
+
+ #include "core/download.h"
+ #include "core/view.h"
+@@ -124,6 +125,14 @@ WindowDownloadList::redraw() {
+ char buffer[m_canvas->width() + 1];
+ char* last = buffer + m_canvas->width() - 2 + 1;
+
++ /*
++ There are four states where colors are applied:
++ 1 inactive # If inactive, e.g. user stopped down/upload
++ 2 dead # If active but no down/upload
++ 3 active # If active and download
++ 4 finished # If finished
++ */
++
+ // Add a proper 'column info' method.
+ if (layout_name == "compact") {
+ print_download_column_compact(buffer, last);
+@@ -135,7 +144,32 @@ WindowDownloadList::redraw() {
+ if (layout_name == "full") {
+ while (range.first != range.second) {
+ print_download_title(buffer, last, *range.first);
+- m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
++ m_canvas->print(0, pos, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
++ if( (*range.first)->is_done() ) {
++ if( (*range.first)->download()->info()->up_rate()->rate() != 0 ) {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_BOLD, 4); // Finished and uploading
++ } else {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 4); // Finished
++ }
++ } else if( (*range.first)->is_active() ) {
++ if( (*range.first)->download()->info()->down_rate()->rate() != 0 ) {
++ if( (*range.first)->download()->info()->up_rate()->rate() != 0 ) {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_BOLD, 3); // Active and uploading
++ } else {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 3); // Active
++ }
++ } else {
++ if( (*range.first)->download()->info()->up_rate()->rate() != 0 ) {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_BOLD, 2); // Dead but still uploading
++ } else {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 2); // Dead
++ }
++ }
++ } else {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 1); // Inactive
++ }
++ pos++;
++
+ print_download_info_full(buffer, last, *range.first);
+ m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
+ print_download_status(buffer, last, *range.first);
+@@ -148,11 +182,111 @@ WindowDownloadList::redraw() {
+ while (range.first != range.second) {
+ print_download_info_compact(buffer, last, *range.first);
+ m_canvas->set_default_attributes(range.first == m_view->focus() ? A_REVERSE : A_NORMAL);
+- m_canvas->print(0, pos++, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
++ m_canvas->print(0, pos, "%c %s", range.first == m_view->focus() ? '*' : ' ', buffer);
++ if( (*range.first)->is_done() ) {
++ if( (*range.first)->download()->info()->up_rate()->rate() != 0 ) {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_BOLD, 4); // Finished and uploading
++ } else {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 4); // Finished
++ }
++ } else if( (*range.first)->is_active() ) {
++ if( (*range.first)->download()->info()->down_rate()->rate() != 0 ) {
++ if( (*range.first)->download()->info()->up_rate()->rate() != 0 ) {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_BOLD, 3); // Active and uploading
++ } else {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 3); // Active
++ }
++ } else {
++ if( (*range.first)->download()->info()->up_rate()->rate() != 0 ) {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_BOLD, 2); // Dead but still uploading
++ } else {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 2); // Dead
++ }
++ }
++ } else {
++ m_canvas->set_attr(0, pos, m_canvas->width()-1, A_NORMAL, 1); // Inactive
++ }
++ pos++;
+
+ range.first++;
+ }
+ }
+ }
+
++// Inactive
++void
++WindowDownloadList::set_color_inactive_fg(int64_t color) {
++ short fg, bg;
++ pair_content(1, &fg, &bg);
++ if( color < 0 ) color = -1;
++ color = color % 8;
++ init_pair(1, (short)color, bg);
++}
++
++void
++WindowDownloadList::set_color_inactive_bg(int64_t color) {
++ short fg, bg;
++ pair_content(1, &fg, &bg);
++ if( color < 0 ) color = -1;
++ color = color % 8;
++ init_pair(1, fg, (short)color);
++}
++
++// Dead
++void
++WindowDownloadList::set_color_dead_fg(int64_t color) {
++ short fg, bg;
++ pair_content(2, &fg, &bg);
++ if( color < 0 ) color = -1;
++ color = color % 8;
++ init_pair(2, (short)color, bg);
++}
++
++void
++WindowDownloadList::set_color_dead_bg(int64_t color) {
++ short fg, bg;
++ pair_content(2, &fg, &bg);
++ if( color < 0 ) color = -1;
++ color = color % 8;
++ init_pair(2, fg, (short)color);
++}
++
++// Active
++void
++WindowDownloadList::set_color_active_fg(int64_t color) {
++ short fg, bg;
++ pair_content(3, &fg, &bg);
++ if( color < 0 ) color = -1;
++ color = color % 8;
++ init_pair(3, (short)color, bg);
++}
++
++void
++WindowDownloadList::set_color_active_bg(int64_t color) {
++ short fg, bg;
++ pair_content(3, &fg, &bg);
++ if( color < 0 ) color = -1;
++ color = color % 8;
++ init_pair(3, fg, (short)color);
++}
++
++// Finished
++void
++WindowDownloadList::set_color_finished_fg(int64_t color) {
++ short fg, bg;
++ pair_content(4, &fg, &bg);
++ if( color < 0 ) color = -1;
++ color = color % 8;
++ init_pair(4, (short)color, bg);
++}
++
++void
++WindowDownloadList::set_color_finished_bg(int64_t color) {
++ short fg, bg;
++ pair_content(4, &fg, &bg);
++ if( color < 0 ) color = -1;
++ color = color % 8;
++ init_pair(4, fg, (short)color);
++}
++
+ }
+diff --git a/src/display/window_download_list.h b/src/display/window_download_list.h
+index 8e15cac..4551a47 100644
+--- a/src/display/window_download_list.h
++++ b/src/display/window_download_list.h
+@@ -55,6 +55,15 @@ public:
+
+ void set_view(core::View* l);
+
++ void set_color_inactive_fg(int64_t color);
++ void set_color_inactive_bg(int64_t color);
++ void set_color_dead_fg(int64_t color);
++ void set_color_dead_bg(int64_t color);
++ void set_color_active_fg(int64_t color);
++ void set_color_active_bg(int64_t color);
++ void set_color_finished_fg(int64_t color);
++ void set_color_finished_bg(int64_t color);
++
+ private:
+ core::View* m_view;
+
+diff --git a/src/main.cc b/src/main.cc
+index 6be6a4d..70f7d07 100644
+--- a/src/main.cc
++++ b/src/main.cc
+@@ -399,6 +399,15 @@ main(int argc, char** argv) {
+ CMD2_REDIRECT ("ip", "network.local_address.set");
+ CMD2_REDIRECT ("port_range", "network.port_range.set");
+
++ CMD2_REDIRECT ("color_inactive_fg", "colors.color_inactive_fg.set");
++ CMD2_REDIRECT ("color_inactive_bg", "colors.color_inactive_bg.set");
++ CMD2_REDIRECT ("color_dead_fg", "colors.color_dead_fg.set");
++ CMD2_REDIRECT ("color_dead_bg", "colors.color_dead_bg.set");
++ CMD2_REDIRECT ("color_active_fg", "colors.color_active_fg.set");
++ CMD2_REDIRECT ("color_active_bg", "colors.color_active_bg.set");
++ CMD2_REDIRECT ("color_finished_fg", "colors.color_finished_fg.set");
++ CMD2_REDIRECT ("color_finished_bg", "colors.color_finished_bg.set");
++
+ CMD2_REDIRECT_GENERIC("dht", "dht.mode.set");
+ CMD2_REDIRECT_GENERIC("dht_port", "dht.port.set");
+
+diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc
+index d98f2c9..ebd7038 100644
+--- a/src/ui/download_list.cc
++++ b/src/ui/download_list.cc
+@@ -135,6 +135,11 @@ DownloadList::unfocus_download(core::Download* d) {
+ current_view()->next_focus();
+ }
+
++display::WindowDownloadList*
++DownloadList::current_window_list() {
++ return dynamic_cast<ElementDownloadList*>(m_uiArray[DISPLAY_DOWNLOAD_LIST])->window();
++}
++
+ void
+ DownloadList::activate_display(Display displayType) {
+ if (!is_active())
+diff --git a/src/ui/download_list.h b/src/ui/download_list.h
+index 791ee61..7e1e548 100644
+--- a/src/ui/download_list.h
++++ b/src/ui/download_list.h
+@@ -100,6 +100,7 @@ public:
+ void activate_display(Display d);
+
+ core::View* current_view();
++ display::WindowDownloadList* current_window_list();
+ void set_current_view(const std::string& name);
+
+ void slot_open_uri(slot_string s) { m_slot_open_uri = s; }
+diff --git a/src/ui/element_download_list.h b/src/ui/element_download_list.h
+index 5bf4f08..34e2352 100644
+--- a/src/ui/element_download_list.h
++++ b/src/ui/element_download_list.h
+@@ -60,6 +60,7 @@ public:
+ void disable();
+
+ core::View* view() { return m_view; }
++ WDownloadList* window() { return m_window; }
+ void set_view(core::View* l);
+
+ void receive_command(const char* cmd);
+diff --git a/src/ui/root.cc b/src/ui/root.cc
+index 074e972..c8130e9 100644
+--- a/src/ui/root.cc
++++ b/src/ui/root.cc
+@@ -47,6 +47,7 @@
+
+ #include "core/manager.h"
+ #include "display/frame.h"
++#include "display/window_download_list.h"
+ #include "display/window_http_queue.h"
+ #include "display/window_title.h"
+ #include "display/window_input.h"
+@@ -72,7 +73,15 @@ Root::Root() :
+ m_windowStatusbar(NULL),
+ m_input_history_length(99),
+ m_input_history_last_input(""),
+- m_input_history_pointer_get(0) {
++ m_input_history_pointer_get(0),
++ color_inactive_fg(-1),
++ color_inactive_bg(-1),
++ color_dead_fg(-1),
++ color_dead_bg(-1),
++ color_active_fg(-1),
++ color_active_bg(-1),
++ color_finished_fg(-1),
++ color_finished_bg(-1) {
+
+ // Initialise prefilled m_input_history and m_input_history_pointers objects.
+ for (int type = ui::DownloadList::INPUT_LOAD_DEFAULT; type != ui::DownloadList::INPUT_EOI; type++) {
+@@ -111,6 +120,14 @@ Root::init(Control* c) {
+ setup_keys();
+
+ m_downloadList->activate(rootFrame->frame(1));
++ m_downloadList->current_window_list()->set_color_inactive_fg(color_inactive_fg);
++ m_downloadList->current_window_list()->set_color_inactive_bg(color_inactive_bg);
++ m_downloadList->current_window_list()->set_color_dead_fg(color_dead_fg);
++ m_downloadList->current_window_list()->set_color_dead_bg(color_dead_bg);
++ m_downloadList->current_window_list()->set_color_active_fg(color_active_fg);
++ m_downloadList->current_window_list()->set_color_active_bg(color_active_bg);
++ m_downloadList->current_window_list()->set_color_finished_fg(color_finished_fg);
++ m_downloadList->current_window_list()->set_color_finished_bg(color_finished_bg);
+ }
+
+ void
+@@ -504,4 +521,88 @@ Root::clear_input_history() {
+ }
+ }
+
++// Inactive
++int
++Root::get_color_inactive_fg() {
++ return color_inactive_fg;
++}
++
++void
++Root::set_color_inactive_fg(int64_t color) {
++ color_inactive_fg = color;
++}
++
++int
++Root::get_color_inactive_bg() {
++ return color_inactive_bg;
++}
++
++void
++Root::set_color_inactive_bg(int64_t color) {
++ color_inactive_bg = color;
++}
++
++// Dead
++int
++Root::get_color_dead_fg() {
++ return color_dead_fg;
++}
++
++void
++Root::set_color_dead_fg(int64_t color) {
++ color_dead_fg = color;
++}
++
++int
++Root::get_color_dead_bg() {
++ return color_dead_bg;
++}
++
++void
++Root::set_color_dead_bg(int64_t color) {
++ color_dead_bg = color;
++}
++
++// Active
++int
++Root::get_color_active_fg() {
++ return color_active_fg;
++}
++
++void
++Root::set_color_active_fg(int64_t color) {
++ color_active_fg = color;
++}
++
++int
++Root::get_color_active_bg() {
++ return color_active_bg;
++}
++
++void
++Root::set_color_active_bg(int64_t color) {
++ color_active_bg = color;
++}
++
++// Finished
++int
++Root::get_color_finished_fg() {
++ return color_finished_fg;
++}
++
++void
++Root::set_color_finished_fg(int64_t color) {
++ color_finished_fg = color;
++}
++
++int
++Root::get_color_finished_bg() {
++ return color_finished_bg;
++}
++
++void
++Root::set_color_finished_bg(int64_t color) {
++ color_finished_bg = color;
++}
++
+ }
+diff --git a/src/ui/root.h b/src/ui/root.h
+index 262de37..e6f2f6f 100644
+--- a/src/ui/root.h
++++ b/src/ui/root.h
+@@ -88,6 +88,23 @@ public:
+ void set_down_throttle_i64(int64_t throttle) { set_down_throttle(throttle >> 10); }
+ void set_up_throttle_i64(int64_t throttle) { set_up_throttle(throttle >> 10); }
+
++ int get_color_inactive_fg();
++ void set_color_inactive_fg(int64_t color);
++ int get_color_inactive_bg();
++ void set_color_inactive_bg(int64_t color);
++ int get_color_dead_fg();
++ void set_color_dead_fg(int64_t color);
++ int get_color_dead_bg();
++ void set_color_dead_bg(int64_t color);
++ int get_color_active_fg();
++ void set_color_active_fg(int64_t color);
++ int get_color_active_bg();
++ void set_color_active_bg(int64_t color);
++ int get_color_finished_fg();
++ void set_color_finished_fg(int64_t color);
++ int get_color_finished_bg();
++ void set_color_finished_bg(int64_t color);
++
+ void adjust_down_throttle(int throttle);
+ void adjust_up_throttle(int throttle);
+
+@@ -129,6 +146,15 @@ private:
+ void next_in_input_history(ui::DownloadList::Input type);
+
+ void reset_input_history_attributes(ui::DownloadList::Input type);
++
++ int64_t color_inactive_fg;
++ int64_t color_inactive_bg;
++ int64_t color_dead_fg;
++ int64_t color_dead_bg;
++ int64_t color_active_fg;
++ int64_t color_active_bg;
++ int64_t color_finished_fg;
++ int64_t color_finished_bg;
+ };
+
+ }
diff --git a/rtorrent-0.9.8_compact_display.patch b/rtorrent-0.9.8_compact_display.patch
new file mode 100755
index 000000000000..71502cd70d4f
--- /dev/null
+++ b/rtorrent-0.9.8_compact_display.patch
@@ -0,0 +1,55 @@
+diff --git a/src/display/utils.cc b/src/display/utils.cc
+index 93011e8..9e42cc2 100644
+--- a/src/display/utils.cc
++++ b/src/display/utils.cc
+@@ -98,9 +98,9 @@ print_hhmmss_local(char* first, char* last, time_t t) {
+ char*
+ print_ddhhmm(char* first, char* last, time_t t) {
+ if (t / (24 * 3600) < 100)
+- return print_buffer(first, last, "%2id %2i:%02i", (int)t / (24 * 3600), ((int)t / 3600) % 24, ((int)t / 60) % 60);
++ return print_buffer(first, last, "%2id %2i:%02i ", (int)t / (24 * 3600), ((int)t / 3600) % 24, ((int)t / 60) % 60);
+ else
+- return print_buffer(first, last, "--d --:--");
++ return print_buffer(first, last, "--d --:-- ");
+ }
+
+ char*
+@@ -221,7 +221,7 @@ print_download_status(char* first, char* last, core::Download* d) {
+ char*
+ print_download_column_compact(char* first, char* last) {
+ first = print_buffer(first, last, " %-64.64s", "Name");
+- first = print_buffer(first, last, "| Status | Downloaded | Size | Done | Up Rate | Down Rate | Uploaded | ETA | Ratio| Misc ");
++ first = print_buffer(first, last, "| Status | Downloaded | Size | Done | Up Rate | Down Rate | Uploaded | ETA | Ratio | Misc ");
+
+ if (first > last)
+ throw torrent::internal_error("print_download_column_compact(...) wrote past end of the buffer.");
+@@ -237,7 +237,7 @@ print_download_info_compact(char* first, char* last, core::Download* d) {
+ if (!d->download()->info()->is_open())
+ first = print_buffer(first, last, " CLOSED ");
+ else if (!d->download()->info()->is_active())
+- first = print_buffer(first, last, " OPEN ");
++ first = print_buffer(first, last, " OPEN ");
+ else
+ first = print_buffer(first, last, " ");
+
+@@ -260,9 +260,9 @@ print_download_info_compact(char* first, char* last, core::Download* d) {
+ if (d->download()->info()->is_active() && !d->is_done())
+ first = print_download_time_left(first, last, d);
+ else
+- first = print_buffer(first, last, " ");
++ first = print_buffer(first, last, " ");
+
+- first = print_buffer(first, last, "| %4.2f ", (double)rpc::call_command_value("d.ratio", rpc::make_target(d)) / 1000.0);
++ first = print_buffer(first, last, "| %4.2f ", (double)rpc::call_command_value("d.ratio", rpc::make_target(d)) / 1000.0);
+ first = print_buffer(first, last, "| %c%c",
+ rpc::call_command_string("d.tied_to_file", rpc::make_target(d)).empty() ? ' ' : 'T',
+ rpc::call_command_value("d.ignore_commands", rpc::make_target(d)) == 0 ? ' ' : 'I',
+@@ -285,7 +285,7 @@ print_download_time_left(char* first, char* last, core::Download* d) {
+ uint32_t rate = d->info()->down_rate()->rate();
+
+ if (rate < 512)
+- return print_buffer(first, last, "--d --:--");
++ return print_buffer(first, last, "--d --:-- ");
+
+ time_t remaining = (d->download()->file_list()->size_bytes() - d->download()->bytes_done()) / (rate & ~(uint32_t)(512 - 1));
+
diff --git a/rtorrent-0.9.8_vi_keybinding_tjwoosta.patch b/rtorrent-0.9.8_vi_keybinding_tjwoosta.patch
new file mode 100755
index 000000000000..83b1c8fab8a1
--- /dev/null
+++ b/rtorrent-0.9.8_vi_keybinding_tjwoosta.patch
@@ -0,0 +1,184 @@
+diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc
+index f1d6af5..d98f2c9 100644
+--- a/src/ui/download_list.cc
++++ b/src/ui/download_list.cc
+@@ -400,11 +400,15 @@ DownloadList::setup_keys() {
+
+ m_uiArray[DISPLAY_LOG]->bindings()[KEY_LEFT] =
+ m_uiArray[DISPLAY_LOG]->bindings()['B' - '@'] =
+- m_uiArray[DISPLAY_LOG]->bindings()[' '] = std::bind(&DownloadList::activate_display, this, DISPLAY_DOWNLOAD_LIST);
++ m_uiArray[DISPLAY_LOG]->bindings()[' '] =
++ m_uiArray[DISPLAY_LOG]->bindings()['h'] = std::bind(&DownloadList::activate_display, this, DISPLAY_DOWNLOAD_LIST);
++
++
+
+ m_uiArray[DISPLAY_DOWNLOAD_LIST]->bindings()[KEY_RIGHT] =
+- m_uiArray[DISPLAY_DOWNLOAD_LIST]->bindings()['F' - '@'] = std::bind(&DownloadList::activate_display, this, DISPLAY_DOWNLOAD);
+- m_uiArray[DISPLAY_DOWNLOAD_LIST]->bindings()['l'] = std::bind(&DownloadList::activate_display, this, DISPLAY_LOG);
++ m_uiArray[DISPLAY_DOWNLOAD_LIST]->bindings()['F' - '@'] =
++ m_uiArray[DISPLAY_DOWNLOAD_LIST]->bindings()['l'] = std::bind(&DownloadList::activate_display, this, DISPLAY_DOWNLOAD);
++ m_uiArray[DISPLAY_DOWNLOAD_LIST]->bindings()['L'] = std::bind(&DownloadList::activate_display, this, DISPLAY_LOG);
+ }
+
+ }
+diff --git a/src/ui/element_chunks_seen.cc b/src/ui/element_chunks_seen.cc
+index 687250e..0a59eb0 100644
+--- a/src/ui/element_chunks_seen.cc
++++ b/src/ui/element_chunks_seen.cc
+@@ -52,10 +52,14 @@ ElementChunksSeen::ElementChunksSeen(core::Download* d) :
+ m_window(NULL),
+ m_focus(0) {
+
+- m_bindings[KEY_LEFT] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
++ m_bindings[KEY_LEFT] = m_bindings['B' - '@'] =
++ m_bindings['h'] = std::bind(&slot_type::operator(), &m_slot_exit);
++
++ m_bindings[KEY_DOWN] = m_bindings['N' - '@'] =
++ m_bindings['j'] = std::bind(&ElementChunksSeen::receive_next, this);
++ m_bindings[KEY_UP] = m_bindings['P' - '@'] =
++ m_bindings['k'] = std::bind(&ElementChunksSeen::receive_prev, this);
+
+- m_bindings[KEY_DOWN] = m_bindings['N' - '@'] = std::bind(&ElementChunksSeen::receive_next, this);
+- m_bindings[KEY_UP] = m_bindings['P' - '@'] = std::bind(&ElementChunksSeen::receive_prev, this);
+ m_bindings[KEY_NPAGE] = std::bind(&ElementChunksSeen::receive_pagenext, this);
+ m_bindings[KEY_PPAGE] = std::bind(&ElementChunksSeen::receive_pageprev, this);
+ }
+diff --git a/src/ui/element_download_list.cc b/src/ui/element_download_list.cc
+index 90a769a..bd5f28a 100644
+--- a/src/ui/element_download_list.cc
++++ b/src/ui/element_download_list.cc
+@@ -97,8 +97,8 @@ ElementDownloadList::ElementDownloadList() :
+ m_bindings['9'] = std::bind(&ElementDownloadList::receive_change_view, this, "leeching");
+ m_bindings['0'] = std::bind(&ElementDownloadList::receive_change_view, this, "active");
+
+- m_bindings[KEY_UP] = m_bindings['P' - '@'] = std::bind(&ElementDownloadList::receive_prev, this);
+- m_bindings[KEY_DOWN] = m_bindings['N' - '@'] = std::bind(&ElementDownloadList::receive_next, this);
++ m_bindings[KEY_UP] = m_bindings['k'] = m_bindings['P' - '@'] = std::bind(&ElementDownloadList::receive_prev, this);
++ m_bindings[KEY_DOWN] = m_bindings['j'] = m_bindings['N' - '@'] = std::bind(&ElementDownloadList::receive_next, this);
+
+ m_bindings['L'] = std::bind(&ElementDownloadList::toggle_layout, this);
+ }
+diff --git a/src/ui/element_file_list.cc b/src/ui/element_file_list.cc
+index 270c215..a6e6a8f 100644
+--- a/src/ui/element_file_list.cc
++++ b/src/ui/element_file_list.cc
+@@ -63,8 +63,8 @@ ElementFileList::ElementFileList(core::Download* d) :
+ m_selected(iterator(d->download()->file_list()->begin())),
+ m_collapsed(false) {
+
+- m_bindings[KEY_LEFT] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
+- m_bindings[KEY_RIGHT] = m_bindings['F' - '@'] = std::bind(&ElementFileList::receive_select, this);
++ m_bindings[KEY_LEFT] = m_bindings['h'] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
++ m_bindings[KEY_RIGHT] = m_bindings['l'] = m_bindings['F' - '@'] = std::bind(&ElementFileList::receive_select, this);
+
+ m_bindings[' '] = std::bind(&ElementFileList::receive_priority, this);
+ m_bindings['*'] = std::bind(&ElementFileList::receive_change_all, this);
+@@ -72,8 +72,8 @@ ElementFileList::ElementFileList(core::Download* d) :
+ m_bindings[KEY_NPAGE] = std::bind(&ElementFileList::receive_pagenext, this);
+ m_bindings[KEY_PPAGE] = std::bind(&ElementFileList::receive_pageprev, this);
+
+- m_bindings[KEY_DOWN] = m_bindings['N' - '@'] = std::bind(&ElementFileList::receive_next, this);
+- m_bindings[KEY_UP] = m_bindings['P' - '@'] = std::bind(&ElementFileList::receive_prev, this);
++ m_bindings[KEY_DOWN] = m_bindings['j'] = m_bindings['N' - '@'] = std::bind(&ElementFileList::receive_next, this);
++ m_bindings[KEY_UP] = m_bindings['k'] = m_bindings['P' - '@'] = std::bind(&ElementFileList::receive_prev, this);
+ }
+
+ inline ElementText*
+diff --git a/src/ui/element_menu.cc b/src/ui/element_menu.cc
+index 079f469..b9a967d 100644
+--- a/src/ui/element_menu.cc
++++ b/src/ui/element_menu.cc
+@@ -72,11 +72,11 @@ ElementMenu::ElementMenu() :
+ m_entry(entry_invalid) {
+
+ // Move bindings into a function that defines default bindings.
+- m_bindings[KEY_LEFT] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
+- m_bindings[KEY_RIGHT] = m_bindings['F' - '@'] = std::bind(&ElementMenu::entry_select, this);
+-
+- m_bindings[KEY_UP] = m_bindings['P' - '@'] = std::bind(&ElementMenu::entry_prev, this);
+- m_bindings[KEY_DOWN] = m_bindings['N' - '@'] = std::bind(&ElementMenu::entry_next, this);
++ m_bindings[KEY_LEFT] = m_bindings['h'] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
++ m_bindings[KEY_RIGHT] = m_bindings['l'] = m_bindings['F' - '@'] = std::bind(&ElementMenu::entry_select, this);
++
++ m_bindings[KEY_UP] = m_bindings['k'] = m_bindings['P' - '@'] = std::bind(&ElementMenu::entry_prev, this);
++ m_bindings[KEY_DOWN] = m_bindings['j'] = m_bindings['N' - '@'] = std::bind(&ElementMenu::entry_next, this);
+ }
+
+ ElementMenu::~ElementMenu() {
+diff --git a/src/ui/element_peer_list.cc b/src/ui/element_peer_list.cc
+index 8e3ff09..3326508 100644
+--- a/src/ui/element_peer_list.cc
++++ b/src/ui/element_peer_list.cc
+@@ -76,14 +76,14 @@ ElementPeerList::ElementPeerList(core::Download* d) :
+
+ m_elementInfo->slot_exit(std::bind(&ElementPeerList::activate_display, this, DISPLAY_LIST));
+
+- m_bindings['k'] = std::bind(&ElementPeerList::receive_disconnect_peer, this);
++ m_bindings['K'] = std::bind(&ElementPeerList::receive_disconnect_peer, this);
+ m_bindings['*'] = std::bind(&ElementPeerList::receive_snub_peer, this);
+ m_bindings['B'] = std::bind(&ElementPeerList::receive_ban_peer, this);
+- m_bindings[KEY_LEFT] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
+- m_bindings[KEY_RIGHT] = m_bindings['F' - '@'] = std::bind(&ElementPeerList::activate_display, this, DISPLAY_INFO);
++ m_bindings[KEY_LEFT] = m_bindings['h'] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
++ m_bindings[KEY_RIGHT] = m_bindings['l'] = m_bindings['F' - '@'] = std::bind(&ElementPeerList::activate_display, this, DISPLAY_INFO);
+
+- m_bindings[KEY_UP] = m_bindings['P' - '@'] = std::bind(&ElementPeerList::receive_prev, this);
+- m_bindings[KEY_DOWN] = m_bindings['N' - '@'] = std::bind(&ElementPeerList::receive_next, this);
++ m_bindings[KEY_UP] = m_bindings['k'] = m_bindings['P' - '@'] = std::bind(&ElementPeerList::receive_prev, this);
++ m_bindings[KEY_DOWN] = m_bindings['j'] = m_bindings['N' - '@'] = std::bind(&ElementPeerList::receive_next, this);
+ }
+
+ ElementPeerList::~ElementPeerList() {
+diff --git a/src/ui/element_text.cc b/src/ui/element_text.cc
+index f1f3dea..ba8529d 100644
+--- a/src/ui/element_text.cc
++++ b/src/ui/element_text.cc
+@@ -54,7 +54,8 @@ ElementText::ElementText(rpc::target_type target) :
+ m_columnWidth(0) {
+
+ // Move bindings into a function that defines default bindings.
+- m_bindings[KEY_LEFT] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
++ m_bindings[KEY_LEFT] = m_bindings['h'] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
++
+
+ // m_bindings[KEY_UP] = std::bind(this, &ElementText::entry_prev);
+ // m_bindings[KEY_DOWN] = std::bind(this, &ElementText::entry_next);
+diff --git a/src/ui/element_tracker_list.cc b/src/ui/element_tracker_list.cc
+index c048165..16590da 100644
+--- a/src/ui/element_tracker_list.cc
++++ b/src/ui/element_tracker_list.cc
+@@ -54,13 +54,13 @@ ElementTrackerList::ElementTrackerList(core::Download* d) :
+ m_window(NULL),
+ m_focus(0) {
+
+- m_bindings[KEY_LEFT] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
++ m_bindings[KEY_LEFT] = m_bindings['h'] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
+
+ m_bindings[' '] = std::bind(&ElementTrackerList::receive_cycle_group, this);
+ m_bindings['*'] = std::bind(&ElementTrackerList::receive_disable, this);
+
+- m_bindings[KEY_DOWN] = m_bindings['N' - '@'] = std::bind(&ElementTrackerList::receive_next, this);
+- m_bindings[KEY_UP] = m_bindings['P' - '@'] = std::bind(&ElementTrackerList::receive_prev, this);
++ m_bindings[KEY_DOWN] = m_bindings['j'] = m_bindings['N' - '@'] = std::bind(&ElementTrackerList::receive_next, this);
++ m_bindings[KEY_UP] = m_bindings['k'] = m_bindings['P' - '@'] = std::bind(&ElementTrackerList::receive_prev, this);
+ }
+
+ void
+diff --git a/src/ui/element_transfer_list.cc b/src/ui/element_transfer_list.cc
+index cd0ae55..6618f1b 100644
+--- a/src/ui/element_transfer_list.cc
++++ b/src/ui/element_transfer_list.cc
+@@ -52,10 +52,10 @@ ElementTransferList::ElementTransferList(core::Download* d) :
+ m_window(NULL),
+ m_focus(0) {
+
+- m_bindings[KEY_LEFT] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
++ m_bindings[KEY_LEFT] = m_bindings['h'] = m_bindings['B' - '@'] = std::bind(&slot_type::operator(), &m_slot_exit);
+
+- m_bindings[KEY_DOWN] = std::bind(&ElementTransferList::receive_next, this);
+- m_bindings[KEY_UP] = std::bind(&ElementTransferList::receive_prev, this);
++ m_bindings[KEY_DOWN] = m_bindings['j'] = std::bind(&ElementTransferList::receive_next, this);
++ m_bindings[KEY_UP] = m_bindings['k'] = std::bind(&ElementTransferList::receive_prev, this);
+ m_bindings[KEY_NPAGE] = std::bind(&ElementTransferList::receive_pagenext, this);
+ m_bindings[KEY_PPAGE] = std::bind(&ElementTransferList::receive_pageprev, this);
+ }