diff --git a/rak/functional.h b/rak/functional.h index e5fa44ce..cc149dbf 100644 --- a/rak/functional.h +++ b/rak/functional.h @@ -37,6 +37,7 @@ #ifndef RAK_FUNCTIONAL_H #define RAK_FUNCTIONAL_H +#include #include namespace rak { diff --git a/scripts/common.m4 b/scripts/common.m4 index bec91f02..fe7ef3c3 100644 --- a/scripts/common.m4 +++ b/scripts/common.m4 @@ -183,7 +183,7 @@ AC_DEFUN([TORRENT_CHECK_MADVISE], [ AC_DEFUN([TORRENT_CHECK_EXECINFO], [ AC_MSG_CHECKING(for execinfo.h) - AC_RUN_IFELSE( + AC_LINK_IFELSE( [[#include int main() { backtrace((void**)0, 0); backtrace_symbols((char**)0, 0); return 0;} ]], diff --git a/src/command_network.cc b/src/command_network.cc index 3eca1b01..551fc9cf 100644 --- a/src/command_network.cc +++ b/src/command_network.cc @@ -261,10 +261,10 @@ apply_scgi(const std::string& arg, int type) { break; } - rak::address_info::free_address_info(ai); + if (ai != NULL) rak::address_info::free_address_info(ai); } catch (torrent::local_error& e) { - rak::address_info::free_address_info(ai); + if (ai != NULL) rak::address_info::free_address_info(ai); throw torrent::input_error(e.what()); } diff --git a/src/command_ui.cc b/src/command_ui.cc index d1a19df5..b649be1e 100644 --- a/src/command_ui.cc +++ b/src/command_ui.cc @@ -36,6 +36,7 @@ #include "config.h" +#include #include #include #include diff --git a/src/core/download.cc b/src/core/download.cc index 42520742..0a2254bb 100644 --- a/src/core/download.cc +++ b/src/core/download.cc @@ -84,11 +84,12 @@ Download::~Download() { void Download::enable_udp_trackers(bool state) { for (torrent::TrackerList::iterator itr = m_download.tracker_list()->begin(), last = m_download.tracker_list()->end(); itr != last; ++itr) - if ((*itr)->type() == torrent::Tracker::TRACKER_UDP) + if ((*itr)->type() == torrent::Tracker::TRACKER_UDP) { if (state) (*itr)->enable(); else (*itr)->disable(); + } } uint32_t diff --git a/src/core/download_store.cc b/src/core/download_store.cc index 9e51b1b1..4fb6a3b0 100644 --- a/src/core/download_store.cc +++ b/src/core/download_store.cc @@ -71,11 +71,12 @@ DownloadStore::enable(bool lock) { else m_lockfile.set_path(std::string()); - if (!m_lockfile.try_lock()) + if (!m_lockfile.try_lock()) { if (rak::error_number::current().is_bad_path()) throw torrent::input_error("Could not lock session directory: \"" + m_path + "\", " + rak::error_number::current().c_str()); else throw torrent::input_error("Could not lock session directory: \"" + m_path + "\", held by \"" + m_lockfile.locked_by_as_string() + "\"."); + } } void diff --git a/src/core/manager.cc b/src/core/manager.cc index 399d7d8b..5ec5feb4 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -383,7 +383,8 @@ Manager::receive_http_failed(std::string msg) { void Manager::try_create_download(const std::string& uri, int flags, const command_list_type& commands) { // If the path was attempted loaded before, skip it. - if (!(flags & create_raw_data) && + if ((flags & create_tied) && + !(flags & create_raw_data) && !is_network_uri(uri) && !file_status_cache()->insert(uri, 0)) return; diff --git a/src/display/canvas.cc b/src/display/canvas.cc index d532c125..4e621dfe 100644 --- a/src/display/canvas.cc +++ b/src/display/canvas.cc @@ -57,17 +57,31 @@ void Canvas::print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes) { move(x, y); + attr_t org_attr; + short org_pair; + wattr_get(m_window, &org_attr, &org_pair, NULL); + attributes_list::const_iterator attrItr = attributes->begin(); - Attributes current = Attributes(first, Attributes::a_normal, Attributes::color_default); + wattr_set(m_window, Attributes::a_normal, Attributes::color_default, NULL); while (first != last) { - if (attrItr != attributes->end() && first >= attrItr->position()) - current = *attrItr++; + const char* next = last; - waddch(m_window, *first++ | current.attributes()); + if (attrItr != attributes->end()) { + next = attrItr->position(); + + if (first >= next) { + wattr_set(m_window, attrItr->attributes(), attrItr->colors(), NULL); + ++attrItr; + } + } + + print("%.*s", next - first, first); + first = next; } // Reset the color. + wattr_set(m_window, org_attr, org_pair, NULL); } void diff --git a/src/display/canvas.h b/src/display/canvas.h index fb438a62..3f3ec286 100644 --- a/src/display/canvas.h +++ b/src/display/canvas.h @@ -86,6 +86,7 @@ public: // since the string shall always be a C string choosen at // compiletime. Might cause extra copying of the string? + void print(const char* str, ...); void print(unsigned int x, unsigned int y, const char* str, ...); void print_attributes(unsigned int x, unsigned int y, const char* first, const char* last, const attributes_list* attributes); @@ -95,6 +96,8 @@ public: void set_attr(unsigned int x, unsigned int y, unsigned int n, int attr, int color) { mvwchgat(m_window, y, x, n, attr, color, NULL); } + void set_default_attributes(int attr) { wattrset(m_window, attr); } + // Initialize stdscr. static void initialize(); static void cleanup(); @@ -115,6 +118,15 @@ private: WINDOW* m_window; }; +inline void +Canvas::print(const char* str, ...) { + va_list arglist; + + va_start(arglist, str); + vw_printw(m_window, const_cast(str), arglist); + va_end(arglist); +} + inline void Canvas::print(unsigned int x, unsigned int y, const char* str, ...) { va_list arglist; diff --git a/src/display/text_element_value.cc b/src/display/text_element_value.cc index 4de279b9..ae5efa39 100644 --- a/src/display/text_element_value.cc +++ b/src/display/text_element_value.cc @@ -36,6 +36,8 @@ #include "config.h" +#include + #include "globals.h" #include "text_element_value.h" diff --git a/src/display/window_file_list.cc b/src/display/window_file_list.cc index 7f375be9..6e8b30e2 100644 --- a/src/display/window_file_list.cc +++ b/src/display/window_file_list.cc @@ -57,22 +57,61 @@ WindowFileList::WindowFileList(const ui::ElementFileList* element) : m_element(element) { } -/* +// Convert std::string to std::wstring of given width (in screen positions), +// taking into account that some characters may be occupying two screen positions. std::wstring -hack_wstring(const std::string& src) { - size_t length = ::mbstowcs(NULL, src.c_str(), src.size()); +wstring_width(const std::string& i_str, int width) { + wchar_t result[width + 1]; + size_t length = std::mbstowcs(result, i_str.c_str(), width); - if (length == (size_t)-1) - return std::wstring(L""); + // If not valid UTF-8 encoding, at least copy the printable characters. + if (length == (size_t)-1) { + wchar_t* out = result; - std::wstring dest; - dest.resize(length); - - ::mbstowcs(&*dest.begin(), src.c_str(), src.size()); + for (std::string::const_iterator itr = i_str.begin(); itr != i_str.end(); ++itr) + if (!std::isprint(*itr, std::locale::classic())) + *out++ = '?'; + else + *out++ = *itr; - return dest; + *out = 0; + } + + int swidth = wcswidth(result, width); + + // Limit to width if it's too wide already. + if (swidth == -1 || swidth > width) { + length = swidth = 0; + + while (result[length]) { + int next = ::wcwidth(result[length]); + + // Unprintable character? + if (next == -1) { + result[length] = '?'; + next = 1; + } + + if (swidth + next > width) { + result[length] = 0; + break; + } + + length++; + swidth += next; + } + } + + // Pad with spaces to given width. + while (swidth < width && length <= (unsigned int)width) { + result[length++] = ' '; + swidth++; + } + + result[length] = 0; + + return result; } -*/ void WindowFileList::redraw() { @@ -115,6 +154,8 @@ WindowFileList::redraw() { } unsigned int pos = 0; + int filenameWidth = m_canvas->width() - 16; + m_canvas->print(0, pos++, "Cmp Pri Size Filename"); while (pos != m_canvas->height()) { @@ -123,20 +164,19 @@ WindowFileList::redraw() { if (itr == iterator(fl->end())) break; + m_canvas->set_default_attributes(itr == m_element->selected() ? is_focused() ? A_REVERSE : A_BOLD : A_NORMAL); + if (itr.is_empty()) { - m_canvas->print(16, pos, "EMPTY"); + m_canvas->print(0, pos, "%*c%-*s", 16, ' ', filenameWidth, "EMPTY"); } else if (itr.is_entering()) { - m_canvas->print(16 + itr.depth(), pos, "\\ %s", - itr.depth() < (*itr)->path()->size() ? (*itr)->path()->at(itr.depth()).c_str() : "UNKNOWN"); + m_canvas->print(0, pos, "%*c %ls", 16 + itr.depth(), '\\', + itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN"); } else if (itr.is_leaving()) { - m_canvas->print(16 + itr.depth() - 1, pos, "/"); + m_canvas->print(0, pos, "%*c %-*s", 16 + (itr.depth() - 1), '/', filenameWidth - (itr.depth() - 1), ""); } else if (itr.is_file()) { - char buffer[std::max(m_canvas->width() + 1, 256)]; - Canvas::attributes_list attributes; - torrent::File* e = *itr; const char* priority; @@ -148,33 +188,26 @@ WindowFileList::redraw() { default: priority = "BUG"; break; }; - sprintf(buffer, "%3d %s ", done_percentage(e), priority); + m_canvas->print(0, pos, "%3d %s ", done_percentage(e), priority); int64_t val = e->size_bytes(); - if (val < (int64_t(1000) << 20)) - sprintf(buffer + 8, "%5.1f M", (double)val / (int64_t(1) << 20)); + if (val < (int64_t(1000) << 10)) + m_canvas->print(8, pos, "%5.1f K", (double)val / (int64_t(1) << 10)); + else if (val < (int64_t(1000) << 20)) + m_canvas->print(8, pos, "%5.1f M", (double)val / (int64_t(1) << 20)); else if (val < (int64_t(1000) << 30)) - sprintf(buffer + 8, "%5.1f G", (double)val / (int64_t(1) << 30)); + m_canvas->print(8, pos, "%5.1f G", (double)val / (int64_t(1) << 30)); else - sprintf(buffer + 8, "%5.1f T", (double)val / (int64_t(1) << 40)); + m_canvas->print(8, pos, "%5.1f T", (double)val / (int64_t(1) << 40)); - std::fill_n(buffer + 15, 64, ' '); - - int first = 16 + std::min(itr.depth(), 8); - int last = std::max(m_canvas->width() + 1, 16 + 12); - - snprintf(buffer + first, last - first, "| %s", - itr.depth() < (*itr)->path()->size() ? (*itr)->path()->at(itr.depth()).c_str() : "UNKNOWN"); - - m_canvas->print_attributes(0, pos, buffer, buffer + std::strlen(buffer), &attributes); + m_canvas->print(15, pos, "%*c %ls", 1 + itr.depth(), '|', + itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN"); } else { m_canvas->print(0, pos, "BORK BORK"); } - - if (itr == m_element->selected()) - m_canvas->set_attr(0, pos, m_canvas->width(), is_focused() ? A_REVERSE : A_BOLD, COLOR_PAIR(0)); + m_canvas->set_default_attributes(A_NORMAL); pos++; first = (first + 1) % (m_canvas->height() - 1); diff --git a/src/rpc/parse.cc b/src/rpc/parse.cc index d6c77749..10abe425 100644 --- a/src/rpc/parse.cc +++ b/src/rpc/parse.cc @@ -36,6 +36,7 @@ #include "config.h" +#include #include #include #include