summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'SwifTools')
-rw-r--r--SwifTools/Application/UnitTest/ApplicationPathProviderTest.cpp5
-rw-r--r--SwifTools/Application/WindowsApplicationPathProvider.cpp21
-rw-r--r--SwifTools/Application/WindowsApplicationPathProvider.h15
-rw-r--r--SwifTools/Cocoa/CocoaAction.h4
-rw-r--r--SwifTools/Cocoa/CocoaAction.mm14
-rw-r--r--SwifTools/CrashReporter.cpp23
-rw-r--r--SwifTools/HunspellChecker.cpp55
-rw-r--r--SwifTools/HunspellChecker.h27
-rw-r--r--SwifTools/Idle/IdleQuerierTest/IdleQuerierTest.cpp3
-rw-r--r--SwifTools/Idle/MacOSXIdleQuerier.cpp3
-rw-r--r--SwifTools/Linkify.cpp53
-rw-r--r--SwifTools/Linkify.h14
-rw-r--r--SwifTools/MacOSXChecker.h22
-rw-r--r--SwifTools/MacOSXChecker.mm54
-rw-r--r--SwifTools/Notifier/GNTPNotifier.cpp5
-rw-r--r--SwifTools/Notifier/GrowlNotifier.mm2
-rw-r--r--SwifTools/Notifier/GrowlNotifierDelegate.mm2
-rw-r--r--SwifTools/SConscript22
-rw-r--r--SwifTools/SpellChecker.h30
-rw-r--r--SwifTools/SpellCheckerFactory.cpp41
-rw-r--r--SwifTools/SpellCheckerFactory.h24
-rw-r--r--SwifTools/SpellParser.cpp70
-rw-r--r--SwifTools/SpellParser.h31
-rw-r--r--SwifTools/URIHandler/MacOSXURIHandler.mm11
-rw-r--r--SwifTools/URIHandler/UnitTest/XMPPURITest.cpp8
-rw-r--r--SwifTools/UnitTest/LastLineTrackerTest.cpp2
-rw-r--r--SwifTools/UnitTest/LinkifyTest.cpp61
-rw-r--r--SwifTools/UnitTest/SConscript5
-rw-r--r--SwifTools/UnitTest/SpellParserTest.cpp51
-rw-r--r--SwifTools/UnitTest/TabCompleteTest.cpp2
30 files changed, 620 insertions, 60 deletions
diff --git a/SwifTools/Application/UnitTest/ApplicationPathProviderTest.cpp b/SwifTools/Application/UnitTest/ApplicationPathProviderTest.cpp
index 5eb0e16..e7a47a7 100644
--- a/SwifTools/Application/UnitTest/ApplicationPathProviderTest.cpp
+++ b/SwifTools/Application/UnitTest/ApplicationPathProviderTest.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -9,6 +9,7 @@
#include <string>
#include <boost/algorithm/string.hpp>
+#include <Swiften/Base/Path.h>
#include <SwifTools/Application/PlatformApplicationPathProvider.h>
using namespace Swift;
@@ -40,7 +41,7 @@ class ApplicationPathProviderTest : public CppUnit::TestFixture {
void testGetExecutableDir() {
boost::filesystem::path dir = testling_->getExecutableDir();
CPPUNIT_ASSERT(boost::filesystem::is_directory(dir));
- CPPUNIT_ASSERT(boost::ends_with(dir.string(), "UnitTest"));
+ CPPUNIT_ASSERT(boost::ends_with(pathToString(dir), "UnitTest"));
}
private:
diff --git a/SwifTools/Application/WindowsApplicationPathProvider.cpp b/SwifTools/Application/WindowsApplicationPathProvider.cpp
index 8514fa7..2c61208 100644
--- a/SwifTools/Application/WindowsApplicationPathProvider.cpp
+++ b/SwifTools/Application/WindowsApplicationPathProvider.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -7,6 +7,8 @@
#include <SwifTools/Application/WindowsApplicationPathProvider.h>
#include <windows.h>
+#include <cassert>
+#include <Swiften/Base/String.h>
namespace Swift {
@@ -15,4 +17,21 @@ WindowsApplicationPathProvider::WindowsApplicationPathProvider(const std::string
resourceDirs.push_back(getExecutableDir() / "../resources"); // Development
}
+boost::filesystem::path WindowsApplicationPathProvider::getDataDir() const {
+ wchar_t* appDirRaw = _wgetenv(L"APPDATA");
+ assert(appDirRaw);
+ boost::filesystem::path result(
+ boost::filesystem::path(appDirRaw) / getApplicationName());
+ boost::filesystem::create_directory(result);
+ return result;
+}
+
+boost::filesystem::path WindowsApplicationPathProvider::getHomeDir() const {
+ //FIXME: This should be My Documents
+ wchar_t* homeDirRaw = _wgetenv(L"USERPROFILE");
+ assert(homeDirRaw);
+ return boost::filesystem::path(homeDirRaw);
+}
+
+
}
diff --git a/SwifTools/Application/WindowsApplicationPathProvider.h b/SwifTools/Application/WindowsApplicationPathProvider.h
index f288326..a4e8668 100644
--- a/SwifTools/Application/WindowsApplicationPathProvider.h
+++ b/SwifTools/Application/WindowsApplicationPathProvider.h
@@ -13,19 +13,8 @@ namespace Swift {
public:
WindowsApplicationPathProvider(const std::string& name);
- boost::filesystem::path getDataDir() const {
- char* appDirRaw = getenv("APPDATA");
- boost::filesystem::path result(boost::filesystem::path(appDirRaw) / getApplicationName());
- boost::filesystem::create_directory(result);
- return result;
- }
-
- boost::filesystem::path getHomeDir() const {
- //FIXME: This should be My Documents
-
- char* homeDirRaw = getenv("USERPROFILE");
- return boost::filesystem::path(homeDirRaw);
- }
+ boost::filesystem::path getDataDir() const;
+ boost::filesystem::path getHomeDir() const;
virtual std::vector<boost::filesystem::path> getResourceDirs() const {
return resourceDirs;
diff --git a/SwifTools/Cocoa/CocoaAction.h b/SwifTools/Cocoa/CocoaAction.h
index a46ef7c..0ef993e 100644
--- a/SwifTools/Cocoa/CocoaAction.h
+++ b/SwifTools/Cocoa/CocoaAction.h
@@ -9,9 +9,7 @@
#include <Cocoa/Cocoa.h>
#include <boost/function.hpp>
-@interface CocoaAction : NSObject {
- boost::function<void ()>* function;
-}
+@interface CocoaAction : NSObject
/**
* Acquires ownership of 'f'.
diff --git a/SwifTools/Cocoa/CocoaAction.mm b/SwifTools/Cocoa/CocoaAction.mm
index d560787..7162cd2 100644
--- a/SwifTools/Cocoa/CocoaAction.mm
+++ b/SwifTools/Cocoa/CocoaAction.mm
@@ -1,18 +1,20 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <SwifTools/Cocoa/CocoaAction.h>
-@implementation CocoaAction
+@implementation CocoaAction {
+ boost::function<void ()>* function;
+}
- (id) initWithFunction: (boost::function<void()>*) f {
- if ([super init]) {
- function = f;
- }
- return self;
+ if ((self = [super init])) {
+ function = f;
+ }
+ return self;
}
- (void) dealloc {
diff --git a/SwifTools/CrashReporter.cpp b/SwifTools/CrashReporter.cpp
index 4a07e40..f47ab33 100644
--- a/SwifTools/CrashReporter.cpp
+++ b/SwifTools/CrashReporter.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012 Remko Tronçon
+ * Copyright (c) 2012-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -7,6 +7,7 @@
#include <SwifTools/CrashReporter.h>
#include <Swiften/Base/Platform.h>
+#include <Swiften/Base/Path.h>
#if defined(HAVE_BREAKPAD)
@@ -51,16 +52,18 @@ CrashReporter::CrashReporter(const boost::filesystem::path& path) {
p = boost::make_shared<Private>();
#if defined(SWIFTEN_PLATFORM_WINDOWS)
// FIXME: Need UTF8 conversion from string to wstring
- std::string pathString = path.string();
- p->handler = boost::make_shared<google_breakpad::ExceptionHandler>(
- std::wstring(pathString.begin(), pathString.end()),
- (google_breakpad::ExceptionHandler::FilterCallback) 0,
- handleDump,
- (void*) 0,
- google_breakpad::ExceptionHandler::HANDLER_ALL);
+ std::string pathString = pathToString(path);
+ p->handler = boost::shared_ptr<google_breakpad::ExceptionHandler>(
+ // Not using make_shared, because 'handleDump' seems to have problems with VC2010
+ new google_breakpad::ExceptionHandler(
+ std::wstring(pathString.begin(), pathString.end()),
+ (google_breakpad::ExceptionHandler::FilterCallback) 0,
+ handleDump,
+ (void*) 0,
+ google_breakpad::ExceptionHandler::HANDLER_ALL));
// Turning it off for Mac, because it doesn't really help us
//#elif defined(SWIFTEN_PLATFORM_MACOSX)
-// p->handler = boost::make_shared<google_breakpad::ExceptionHandler>(path.string(), (google_breakpad::ExceptionHandler::FilterCallback) 0, handleDump, (void*) 0, true, (const char*) 0);
+// p->handler = boost::make_shared<google_breakpad::ExceptionHandler>(pathToString(path), (google_breakpad::ExceptionHandler::FilterCallback) 0, handleDump, (void*) 0, true, (const char*) 0);
#endif
}
@@ -71,6 +74,6 @@ CrashReporter::CrashReporter(const boost::filesystem::path& path) {
// Dummy implementation
namespace Swift {
CrashReporter::CrashReporter(const boost::filesystem::path&) {}
-};
+}
#endif
diff --git a/SwifTools/HunspellChecker.cpp b/SwifTools/HunspellChecker.cpp
new file mode 100644
index 0000000..ecd352e
--- /dev/null
+++ b/SwifTools/HunspellChecker.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Vlad Voicu
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <SwifTools/HunspellChecker.h>
+
+#include <algorithm>
+#include <hunspell/hunspell.hxx>
+#include <boost/algorithm/string.hpp>
+
+
+namespace Swift {
+
+HunspellChecker::HunspellChecker(const char* affix_path, const char* dictionary_path) {
+ speller_ = new Hunspell(affix_path, dictionary_path);
+}
+
+HunspellChecker::~HunspellChecker() {
+ delete speller_;
+}
+
+bool HunspellChecker::isCorrect(const std::string& word) {
+ return speller_->spell(word.c_str());
+}
+
+void HunspellChecker::getSuggestions(const std::string& word, std::vector<std::string>& list) {
+ char **suggestList;
+ int words_returned;
+ if (!word.empty()) {
+ words_returned = speller_->suggest(&suggestList, word.c_str());
+ }
+ for (int i = 0; i < words_returned; ++i) {
+ list.push_back(suggestList[i]);
+ free(suggestList[i]);
+ }
+ free(suggestList);
+}
+
+void HunspellChecker::checkFragment(const std::string& fragment, PositionPairList& misspelledPositions) {
+ if (!fragment.empty()) {
+ parser_->check(fragment, misspelledPositions);
+ for (PositionPairList::iterator it = misspelledPositions.begin(); it != misspelledPositions.end();) {
+ if (isCorrect(fragment.substr(boost::get<0>(*it), boost::get<1>(*it) - boost::get<0>(*it)))) {
+ it = misspelledPositions.erase(it);
+ }
+ else {
+ ++it;
+ }
+ }
+ }
+}
+
+}
diff --git a/SwifTools/HunspellChecker.h b/SwifTools/HunspellChecker.h
new file mode 100644
index 0000000..12c0485
--- /dev/null
+++ b/SwifTools/HunspellChecker.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Vlad Voicu
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <vector>
+#include <boost/algorithm/string.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <SwifTools/SpellChecker.h>
+
+#pragma once
+
+class Hunspell;
+
+namespace Swift {
+ class HunspellChecker : public SpellChecker {
+ public:
+ HunspellChecker(const char* affix_path, const char* dict_path);
+ virtual ~HunspellChecker();
+ virtual bool isCorrect(const std::string& word);
+ virtual void getSuggestions(const std::string& word, std::vector<std::string>& list);
+ virtual void checkFragment(const std::string& fragment, PositionPairList& misspelledPositions);
+ private:
+ Hunspell* speller_;
+ };
+}
diff --git a/SwifTools/Idle/IdleQuerierTest/IdleQuerierTest.cpp b/SwifTools/Idle/IdleQuerierTest/IdleQuerierTest.cpp
index df233a2..41238a0 100644
--- a/SwifTools/Idle/IdleQuerierTest/IdleQuerierTest.cpp
+++ b/SwifTools/Idle/IdleQuerierTest/IdleQuerierTest.cpp
@@ -5,6 +5,7 @@
*/
#include <iostream>
+#include <cassert>
#include <SwifTools/Idle/PlatformIdleQuerier.h>
#include <Swiften/Base/sleep.h>
@@ -17,6 +18,6 @@ int main() {
std::cout << "Idle time: " << querier.getIdleTimeSeconds() << std::endl;
Swift::sleep(1000);
}
-
+ assert(false);
return 0;
}
diff --git a/SwifTools/Idle/MacOSXIdleQuerier.cpp b/SwifTools/Idle/MacOSXIdleQuerier.cpp
index 233d7c6..8eaece6 100644
--- a/SwifTools/Idle/MacOSXIdleQuerier.cpp
+++ b/SwifTools/Idle/MacOSXIdleQuerier.cpp
@@ -10,6 +10,7 @@
#include <cassert>
#include <iostream>
+#include <boost/numeric/conversion/cast.hpp>
#include <CoreFoundation/CoreFoundation.h>
namespace Swift {
@@ -28,7 +29,7 @@ int MacOSXIdleQuerier::getIdleTimeSeconds() {
assert(result);
(void) result;
CFRelease(property);
- return idle / 1000000000;
+ return boost::numeric_cast<int>(idle / 1000000000);
}
}
diff --git a/SwifTools/Linkify.cpp b/SwifTools/Linkify.cpp
index 906026d..8ecbb09 100644
--- a/SwifTools/Linkify.cpp
+++ b/SwifTools/Linkify.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -49,4 +49,55 @@ std::string Linkify::linkify(const std::string& input) {
return std::string(result.str());
}
+std::pair<std::vector<std::string>, size_t> Linkify::splitLink(const std::string& input) {
+ std::vector<std::string> result;
+ std::pair<std::vector<std::string>, size_t> pair;
+ std::vector<char> currentURL;
+ bool inURL = false;
+ size_t urlStartsAt = 0;
+ for (size_t i = 0; i < input.size(); ++i) {
+ char c = input[i];
+ if (inURL) {
+ if (c != ' ' && c != '\t' && c != '\n' && !(c == '*' && i == input.size() - 1 && input[0] == '*')) {
+ // Keep parsing
+ }
+ else {
+ std::string url(input.substr(urlStartsAt, i - urlStartsAt));
+ result.push_back(url);
+ inURL = false;
+ size_t remaining = input.size() - i;
+ if (remaining > 0) {
+ result.push_back(input.substr(i, remaining));
+ }
+ pair.first = result;
+ pair.second = urlStartsAt == 0 ? 0 : 1;
+ return pair;
+ }
+ }
+ else {
+ if (boost::regex_match(input.substr(i, 8), linkifyRegexp)) {
+ urlStartsAt = i;
+ inURL = true;
+ if (i > 0) {
+ result.push_back(input.substr(0, i));
+ }
+ }
+ else {
+ // Just keep swimming
+ }
+ }
+ }
+ if (urlStartsAt > 0 || inURL) {
+ std::string url(input.substr(urlStartsAt, input.size() - urlStartsAt));
+ result.push_back(url);
+ pair.first = result;
+ pair.second = urlStartsAt == 0 ? 0 : 1;
+ }
+ else {
+ pair.first.push_back(input);
+ pair.second = 1;
+ }
+ return pair;
+}
+
}
diff --git a/SwifTools/Linkify.h b/SwifTools/Linkify.h
index ebe232f..0a9c132 100644
--- a/SwifTools/Linkify.h
+++ b/SwifTools/Linkify.h
@@ -1,15 +1,27 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
+#include <vector>
#include <string>
namespace Swift {
namespace Linkify {
std::string linkify(const std::string&);
+ /**
+ * Parse the string for a URI. The string will be split by the URI, and the segments plus index of the URI returned.
+ * If no URI is found the index will be result.size() (i.e. an invalid index)
+ *
+ * Examples:
+ * "not a URI" -> <<"not a URI">, -1>
+ * "http://swift.im" -> <<"http://swift.im">, 0
+ * " See http://swift.im" -> <<" See ", "http://swift.im">, 1>
+ * "Right, http://swift.im it is" -> <<"Right, ", "http://swift.im", " it is">, 1>
+ */
+ std::pair<std::vector<std::string>, size_t> splitLink(const std::string& text);
}
}
diff --git a/SwifTools/MacOSXChecker.h b/SwifTools/MacOSXChecker.h
new file mode 100644
index 0000000..f2f8ebc
--- /dev/null
+++ b/SwifTools/MacOSXChecker.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <vector>
+#include <boost/tuple/tuple.hpp>
+#include <SwifTools/SpellChecker.h>
+
+namespace Swift {
+ class MacOSXChecker : public SpellChecker {
+ public:
+ MacOSXChecker();
+ virtual ~MacOSXChecker();
+ virtual bool isCorrect(const std::string& word);
+ virtual void getSuggestions(const std::string& word, std::vector<std::string>& list);
+ virtual void checkFragment(const std::string& fragment, PositionPairList& misspelledPositions);
+ };
+}
diff --git a/SwifTools/MacOSXChecker.mm b/SwifTools/MacOSXChecker.mm
new file mode 100644
index 0000000..3e687d1
--- /dev/null
+++ b/SwifTools/MacOSXChecker.mm
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 Tobias Markmann
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <SwifTools/MacOSXChecker.h>
+
+#include <algorithm>
+#include <boost/algorithm/string.hpp>
+
+#include <AppKit/AppKit.h>
+
+namespace Swift {
+
+MacOSXChecker::MacOSXChecker() {
+}
+
+MacOSXChecker::~MacOSXChecker() {
+}
+
+bool MacOSXChecker::isCorrect(const std::string& /*word*/) {
+ // No content since it doesn't seem to be used anywhere.
+ return false;
+}
+
+void MacOSXChecker::getSuggestions(const std::string& word, std::vector<std::string>& list) {
+ NSSpellChecker* spellChecker = [NSSpellChecker sharedSpellChecker];
+ NSString* wordString = [[NSString alloc] initWithUTF8String: word.c_str()];
+ NSArray* suggestions = [spellChecker guessesForWord: wordString];
+ for(unsigned int i = 0; i < [suggestions count]; ++i) {
+ list.push_back(std::string([[suggestions objectAtIndex:i] UTF8String]));
+ }
+ [wordString release];
+}
+
+void MacOSXChecker::checkFragment(const std::string& fragment, PositionPairList& misspelledPositions) {
+ NSSpellChecker* spellChecker = [NSSpellChecker sharedSpellChecker];
+ size_t nextLocation = 0;
+ NSRange range;
+ NSString *fragmentString = [[NSString alloc] initWithUTF8String: fragment.c_str()];
+ do {
+ range = [spellChecker checkSpellingOfString:fragmentString startingAt:static_cast<long>(nextLocation)];
+ if (range.location != NSNotFound) {
+ if (range.location < nextLocation)
+ break;
+ misspelledPositions.push_back(PositionPair(static_cast<int>(range.location), static_cast<int>(range.location + range.length)));
+ nextLocation = range.location + range.length + 1;
+ }
+ } while (range.location != NSNotFound);
+ [fragmentString release];
+}
+
+}
diff --git a/SwifTools/Notifier/GNTPNotifier.cpp b/SwifTools/Notifier/GNTPNotifier.cpp
index 9bc05bd..757594f 100644
--- a/SwifTools/Notifier/GNTPNotifier.cpp
+++ b/SwifTools/Notifier/GNTPNotifier.cpp
@@ -14,6 +14,7 @@
#include <sstream>
#include <Swiften/Base/foreach.h>
+#include <Swiften/Base/Path.h>
#include <Swiften/Network/ConnectionFactory.h>
namespace Swift {
@@ -23,7 +24,7 @@ GNTPNotifier::GNTPNotifier(const std::string& name, const boost::filesystem::pat
std::ostringstream message;
message << "GNTP/1.0 REGISTER NONE\r\n";
message << "Application-Name: " << name << "\r\n";
- message << "Application-Icon: file://" << icon.string() << "\r\n";
+ message << "Application-Icon: file://" << pathToString(icon) << "\r\n";
message << "Notifications-Count: " << getAllTypes().size() << "\r\n";
std::vector<Notifier::Type> defaultTypes = getDefaultTypes();
std::vector<Notifier::Type> allTypes = getAllTypes();
@@ -59,7 +60,7 @@ void GNTPNotifier::showMessage(Type type, const std::string& subject, const std:
message << "Notification-Name: " << typeToString(type) << "\r\n";
message << "Notification-Title: " << subject << "\r\n";
message << "Notification-Text: " << description << "\r\n";
- message << "Notification-Icon: " << picture.string() << "\r\n";
+ message << "Notification-Icon: " << pathToString(picture) << "\r\n";
message << "\r\n";
send(message.str());
}
diff --git a/SwifTools/Notifier/GrowlNotifier.mm b/SwifTools/Notifier/GrowlNotifier.mm
index c1996d9..2ababf4 100644
--- a/SwifTools/Notifier/GrowlNotifier.mm
+++ b/SwifTools/Notifier/GrowlNotifier.mm
@@ -65,7 +65,7 @@ GrowlNotifier::~GrowlNotifier() {
void GrowlNotifier::showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picturePath, boost::function<void()> callback) {
ByteArray picture;
- readByteArrayFromFile(picture, picturePath.string());
+ readByteArrayFromFile(picture, picturePath);
Context* context = new Context(callback);
// Growl sometimes sends timeout notifications twice for the same message. We therefore need
diff --git a/SwifTools/Notifier/GrowlNotifierDelegate.mm b/SwifTools/Notifier/GrowlNotifierDelegate.mm
index 6952cab..e184da6 100644
--- a/SwifTools/Notifier/GrowlNotifierDelegate.mm
+++ b/SwifTools/Notifier/GrowlNotifierDelegate.mm
@@ -8,7 +8,7 @@
#include <SwifTools/Notifier/GrowlNotifier.h>
-@implementation GrowlNotifierDelegate;
+@implementation GrowlNotifierDelegate
@synthesize registrationDictionary;
@synthesize name;
diff --git a/SwifTools/SConscript b/SwifTools/SConscript
index fa2686a..b9822e0 100644
--- a/SwifTools/SConscript
+++ b/SwifTools/SConscript
@@ -30,9 +30,25 @@ if env["SCONS_STAGE"] == "build" :
"TabComplete.cpp",
"LastLineTracker.cpp",
]
+
+ if swiftools_env["HAVE_HUNSPELL"] :
+ swiftools_env.UseFlags(swiftools_env["HUNSPELL_FLAGS"])
+ swiftools_env.Append(CPPDEFINES = ["HAVE_HUNSPELL"])
+ sources += [
+ "SpellCheckerFactory.cpp",
+ "HunspellChecker.cpp",
+ "SpellParser.cpp",
+ ]
+ elif swiftools_env["PLATFORM"] == "darwin" and env["target"] == "native" :
+ sources += [
+ "SpellCheckerFactory.cpp",
+ "MacOSXChecker.mm",
+ "SpellParser.cpp",
+ ]
+
if swiftools_env.get("HAVE_SPARKLE", 0) :
- swiftools_env.MergeFlags(swiftools_env["SPARKLE_FLAGS"])
+ swiftools_env.UseFlags(swiftools_env["SPARKLE_FLAGS"])
swiftools_env.Append(CPPDEFINES = ["HAVE_SPARKLE"])
sources += ["AutoUpdater/SparkleAutoUpdater.mm"]
@@ -45,8 +61,8 @@ if env["SCONS_STAGE"] == "build" :
swiftools_env.Append(CPPDEFINES = ["HAVE_XSS"])
sources += ["Idle/XSSIdleQuerier.cpp"]
- swiftools_env.UseFlags(swiftools_env["BREAKPAD_FLAGS"])
- if env["HAVE_BREAKPAD"] :
+ if env.get("HAVE_BREAKPAD", False) :
+ swiftools_env.UseFlags(swiftools_env["BREAKPAD_FLAGS"])
swiftools_env.Append(CPPDEFINES = ["HAVE_BREAKPAD"])
sources += ["CrashReporter.cpp"]
diff --git a/SwifTools/SpellChecker.h b/SwifTools/SpellChecker.h
new file mode 100644
index 0000000..fd38418
--- /dev/null
+++ b/SwifTools/SpellChecker.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011 Vlad Voicu
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <SwifTools/SpellParser.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <vector>
+
+#pragma once
+
+namespace Swift {
+ class SpellChecker {
+ public:
+ SpellChecker() {
+ parser_ = new SpellParser();
+ }
+ virtual ~SpellChecker() {
+ delete parser_;
+ }
+ virtual bool isCorrect(const std::string& word) = 0;
+ virtual void getSuggestions(const std::string& word, std::vector<std::string>& list) = 0;
+ virtual void checkFragment(const std::string& fragment, PositionPairList& misspelledPositions) = 0;
+ protected:
+ SpellParser *parser_;
+ };
+}
diff --git a/SwifTools/SpellCheckerFactory.cpp b/SwifTools/SpellCheckerFactory.cpp
new file mode 100644
index 0000000..428e1a5
--- /dev/null
+++ b/SwifTools/SpellCheckerFactory.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011 Vlad Voicu
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <boost/filesystem/operations.hpp>
+
+#include <SwifTools/SpellChecker.h>
+#include <SwifTools/HunspellChecker.h>
+#include <SwifTools/SpellCheckerFactory.h>
+#include <Swiften/Base/Platform.h>
+
+#ifdef HAVE_HUNSPELL
+#include <hunspell/hunspell.hxx>
+#elif defined(SWIFTEN_PLATFORM_MACOSX)
+#include <SwifTools/MacOSXChecker.h>
+#endif
+
+namespace Swift {
+
+SpellCheckerFactory::SpellCheckerFactory() {
+}
+
+#ifdef HAVE_HUNSPELL
+SpellChecker* SpellCheckerFactory::createSpellChecker(const std::string& dictFile) {
+ std::string affixFile(dictFile);
+ boost::replace_all(affixFile, ".dic", ".aff");
+ if ((boost::filesystem::exists(dictFile)) && (boost::filesystem::exists(affixFile))) {
+ return new HunspellChecker(affixFile.c_str(), dictFile.c_str());
+ }
+ // If dictionaries don't exist disable the checker
+ return NULL;
+}
+#elif defined(SWIFTEN_PLATFORM_MACOSX)
+SpellChecker* SpellCheckerFactory::createSpellChecker(const std::string& /*dictFile*/) {
+ return new MacOSXChecker();
+}
+#endif
+
+}
diff --git a/SwifTools/SpellCheckerFactory.h b/SwifTools/SpellCheckerFactory.h
new file mode 100644
index 0000000..91118f9
--- /dev/null
+++ b/SwifTools/SpellCheckerFactory.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2011 Vlad Voicu
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/Platform.h>
+
+#ifdef HAVE_HUNSPELL
+#define HAVE_SPELLCHECKER
+#elif defined(SWIFTEN_PLATFORM_MACOSX)
+#define HAVE_SPELLCHECKER
+#endif
+
+namespace Swift {
+ class SpellChecker;
+ class SpellCheckerFactory {
+ public:
+ SpellCheckerFactory();
+ SpellChecker* createSpellChecker(const std::string& dictFile);
+ };
+}
diff --git a/SwifTools/SpellParser.cpp b/SwifTools/SpellParser.cpp
new file mode 100644
index 0000000..8cb42e4
--- /dev/null
+++ b/SwifTools/SpellParser.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011-2013 Vlad Voicu
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <SwifTools/SpellParser.h>
+
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/bind.hpp>
+#include <boost/ref.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <string>
+
+namespace lex = boost::spirit::lex;
+
+namespace Swift {
+
+template <typename Lexer>
+struct word_count_tokens : lex::lexer<Lexer>
+{
+ word_count_tokens()
+ {
+ // define tokens (regular expresions) to match strings
+ // order is important
+ this->self.add
+ ("w{3}.[^ ]+", ID_WWW)
+ ("http:\\/\\/[^ ]+", ID_HTTP)
+ ("\\w{1,}['?|\\-?]?\\w{1,}", ID_WORD)
+ (".", ID_CHAR);
+ }
+};
+
+struct counter
+{
+ typedef bool result_type;
+ // the function operator gets called for each of the matched tokens
+ template <typename Token>
+ bool operator()(Token const& t, PositionPairList& wordPositions, std::size_t& position) const
+ {
+ switch (t.id()) {
+ case ID_WWW:
+ position += boost::numeric_cast<size_t>(t.value().size());
+ break;
+ case ID_HTTP:
+ position += boost::numeric_cast<size_t>(t.value().size());
+ break;
+ case ID_WORD: // matched a word
+ wordPositions.push_back(boost::tuples::make_tuple(position, position + boost::numeric_cast<size_t>(t.value().size())));
+ position += boost::numeric_cast<size_t>(t.value().size());
+ break;
+ case ID_CHAR: // match a simple char
+ ++position;
+ break;
+ }
+ return true; // always continue to tokenize
+ }
+};
+
+void SpellParser::check(const std::string& fragment, PositionPairList& wordPositions) {
+ std::size_t position = 0;
+ // create the token definition instance needed to invoke the lexical analyzer
+ word_count_tokens<lex::lexertl::lexer<> > word_count_functor;
+ char const* first = fragment.c_str();
+ char const* last = &first[fragment.size()];
+ lex::tokenize(first, last, word_count_functor, boost::bind(counter(), _1, boost::ref(wordPositions), boost::ref(position)));
+}
+
+}
diff --git a/SwifTools/SpellParser.h b/SwifTools/SpellParser.h
new file mode 100644
index 0000000..b64565c
--- /dev/null
+++ b/SwifTools/SpellParser.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 Vlad Voicu
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/algorithm/string.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <vector>
+
+namespace Swift {
+ enum token_ids
+ {
+ ID_WWW = 1,
+ ID_HTTP = 2,
+ ID_WORD = 3,
+ ID_CHAR = 4
+ };
+
+ typedef boost::tuple<int, int> PositionPair;
+ typedef std::vector<PositionPair > PositionPairList;
+
+ class SpellParser{
+ public:
+ void check(const std::string& fragment, PositionPairList& wordPositions);
+ };
+}
diff --git a/SwifTools/URIHandler/MacOSXURIHandler.mm b/SwifTools/URIHandler/MacOSXURIHandler.mm
index 0575d47..cdfba33 100644
--- a/SwifTools/URIHandler/MacOSXURIHandler.mm
+++ b/SwifTools/URIHandler/MacOSXURIHandler.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 Remko Tronçon
+ * Copyright (c) 2011-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -12,15 +12,20 @@
using namespace Swift;
@interface MacOSXURIEventHandler : NSObject {
- URIHandler* handler;
}
+
- (id) initWithHandler: (URIHandler*) handler;
- (void) getUrl: (NSAppleEventDescriptor*) event withReplyEvent: (NSAppleEventDescriptor*) replyEvent;
@end
+
@implementation MacOSXURIEventHandler
+ {
+ URIHandler* handler;
+ }
+
- (id) initWithHandler: (URIHandler*) h {
- if ([super init]) {
+ if ((self = [super init])) {
handler = h;
}
return self;
diff --git a/SwifTools/URIHandler/UnitTest/XMPPURITest.cpp b/SwifTools/URIHandler/UnitTest/XMPPURITest.cpp
index 8d03b60..35020da 100644
--- a/SwifTools/URIHandler/UnitTest/XMPPURITest.cpp
+++ b/SwifTools/URIHandler/UnitTest/XMPPURITest.cpp
@@ -65,9 +65,9 @@ class XMPPURITest : public CppUnit::TestFixture {
}
void testFromString_AuthorityWithIntlChars() {
- XMPPURI testling = XMPPURI::fromString("xmpp://nasty!%23$%25()*+,-.;=\%3F\%5B\%5C\%5D\%5E_\%60\%7B\%7C\%7D~node@example.com");
+ XMPPURI testling = XMPPURI::fromString("xmpp://nasty!%23$%25()*+,-.;=%3F%5B%5C%5D%5E_%60%7B%7C%7D~node@example.com");
- CPPUNIT_ASSERT_EQUAL(JID("nasty!#$\%()*+,-.;=?[\\]^_`{|}~node@example.com"), testling.getAuthority());
+ CPPUNIT_ASSERT_EQUAL(JID("nasty!#$%()*+,-.;=?[\\]^_`{|}~node@example.com"), testling.getAuthority());
}
void testFromString_AuthorityWithQueryWithoutParameters() {
@@ -118,9 +118,9 @@ class XMPPURITest : public CppUnit::TestFixture {
}
void testFromString_PathWithIntlChars() {
- XMPPURI testling = XMPPURI::fromString("xmpp:nasty!%23$%25()*+,-.;=\%3F\%5B\%5C\%5D\%5E_\%60\%7B\%7C\%7D~node@example.com");
+ XMPPURI testling = XMPPURI::fromString("xmpp:nasty!%23$%25()*+,-.;=%3F%5B%5C%5D%5E_%60%7B%7C%7D~node@example.com");
- CPPUNIT_ASSERT_EQUAL(JID("nasty!#$\%()*+,-.;=?[\\]^_`{|}~node@example.com"), testling.getPath());
+ CPPUNIT_ASSERT_EQUAL(JID("nasty!#$%()*+,-.;=?[\\]^_`{|}~node@example.com"), testling.getPath());
}
void testFromString_PathWithInvalidEscapedChar() {
diff --git a/SwifTools/UnitTest/LastLineTrackerTest.cpp b/SwifTools/UnitTest/LastLineTrackerTest.cpp
index a7046ed..97790e5 100644
--- a/SwifTools/UnitTest/LastLineTrackerTest.cpp
+++ b/SwifTools/UnitTest/LastLineTrackerTest.cpp
@@ -21,7 +21,7 @@ class LastLineTrackerTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE_END();
public:
LastLineTrackerTest () {
- };
+ }
void testFocusNormal() {
LastLineTracker testling;
testling.setHasFocus(true);
diff --git a/SwifTools/UnitTest/LinkifyTest.cpp b/SwifTools/UnitTest/LinkifyTest.cpp
index 5df1a96..c464b50 100644
--- a/SwifTools/UnitTest/LinkifyTest.cpp
+++ b/SwifTools/UnitTest/LinkifyTest.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -32,6 +32,12 @@ class LinkifyTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testLinkify_NewLine);
CPPUNIT_TEST(testLinkify_Tab);
CPPUNIT_TEST(testLinkify_Action);
+
+ CPPUNIT_TEST(testLinkify_SplitNone);
+ CPPUNIT_TEST(testLinkify_SplitAll);
+ CPPUNIT_TEST(testLinkify_SplitFirst);
+ CPPUNIT_TEST(testLinkify_SplitSecond);
+ CPPUNIT_TEST(testLinkify_SplitMiddle);
CPPUNIT_TEST_SUITE_END();
public:
@@ -181,12 +187,57 @@ class LinkifyTest : public CppUnit::TestFixture {
}
void testLinkify_Action() {
- std::string result = Linkify::linkify("*http://swift.im*");
+ std::string result = Linkify::linkify("*http://swift.im*");
+
+ CPPUNIT_ASSERT_EQUAL(
+ std::string("*<a href=\"http://swift.im\">http://swift.im</a>*"),
+ result);
+ }
- CPPUNIT_ASSERT_EQUAL(
- std::string("*<a href=\"http://swift.im\">http://swift.im</a>*"),
- result);
+ void checkResult(const std::string& testling, size_t expectedIndex, std::string expectedSplit[]) {
+ std::pair<std::vector<std::string>, size_t> result = Linkify::splitLink(testling);
+ CPPUNIT_ASSERT_EQUAL(expectedIndex, result.second);
+ for (size_t i = 0; i < result.first.size(); i++) {
+ CPPUNIT_ASSERT_EQUAL(expectedSplit[i], result.first[i]);
}
+ }
+
+ void testLinkify_SplitNone() {
+ std::string testling = "http this ain't";
+ size_t expectedIndex = 1;
+ std::string expectedSplit[] = {"http this ain't"};
+ checkResult(testling, expectedIndex, expectedSplit);
+ }
+
+ void testLinkify_SplitAll() {
+ std::string testling = "http://swift.im";
+ size_t expectedIndex = 0;
+ std::string expectedSplit[] = {"http://swift.im"};
+ checkResult(testling, expectedIndex, expectedSplit);
+ }
+
+ void testLinkify_SplitFirst() {
+ std::string testling = "http://swift.im is a link";
+ size_t expectedIndex = 0;
+ std::string expectedSplit[] = {"http://swift.im", " is a link"};
+ checkResult(testling, expectedIndex, expectedSplit);
+ }
+
+ void testLinkify_SplitSecond() {
+ std::string testling = "this is a link: http://swift.im";
+ size_t expectedIndex = 1;
+ std::string expectedSplit[] = {"this is a link: ", "http://swift.im"};
+ checkResult(testling, expectedIndex, expectedSplit);
+ }
+
+ void testLinkify_SplitMiddle() {
+ std::string testling = "Shove a link like http://swift.im in the middle";
+ size_t expectedIndex = 1;
+ std::string expectedSplit[] = {"Shove a link like ","http://swift.im", " in the middle"};
+ checkResult(testling, expectedIndex, expectedSplit);
+ }
+
+
};
CPPUNIT_TEST_SUITE_REGISTRATION(LinkifyTest);
diff --git a/SwifTools/UnitTest/SConscript b/SwifTools/UnitTest/SConscript
index e469deb..dbd1ce5 100644
--- a/SwifTools/UnitTest/SConscript
+++ b/SwifTools/UnitTest/SConscript
@@ -5,3 +5,8 @@ env.Append(UNITTEST_SOURCES = [
File("TabCompleteTest.cpp"),
File("LastLineTrackerTest.cpp"),
])
+
+if env["HAVE_HUNSPELL"] :
+ env.Append(UNITTEST_SOURCES = [
+ File("SpellParserTest.cpp"),
+ ])
diff --git a/SwifTools/UnitTest/SpellParserTest.cpp b/SwifTools/UnitTest/SpellParserTest.cpp
new file mode 100644
index 0000000..09e686c
--- /dev/null
+++ b/SwifTools/UnitTest/SpellParserTest.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012 Vlad Voicu
+ * Licensed under the Simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include <boost/algorithm/string.hpp>
+
+#include <SwifTools/SpellParser.h>
+
+using namespace Swift;
+
+class SpellParserTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(SpellParserTest);
+ CPPUNIT_TEST(testSimpleCheckFragment);
+ CPPUNIT_TEST(testWWWCheckFragment);
+ CPPUNIT_TEST_SUITE_END();
+ public:
+ SpellParserTest() {
+ parser_ = new SpellParser();
+ };
+ void tearDown() {
+ position_.clear();
+ }
+ void testSimpleCheckFragment() {
+ parser_->check("fragment test", position_);
+ int size = position_.size();
+ CPPUNIT_ASSERT_EQUAL(2, size);
+ CPPUNIT_ASSERT_EQUAL(0, boost::get<0>(position_.front()));
+ CPPUNIT_ASSERT_EQUAL(8, boost::get<1>(position_.front()));
+ CPPUNIT_ASSERT_EQUAL(9, boost::get<0>(position_.back()));
+ CPPUNIT_ASSERT_EQUAL(13, boost::get<1>(position_.back()));
+ }
+ void testWWWCheckFragment() {
+ parser_->check("www.link.com fragment test", position_);
+ int size = position_.size();
+ CPPUNIT_ASSERT_EQUAL(2, size);
+ CPPUNIT_ASSERT_EQUAL(13, boost::get<0>(position_.front()));
+ CPPUNIT_ASSERT_EQUAL(21, boost::get<1>(position_.front()));
+ CPPUNIT_ASSERT_EQUAL(22, boost::get<0>(position_.back()));
+ CPPUNIT_ASSERT_EQUAL(26, boost::get<1>(position_.back()));
+ }
+ private:
+ SpellParser *parser_;
+ PositionPairList position_;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SpellParserTest);
diff --git a/SwifTools/UnitTest/TabCompleteTest.cpp b/SwifTools/UnitTest/TabCompleteTest.cpp
index 0466484..cdb0296 100644
--- a/SwifTools/UnitTest/TabCompleteTest.cpp
+++ b/SwifTools/UnitTest/TabCompleteTest.cpp
@@ -24,7 +24,7 @@ class TabCompleteTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE_END();
public:
- TabCompleteTest() {};
+ TabCompleteTest() {}
void setUp() {
completer_ = TabComplete();