aboutsummaryrefslogtreecommitdiff
path: root/c/ext.cpp
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-08-22 22:22:29 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-08-22 22:22:29 +0200
commit5d0979480ff50390b3883795ec2093e0d3d6193b (patch)
tree34a5fc5d18cb2d9cc87c01e6eb2eb40e0f3d5050 /c/ext.cpp
parent8566655b85f0a4e515d57f6686636db516116f95 (diff)
downloadEpisodeBrowser-5d0979480ff50390b3883795ec2093e0d3d6193b.tar.gz
Open episodes without Prolog.
Diffstat (limited to 'c/ext.cpp')
-rw-r--r--c/ext.cpp132
1 files changed, 132 insertions, 0 deletions
diff --git a/c/ext.cpp b/c/ext.cpp
new file mode 100644
index 0000000..f485dce
--- /dev/null
+++ b/c/ext.cpp
@@ -0,0 +1,132 @@
+#include <ctype.h>
+#include <string>
+#include <string_view>
+
+#include "data.h"
+
+extern CfgA& g_cfg;
+extern FileView<ElvDataA> g_fvElv;
+extern FileView<DlvDataA> g_fvDlv;
+
+void OpenOnline(int iEp)
+{
+ wchar_t url[sizeof(g_cfg.url)+4];
+ Swprintf(url, L"%s%d", g_cfg.url, iEp);
+ INT_PTR r = reinterpret_cast<INT_PTR>(
+ ShellExecute(nullptr, L"open", url, nullptr, nullptr, SW_SHOWNORMAL));
+ if (r <= 32)
+ throw Win32Error();
+}
+
+void OpenWiki(int iEp)
+{
+ const DlvDataA& d = g_fvDlv.At(iEp-1);
+ wchar_t url[sizeof(d.wiki)+35];
+ Swprintf(url, L"https://www.detectiveconanworld.com%s", d.wiki);
+ INT_PTR r = reinterpret_cast<INT_PTR>(
+ ShellExecute(nullptr, L"open", url, nullptr, nullptr, SW_SHOWNORMAL));
+ if (r <= 32)
+ throw Win32Error();
+}
+
+static inline bool MatchFileName(wchar_t (&file)[MAX_PATH], const wchar_t* const siEp) noexcept
+{
+ /* This is a hand-written parser that matches file names of
+ * the type "Detective Conan - 010.mkv". */
+
+ wchar_t* f = file;
+
+ /* Match Detective Conan prefix. */
+ if (*f != L'D' && *f != L'd')
+ return false;
+ f++;
+
+ if (wcsncmp(f, L"etective", 8) != 0)
+ return false;
+ f += 8;
+
+ if (*f != L' ' && *f != L'_' && *f != L'-')
+ return false;
+ f++;
+
+ if (*f != L'C' && *f != L'c')
+ return false;
+ f++;
+
+ if (wcsncmp(f, L"onan", 4) != 0)
+ return false;
+ f += 4;
+
+ /* Match garbage before episode number. */
+ while (*f == L' ' || *f == L'_' || *f == L'-' || *f == L'0')
+ f++;
+
+ /* Match episode number. */
+ size_t lenEp = wcslen(siEp);
+ if (wcsncmp(f, siEp, lenEp) != 0)
+ return false;
+ f += lenEp;
+
+ if (isdigit(*f))
+ return false;
+
+ return true;
+}
+
+static bool FindMatchingFile(wchar_t (&file)[MAX_PATH], const wchar_t* const root,
+ const wchar_t* const siEp, const int level = 0)
+{
+ /* Don't recurse too much. */
+ if (level > 3)
+ return false;
+
+ wchar_t pat[MAX_PATH];
+ Swprintf(pat, L"%s\\*", root);
+
+ WIN32_FIND_DATA fdata;
+ HANDLE hf = FindFirstFile(pat, &fdata);
+ if (hf == INVALID_HANDLE_VALUE)
+ throw Win32Error().what();
+
+ do {
+ if (fdata.cFileName[0] == L'.')
+ continue;
+ if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ /* Recurse into directory. */
+ wchar_t root2[MAX_PATH];
+ Swprintf(root2, L"%s\\%s", root, fdata.cFileName);
+ try {
+ if (FindMatchingFile(file, root2, siEp, level+1))
+ return true;
+ } catch (...) {
+ FindClose(hf);
+ throw;
+ }
+ }
+ else /* Try to match file name. */
+ if (MatchFileName(fdata.cFileName, siEp)) {
+ Swprintf(file, L"%s\\%s", root, fdata.cFileName);
+ return true;
+ }
+ } while (FindNextFile(hf, &fdata));
+
+ DWORD e = GetLastError();
+ FindClose(hf);
+ if (e != ERROR_NO_MORE_FILES)
+ throw Win32Error(e);
+
+ return false;
+}
+
+bool OpenLocally(int iEp)
+{
+ wchar_t file[MAX_PATH];
+ if (FindMatchingFile(file, g_cfg.root, g_fvElv.At(iEp-1).siEp)) {
+ INT_PTR r = reinterpret_cast<INT_PTR>(
+ ShellExecute(nullptr, L"open", file, nullptr, nullptr, SW_SHOWNORMAL));
+ if (r <= 32)
+ throw Win32Error();
+ return true;
+ } else
+ return false;
+}