1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#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)
{
using FindHandle = Managed<HANDLE, FindClose, Win32Error, -1>;
/* Don't recurse too much. */
if (level > 3)
return false;
wchar_t pat[MAX_PATH];
Swprintf(pat, L"%s\\*", root);
WIN32_FIND_DATA fdata;
FindHandle h = FindFirstFile(pat, &fdata);
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);
if (FindMatchingFile(file, root2, siEp, level+1))
return true;
}
else /* Try to match file name. */
if (MatchFileName(fdata.cFileName, siEp)) {
Swprintf(file, L"%s\\%s", root, fdata.cFileName);
return true;
}
} while (FindNextFile(h, &fdata));
if (GetLastError() != ERROR_NO_MORE_FILES)
throw Win32Error();
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;
}
|