forked from ffftp/ffftp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmisc.cpp
186 lines (166 loc) · 6.82 KB
/
misc.cpp
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*=============================================================================
*
* その他の汎用サブルーチン
*
===============================================================================
/ Copyright (C) 1997-2007 Sota. All rights reserved.
/
/ Redistribution and use in source and binary forms, with or without
/ modification, are permitted provided that the following conditions
/ are met:
/
/ 1. Redistributions of source code must retain the above copyright
/ notice, this list of conditions and the following disclaimer.
/ 2. Redistributions in binary form must reproduce the above copyright
/ notice, this list of conditions and the following disclaimer in the
/ documentation and/or other materials provided with the distribution.
/
/ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
/ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
/ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
/ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
/ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
/ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
/ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
/ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
/ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
/ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/============================================================================*/
#include "common.h"
// 文字列の最後に "/" を付ける
// Tandem では / の代わりに . を追加
std::wstring SetSlashTail(std::wstring&& path) {
wchar_t separator = L'/';
#if defined(HAVE_TANDEM)
if (AskHostType() == HTYPE_TANDEM)
separator = L'.';
#endif
if (!path.ends_with(separator))
path += separator;
return path;
}
// 文字列内の特定の文字を全て置き換える
// Tandem ではノード名の変換を行わないため、最初の1文字が \ でもそのままにする
// 置換対象fromが \ 以外ならstd::replaceでよい
std::wstring ReplaceAll(std::wstring&& str, wchar_t from, wchar_t to) {
if (!empty(str)) {
auto it = begin(str);
#if defined(HAVE_TANDEM)
if (GetConnectingHost().HostType == HTYPE_TANDEM)
++it;
#endif
std::replace(it, end(str), from, to);
}
return str;
}
// パス名の中のファイル名の先頭を返す
// ディレクトリの区切り記号は "\" と "/" の両方が有効
// Tandem は . がデリミッタとなる
std::wstring_view GetFileName(std::wstring_view path) {
if (auto const pos = path.find_first_of(L':'); pos != std::wstring_view::npos)
path = path.substr(pos + 1);
auto delimiter = L"\\/"sv;
#if defined(HAVE_TANDEM)
if (AskHostType() == HTYPE_TANDEM)
delimiter = L"\\/."sv;
#endif
if (auto const pos = path.find_last_of(delimiter); pos != std::wstring_view::npos)
path = path.substr(pos + 1);
return path;
}
// パス名からファイル名を取り除く
// ディレクトリの区切り記号は "\" と "/" の両方が有効
static std::string_view RemoveFileName(std::string_view path) {
if (auto const p = path.rfind('/'); p != std::string_view::npos)
return path.substr(0, p);
if (auto const p = path.rfind('\\'); p != std::string_view::npos)
if (p == 0 || path[p - 1] != ':')
return path.substr(0, p);
return path;
}
// StaticTextの領域に収まるようにパス名を整形して表示
void DispStaticText(HWND hWnd, std::wstring text) {
RECT rect;
GetClientRect(hWnd, &rect);
auto font = (HFONT)SendMessageW(hWnd, WM_GETFONT, 0, 0);
auto dc = GetDC(hWnd);
auto previous = SelectObject(dc, font);
for (;;) {
if (size(text) <= 4)
break;
if (SIZE size; GetTextExtentPoint32W(dc, data(text), size_as<int>(text), &size) && size.cx <= rect.right)
break;
auto const pos = text.find_first_of(L"\\/"sv, 4);
text.erase(0, pos != std::wstring::npos ? pos - 3 : 1);
std::fill_n(begin(text), 3, L'.');
}
SelectObject(dc, previous);
ReleaseDC(hWnd, dc);
SetText(hWnd, text);
}
static auto GetFilterString(std::initializer_list<FileType> fileTypes) {
static auto const map = [] {
std::map<FileType, std::wstring> map;
for (auto fileType : AllFileTyes) {
// リソース文字列は末尾 '\0' を扱えないので '\t' を利用し、ここで置換する。
auto text = GetString(static_cast<UINT>(fileType));
for (auto& ch : text)
if (ch == L'\t')
ch = L'\0';
map.emplace(fileType, text);
}
return map;
}();
return std::accumulate(begin(fileTypes), end(fileTypes), L""s, [](auto const& result, auto fileType) { return result + map.at(fileType); });
}
// ファイル選択
fs::path SelectFile(bool open, HWND hWnd, UINT titleId, const wchar_t* initialFileName, const wchar_t* extension, std::initializer_list<FileType> fileTypes) {
auto const filter = GetFilterString(fileTypes);
wchar_t buffer[FMAX_PATH + 1];
wcscpy_s(buffer, initialFileName);
auto const title = GetString(titleId);
DWORD const flags = (open ? OFN_FILEMUSTEXIST : OFN_EXTENSIONDIFFERENT | OFN_OVERWRITEPROMPT) | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
OPENFILENAMEW ofn{ sizeof(OPENFILENAMEW), hWnd, 0, filter.c_str(), nullptr, 0, 1, buffer, size_as<DWORD>(buffer), nullptr, 0, nullptr, title.c_str(), flags, 0, 0, extension };
auto const cwd = fs::current_path();
int const result = (open ? GetOpenFileNameW : GetSaveFileNameW)(&ofn);
fs::current_path(cwd);
if (!result)
return {};
return buffer;
}
// ディレクトリを選択
fs::path SelectDir(HWND hWnd) {
fs::path path;
auto const cwd = fs::current_path();
auto const title = GetString(IDS_MSGJPN185);
BROWSEINFOW bi{ hWnd, nullptr, nullptr, title.c_str(), BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE };
if (auto idlist = SHBrowseForFolderW(&bi)) {
wchar_t buffer[FMAX_PATH + 1];
SHGetPathFromIDListEx(idlist, buffer, size_as<DWORD>(buffer), GPFIDL_DEFAULT);
path = buffer;
CoTaskMemFree(idlist);
}
fs::current_path(cwd);
return path;
}
#if defined(HAVE_TANDEM)
// ファイルサイズからEXTENTサイズの計算を行う
void CalcExtentSize(TRANSPACKET *Pkt, LONGLONG Size) noexcept {
LONGLONG extent;
/* EXTENTS(4,28) MAXEXTENTS 978 */
if(Size < 56025088) {
Pkt->PriExt = DEF_PRIEXT;
Pkt->SecExt = DEF_SECEXT;
Pkt->MaxExt = DEF_MAXEXT;
} else {
/* 増加余地を残すため Used 75% 近辺になるように EXTENT サイズを調整) */
extent = (LONGLONG)(Size / ((DEF_MAXEXT * 0.75) * 2048LL));
/* 28未満にすると誤差でFile Fullになる可能性がある */
if(extent < 28)
extent = 28;
Pkt->PriExt = (int)extent;
Pkt->SecExt = (int)extent;
Pkt->MaxExt = DEF_MAXEXT;
}
}
#endif