All patches in this commit were from Josef Drexler.

* Fixes a segfault when configure finds execinfo.h.

* Fix compile errors and warnings with g++ 4.3.x.

* Fixes an interoperability issue in the get_peers handling, now it
behaves according to the clarified BEP-0005. Also fixes a minor issue
of not being able to generate error packets.

* Fix a crash in scgi_local or scgi_port when calling freeaddrinfo
with a NULL pointer.

* Only check the filename cache for loading tied torrents (e.g. from
watch dirs) but not manually loaded ones via <enter>/<bs>, to allow
loading those again (ticket #1227).

* Fix display of multi-byte characters with attributes (i.e. utf-8
filenames in the file list), and make the list aware of characters
occupying two screen positions.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1064 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2008-08-26 20:42:57 +00:00
parent 5a700f34d9
commit c627d6dc0c
12 changed files with 112 additions and 45 deletions
+1
View File
@@ -37,6 +37,7 @@
#ifndef RAK_FUNCTIONAL_H
#define RAK_FUNCTIONAL_H
#include <cstddef>
#include <functional>
namespace rak {
+1 -1
View File
@@ -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 <execinfo.h>
int main() { backtrace((void**)0, 0); backtrace_symbols((char**)0, 0); return 0;}
]],
+2 -2
View File
@@ -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());
}
+1
View File
@@ -36,6 +36,7 @@
#include "config.h"
#include <ctime>
#include <rak/functional.h>
#include <rak/functional_fun.h>
#include <sigc++/adaptors/bind.h>
+2 -1
View File
@@ -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
+2 -1
View File
@@ -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
+2 -1
View File
@@ -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;
+18 -4
View File
@@ -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
+12
View File
@@ -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<char*>(str), arglist);
va_end(arglist);
}
inline void
Canvas::print(unsigned int x, unsigned int y, const char* str, ...) {
va_list arglist;
+2
View File
@@ -36,6 +36,8 @@
#include "config.h"
#include <ctime>
#include "globals.h"
#include "text_element_value.h"
+68 -35
View File
@@ -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"<invalid>");
// 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<unsigned int>(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<unsigned int>(itr.depth(), 8);
int last = std::max<unsigned int>(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);
+1
View File
@@ -36,6 +36,7 @@
#include "config.h"
#include <cstring>
#include <locale>
#include <rak/path.h>
#include <torrent/exceptions.h>