forked from sakura-editor/sakura
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCLoadAgent.cpp
317 lines (278 loc) · 11.8 KB
/
CLoadAgent.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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
/*! @file */
/*
Copyright (C) 2008, kobake
Copyright (C) 2018-2022, Sakura Editor Organization
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but is
not required.
2. Altered source versions must be plainly marked as such,
and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "StdAfx.h"
#include "CLoadAgent.h"
#include "CReadManager.h"
#include "_main/CAppMode.h"
#include "_main/CControlTray.h"
#include "CEditApp.h"
#include "env/CDocTypeManager.h"
#include "env/CShareData.h"
#include "doc/CEditDoc.h"
#include "view/CEditView.h"
#include "window/CEditWnd.h"
#include "uiparts/CVisualProgress.h"
#include "util/file.h"
#include "io/CFileLoad.h"
#include "apiwrap/StdApi.h"
#include "config/app_constants.h"
#include "String_define.h"
ECallbackResult CLoadAgent::OnCheckLoad(SLoadInfo* pLoadInfo)
{
CEditDoc* pcDoc = GetListeningDoc();
// リロード要求の場合は、継続。
if(pLoadInfo->bRequestReload)goto next;
//フォルダーが指定された場合は「ファイルを開く」ダイアログを表示し、実際のファイル入力を促す
if( IsDirectory(pLoadInfo->cFilePath) ){
std::vector<std::wstring> files;
SLoadInfo sLoadInfo(L"", CODE_AUTODETECT, false);
bool bDlgResult = pcDoc->m_cDocFileOperation.OpenFileDialog(
CEditWnd::getInstance()->GetHwnd(),
pLoadInfo->cFilePath, //指定されたフォルダー
&sLoadInfo,
files
);
if( !bDlgResult ){
return CALLBACK_INTERRUPT; //キャンセルされた場合は中断
}
size_t nSize = files.size();
if( 0 < nSize ){
sLoadInfo.cFilePath = files[0].c_str();
// 他のファイルは新規ウィンドウ
for( size_t i = 1; i < nSize; i++ ){
SLoadInfo sFilesLoadInfo = sLoadInfo;
sFilesLoadInfo.cFilePath = files[i].c_str();
CControlTray::OpenNewEditor(
G_AppInstance(),
CEditWnd::getInstance()->GetHwnd(),
sFilesLoadInfo,
NULL,
true
);
}
}
*pLoadInfo = sLoadInfo;
}
// 他のウィンドウで既に開かれている場合は、それをアクティブにする
HWND hWndOwner;
if( CShareData::getInstance()->ActiveAlreadyOpenedWindow(pLoadInfo->cFilePath, &hWndOwner, pLoadInfo->eCharCode) ){
pLoadInfo->bOpened = true;
return CALLBACK_INTERRUPT;
}
// 現在のウィンドウに対してファイルを読み込めない場合は、新たなウィンドウを開き、そこにファイルを読み込ませる
if(!pcDoc->IsAcceptLoad()){
CControlTray::OpenNewEditor(
G_AppInstance(),
CEditWnd::getInstance()->GetHwnd(),
*pLoadInfo
);
return CALLBACK_INTERRUPT;
}
next:
// オプション:開こうとしたファイルが存在しないとき警告する
if( GetDllShareData().m_Common.m_sFile.GetAlertIfFileNotExist() ){
if(!fexist(pLoadInfo->cFilePath)){
InfoBeep();
// Feb. 15, 2003 genta Popupウィンドウを表示しないように.
// ここでステータスメッセージを使っても画面に表示されない.
TopInfoMessage(
CEditWnd::getInstance()->GetHwnd(),
LS(STR_NOT_EXSIST_SAVE), //Mar. 24, 2001 jepro 若干修正
pLoadInfo->cFilePath.GetBufferPointer()
);
}
}
// 読み取り可能チェック
do{
CFile cFile(pLoadInfo->cFilePath.c_str());
//ファイルが存在しない場合はチェック省略
if(!cFile.IsFileExist())break;
// ロックは一時的に解除してチェックする(チェックせずに後戻りできないところまで進めるより安全)
// ※ ロックしていてもアクセス許可の変更によって読み取れなくなっていることもある
bool bLock = (pLoadInfo->IsSamePath(pcDoc->m_cDocFile.GetFilePath()) && pcDoc->m_cDocFile.IsFileLocking());
if( bLock ) pcDoc->m_cDocFileOperation.DoFileUnlock();
//チェック
if(!cFile.IsFileReadable()){
if( bLock ) pcDoc->m_cDocFileOperation.DoFileLock(false);
ErrorMessage(
CEditWnd::getInstance()->GetHwnd(),
LS(STR_LOADAGENT_ERR_OPEN),
pLoadInfo->cFilePath.c_str()
);
return CALLBACK_INTERRUPT; //ファイルが存在しているのに読み取れない場合は中断
}
if( bLock ) pcDoc->m_cDocFileOperation.DoFileLock(false);
}
while(false); // 1回しか通らない. breakでここまで飛ぶ
// ファイルサイズチェック
WIN32_FIND_DATA wfd;
HANDLE nFind = ::FindFirstFile(pLoadInfo->cFilePath.c_str(), &wfd);
if (nFind != INVALID_HANDLE_VALUE) {
::FindClose(nFind);
LARGE_INTEGER nFileSize;
nFileSize.HighPart = wfd.nFileSizeHigh;
nFileSize.LowPart = wfd.nFileSizeLow;
// システム的に開けない場合にはエラーダイアログを出してオープン処理中断
#ifdef _WIN64
bool bBigFile = true;
#else
bool bBigFile = false;
#endif
if (!CFileLoad::IsLoadableSize(nFileSize.QuadPart)) {
// ファイルサイズがシステム的に大きすぎるため、エラーとしてファイルロードを中断する。
// ※32bit 版の場合は 2GB あたりを上限とする。
// ここでエラーを出さずに OnLoad に突入させてしまうと CFileLoad::FileOpen が例外を吐くので、
// この段階でエラーを出して処理を中断させる。
ErrorMessage(
CEditWnd::getInstance()->GetHwnd(),
LS(STR_LOADAGENT_BIG_ERROR),
pLoadInfo->cFilePath.c_str(),
CFileLoad::GetSizeStringForHuman(nFileSize.QuadPart).c_str(),
CFileLoad::GetSizeStringForHuman(CFileLoad::GetLimitSize()).c_str()
);
return CALLBACK_INTERRUPT;
}
// ファイルサイズがユーザー設定の閾値以上の場合は警告ダイアログを出す
if (GetDllShareData().m_Common.m_sFile.m_bAlertIfLargeFile) {
// GetDllShareData().m_Common.m_sFile.m_nAlertFileSize はMB単位
if( (nFileSize.QuadPart>>20) >= (GetDllShareData().m_Common.m_sFile.m_nAlertFileSize) ){
// 本当に開いて良いかどうかの警告ダイアログ
int nRet = MYMESSAGEBOX( CEditWnd::getInstance()->GetHwnd(),
MB_ICONQUESTION | MB_YESNO | MB_TOPMOST,
GSTR_APPNAME,
LS(STR_LOADAGENT_BIG_WARNING),
pLoadInfo->cFilePath.c_str(),
GetDllShareData().m_Common.m_sFile.m_nAlertFileSize );
if( nRet != IDYES ){
return CALLBACK_INTERRUPT;
}
}
}
}
return CALLBACK_CONTINUE;
}
void CLoadAgent::OnBeforeLoad(SLoadInfo* pLoadInfo)
{
}
ELoadResult CLoadAgent::OnLoad(const SLoadInfo& sLoadInfo)
{
ELoadResult eRet = LOADED_OK;
CEditDoc* pcDoc = GetListeningDoc();
/* 既存データのクリア */
pcDoc->InitDoc(); //$$
// パスを確定
pcDoc->SetFilePathAndIcon( sLoadInfo.cFilePath );
// 文書種別確定
pcDoc->m_cDocType.SetDocumentType( sLoadInfo.nType, true );
GetEditWnd().m_pcViewFontMiniMap->UpdateFont(&GetEditWnd().GetLogfont());
InitCharWidthCache( GetEditWnd().m_pcViewFontMiniMap->GetLogfont(), CWM_FONT_MINIMAP );
SelectCharWidthCache( CWM_FONT_EDIT, GetEditWnd().GetLogfontCacheMode() );
InitCharWidthCache( GetEditWnd().GetLogfont() );
GetEditWnd().m_pcViewFont->UpdateFont(&GetEditWnd().GetLogfont());
// 起動と同時に読む場合は予めアウトライン解析画面を配置しておく
// (ファイル読み込み開始とともにビューが表示されるので、あとで配置すると画面のちらつきが大きいの)
if( !GetEditWnd().m_cDlgFuncList.m_bEditWndReady ){
GetEditWnd().m_cDlgFuncList.Refresh();
HWND hEditWnd = GetEditWnd().GetHwnd();
if( !::IsIconic( hEditWnd ) && GetEditWnd().m_cDlgFuncList.GetHwnd() ){
RECT rc;
::GetClientRect( hEditWnd, &rc );
::SendMessageAny( hEditWnd, WM_SIZE, ::IsZoomed( hEditWnd )? SIZE_MAXIMIZED: SIZE_RESTORED, MAKELONG( rc.right - rc.left, rc.bottom - rc.top ) );
}
}
//ファイルが存在する場合はファイルを読む
if(fexist(sLoadInfo.cFilePath)){
//CDocLineMgrの構成
CReadManager cReader;
CProgressSubject* pOld = CEditApp::getInstance()->m_pcVisualProgress->CProgressListener::Listen(&cReader);
EConvertResult eReadResult = cReader.ReadFile_To_CDocLineMgr(
&pcDoc->m_cDocLineMgr,
sLoadInfo,
&pcDoc->m_cDocFile.m_sFileInfo
);
if(eReadResult==RESULT_LOSESOME){
eRet = LOADED_LOSESOME;
}
CEditApp::getInstance()->m_pcVisualProgress->CProgressListener::Listen(pOld);
}
else{
// 存在しないときもドキュメントに文字コードを反映する
const STypeConfig& types = pcDoc->m_cDocType.GetDocumentAttribute();
pcDoc->m_cDocFile.SetCodeSet( sLoadInfo.eCharCode,
( sLoadInfo.eCharCode == types.m_encoding.m_eDefaultCodetype ) ?
types.m_encoding.m_bDefaultBom : CCodeTypeName( sLoadInfo.eCharCode ).IsBomDefOn() );
}
/* レイアウト情報の変更 */
// 2008.06.07 nasukoji 折り返し方法の追加に対応
// 「指定桁で折り返す」以外の時は折り返し幅をMAXLINEKETASで初期化する
// 「右端で折り返す」は、この後のOnSize()で再設定される
const STypeConfig& ref = pcDoc->m_cDocType.GetDocumentAttribute();
CKetaXInt nMaxLineKetas = ref.m_nMaxLineKetas;
if( ref.m_nTextWrapMethod != WRAP_SETTING_WIDTH )
nMaxLineKetas = CKetaXInt(MAXLINEKETAS);
CProgressSubject* pOld = CEditApp::getInstance()->m_pcVisualProgress->CProgressListener::Listen(&pcDoc->m_cLayoutMgr);
pcDoc->m_cLayoutMgr.SetLayoutInfo( true, true, ref, ref.m_nTabSpace, ref.m_nTsvMode, nMaxLineKetas, CLayoutXInt(-1), &GetEditWnd().GetLogfont() );
GetEditWnd().ClearViewCaretPosInfo();
if (pcDoc->m_cLayoutMgr.m_tsvInfo.m_nTsvMode != TSV_MODE_NONE) {
pcDoc->m_cLayoutMgr.m_tsvInfo.CalcTabLength(pcDoc->m_cLayoutMgr.m_pcDocLineMgr);
}
CEditApp::getInstance()->m_pcVisualProgress->CProgressListener::Listen(pOld);
return eRet;
}
void CLoadAgent::OnAfterLoad(const SLoadInfo& sLoadInfo)
{
CEditDoc* pcDoc = GetListeningDoc();
/* 親ウィンドウのタイトルを更新 */
GetEditWnd().UpdateCaption();
// -- -- ※ InitAllViewでやってたこと -- -- // // 2009.08.28 nasukoji CEditView::OnAfterLoad()からここに移動
pcDoc->m_nCommandExecNum=0;
// テキストの折り返し方法を初期化
pcDoc->m_nTextWrapMethodCur = pcDoc->m_cDocType.GetDocumentAttribute().m_nTextWrapMethod; // 折り返し方法
pcDoc->m_bTextWrapMethodCurTemp = false; // 一時設定適用中を解除
pcDoc->m_blfCurTemp = false;
pcDoc->m_bTabSpaceCurTemp = false;
// 2009.08.28 nasukoji 「折り返さない」ならテキスト最大幅を算出、それ以外は変数をクリア
if( pcDoc->m_nTextWrapMethodCur == WRAP_NO_TEXT_WRAP )
pcDoc->m_cLayoutMgr.CalculateTextWidth(); // テキスト最大幅を算出する
else
pcDoc->m_cLayoutMgr.ClearLayoutLineWidth(); // 各行のレイアウト行長の記憶をクリアする
}
void CLoadAgent::OnFinalLoad(ELoadResult eLoadResult)
{
CEditDoc* pcDoc = GetListeningDoc();
if(eLoadResult==LOADED_FAILURE){
pcDoc->SetFilePathAndIcon( L"" );
pcDoc->m_cDocFile.SetBomDefoult();
}
if(eLoadResult==LOADED_LOSESOME){
CAppMode::getInstance()->SetViewMode(true);
}
//再描画 $$不足
// CEditWnd::getInstance()->GetActiveView().SetDrawSwitch(true);
bool bDraw = CEditWnd::getInstance()->GetActiveView().GetDrawSwitch();
if( bDraw ){
CEditWnd::getInstance()->Views_RedrawAll(); //ビュー再描画
InvalidateRect( CEditWnd::getInstance()->GetHwnd(), NULL, TRUE );
}
CCaret& cCaret = CEditWnd::getInstance()->GetActiveView().GetCaret();
cCaret.MoveCursor(cCaret.GetCaretLayoutPos(),true);
CEditWnd::getInstance()->GetActiveView().AdjustScrollBars();
}