summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2022-03-16 22:10:55 +0100
committerCarl Hetherington <cth@carlh.net>2022-03-18 00:12:44 +0100
commitc36cc02c31740f6676e31df2c36001e5d082c71c (patch)
treee0919a64234f5958855a576b6e7b68d2fbf53bd5
parentff474f597a40366d4232e1d5a43de824538f08c1 (diff)
Use the ICU library to sort cinemas rather than strcoll() (part of #2208).
strcoll() just doesn't really seem to work at all on Windows.
-rw-r--r--src/wx/screens_panel.cc40
-rw-r--r--src/wx/screens_panel.h12
2 files changed, 48 insertions, 4 deletions
diff --git a/src/wx/screens_panel.cc b/src/wx/screens_panel.cc
index 2075515f3..f255d4413 100644
--- a/src/wx/screens_panel.cc
+++ b/src/wx/screens_panel.cc
@@ -27,6 +27,11 @@
#include "lib/cinema.h"
#include "lib/config.h"
#include "lib/screen.h"
+#include <unicode/putil.h>
+#include <unicode/ucol.h>
+#include <unicode/uiter.h>
+#include <unicode/utypes.h>
+#include <unicode/ustring.h>
using std::cout;
@@ -523,3 +528,38 @@ ScreensPanel::screen_by_tree_list_item (wxTreeListItem item) const
);
}
+
+ScreensPanel::Comparator::Comparator ()
+{
+ UErrorCode status = U_ZERO_ERROR;
+ _collator = ucol_open(nullptr, &status);
+ if (_collator) {
+ ucol_setAttribute(_collator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ ucol_setAttribute(_collator, UCOL_STRENGTH, UCOL_PRIMARY, &status);
+ ucol_setAttribute(_collator, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
+ }
+}
+
+ScreensPanel::Comparator::~Comparator ()
+{
+ if (_collator) {
+ ucol_close (_collator);
+ }
+}
+
+int
+ScreensPanel::Comparator::Compare (wxTreeListCtrl* tree_list, unsigned, wxTreeListItem a, wxTreeListItem b)
+{
+ auto utf8_a = wx_to_std(tree_list->GetItemText(a));
+ auto utf8_b = wx_to_std(tree_list->GetItemText(b));
+ if (_collator) {
+ UErrorCode error = U_ZERO_ERROR;
+ boost::scoped_array<uint16_t> utf16_a(new uint16_t[utf8_a.size() + 1]);
+ u_strFromUTF8(reinterpret_cast<UChar*>(utf16_a.get()), utf8_a.size() + 1, nullptr, utf8_a.c_str(), -1, &error);
+ boost::scoped_array<uint16_t> utf16_b(new uint16_t[utf8_b.size() + 1]);
+ u_strFromUTF8(reinterpret_cast<UChar*>(utf16_b.get()), utf8_b.size() + 1, nullptr, utf8_b.c_str(), -1, &error);
+ return ucol_strcoll(_collator, reinterpret_cast<UChar*>(utf16_a.get()), -1, reinterpret_cast<UChar*>(utf16_b.get()), -1);
+ } else {
+ return strcoll(utf8_a.c_str(), utf8_b.c_str());
+ }
+}
diff --git a/src/wx/screens_panel.h b/src/wx/screens_panel.h
index c0b90dfcf..4b7a80141 100644
--- a/src/wx/screens_panel.h
+++ b/src/wx/screens_panel.h
@@ -36,6 +36,7 @@ namespace dcpomatic {
class Cinema;
+class UCollator;
class ScreensPanel : public wxPanel
@@ -90,10 +91,13 @@ private:
class Comparator : public wxTreeListItemComparator
{
public:
- int Compare (wxTreeListCtrl* tree_list, unsigned, wxTreeListItem a, wxTreeListItem b) override
- {
- return strcoll(wx_to_std(tree_list->GetItemText(a)).c_str(), wx_to_std(tree_list->GetItemText(b)).c_str());
- }
+ Comparator ();
+ ~Comparator ();
+
+ int Compare (wxTreeListCtrl* tree_list, unsigned, wxTreeListItem a, wxTreeListItem b) override;
+
+ private:
+ UCollator* _collator;
};
Comparator _comparator;