8 changes: 4 additions & 4 deletions sakura_core/cmd/CViewCommander_File.cpp
Expand Up @@ -512,10 +512,10 @@ void CViewCommander::Command_VIEWMODE( void )
// 排他制御の切り替え
// ※ビューモード ON 時は排他制御 OFF、ビューモード OFF 時は排他制御 ON の仕様(>>data:5262)を即時反映する
GetDocument()->m_cDocFileOperation.DoFileUnlock(); // ファイルの排他ロック解除
GetDocument()->m_cDocLocker.CheckWritable(!CAppMode::getInstance()->IsViewMode()); // ファイル書込可能のチェック
if( GetDocument()->m_cDocLocker.IsDocWritable() ){
GetDocument()->m_cDocFileOperation.DoFileLock(); // ファイルの排他ロック
}
//if (! CAppMode::getInstance()->IsViewMode()) { // 上書き可能かどうかファイルの状態の変化を反映できるようにする。
// GetDocument()->m_cDocLocker.Clear();
//}
GetDocument()->m_cDocFileOperation.DoFileLock(); // ファイルの排他ロック(ビューモード ON など、必要がなければ実際にロックはしない)

// 親ウィンドウのタイトルを更新
GetEditWindow()->UpdateCaption();
Expand Down
18 changes: 13 additions & 5 deletions sakura_core/doc/CDocFileOperation.cpp
Expand Up @@ -48,13 +48,21 @@
bool CDocFileOperation::_ToDoLock() const
{
// ファイルを開いていない
if( !m_pcDocRef->m_cDocFile.GetFilePathClass().IsValidPath() )return false;

if (! m_pcDocRef->m_cDocFile.GetFilePathClass().IsValidPath()) {
return false;
}
// ビューモード
if( CAppMode::getInstance()->IsViewMode() )return false;

if (CAppMode::getInstance()->IsViewMode()) {
return false;
}
// 排他設定
if( GetDllShareData().m_Common.m_sFile.m_nFileShareMode == SHAREMODE_NOT_EXCLUSIVE )return false;
if (GetDllShareData().m_Common.m_sFile.m_nFileShareMode == SHAREMODE_NOT_EXCLUSIVE) {
return false;
}
// 上書き禁止
if (! m_pcDocRef->m_cDocLocker.IsDocWritable()) {
return false;
}

return true;
}
Expand Down
30 changes: 17 additions & 13 deletions sakura_core/doc/CDocLocker.cpp
Expand Up @@ -10,7 +10,9 @@
// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //

CDocLocker::CDocLocker()
: m_bIsDocWritable(true)
: m_eIsDocWritable(UNTESTED)
, m_bNoMsg(false)
, m_bNeedRecheck(false)
{
}

Expand All @@ -22,11 +24,7 @@ void CDocLocker::OnAfterLoad(const SLoadInfo& sLoadInfo)
{
CEditDoc* pcDoc = GetListeningDoc();

//書き込めるか検査
CheckWritable(!sLoadInfo.bViewMode && !sLoadInfo.bWritableNoMsg);
if( !m_bIsDocWritable ){
return;
}
m_bNoMsg = sLoadInfo.bWritableNoMsg;

// ファイルの排他ロック
pcDoc->m_cDocFileOperation.DoFileLock();
Expand All @@ -48,8 +46,8 @@ void CDocLocker::OnAfterSave(const SSaveInfo& sSaveInfo)
{
CEditDoc* pcDoc = GetListeningDoc();

// 書き込めるか検査
m_bIsDocWritable = true;
m_eIsDocWritable = WRITABLE;
m_bNeedRecheck = false;

// ファイルの排他ロック
pcDoc->m_cDocFileOperation.DoFileLock();
Expand All @@ -60,28 +58,34 @@ void CDocLocker::OnAfterSave(const SSaveInfo& sSaveInfo)
// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //

//! 書き込めるか検査
void CDocLocker::CheckWritable(bool bMsg)
void CDocLocker::_CheckWritable()
{
CEditDoc* pcDoc = GetListeningDoc();

m_bNeedRecheck = false;

// ファイルが存在しない場合 (「開く」で新しくファイルを作成した扱い) は、以下の処理は行わない
if( !fexist(pcDoc->m_cDocFile.GetFilePath()) ){
m_bIsDocWritable = true;
m_eIsDocWritable = WRITABLE;
return;
}

// 読み取り専用ファイルの場合は、以下の処理は行わない
if( !pcDoc->m_cDocFile.HasWritablePermission() ){
m_bIsDocWritable = false;
m_eIsDocWritable = UNWRITABLE;
return;
}

WritableState IsWritableOld = m_eIsDocWritable;

// 書き込めるか検査
CDocFile& cDocFile = pcDoc->m_cDocFile;
m_bIsDocWritable = cDocFile.IsFileWritable();
if(!m_bIsDocWritable && bMsg){
m_eIsDocWritable = cDocFile.IsFileWritable() ? WRITABLE : UNWRITABLE;
if(m_eIsDocWritable == UNWRITABLE && ! m_bNoMsg && IsWritableOld != UNWRITABLE){
// 排他されている場合だけメッセージを出す
// その他の原因(ファイルシステムのセキュリティ設定など)では読み取り専用と同様にメッセージを出さない
// 編集禁止だったファイルを読み直したときには改めてメッセージを出さない(m_bNoMsg)。
// 書き込み可能状態が 不可ではない(不明,可能)→不可 と変化した場合にだけメッセージを出す。
if( ::GetLastError() == ERROR_SHARING_VIOLATION ){
TopWarningMessage(
CEditWnd::getInstance()->GetHwnd(),
Expand Down
27 changes: 22 additions & 5 deletions sakura_core/doc/CDocLocker.h
Expand Up @@ -31,7 +31,7 @@ class CDocLocker : public CDocListenerEx{
CDocLocker();

//クリア
void Clear(void) { m_bIsDocWritable = true; }
void Clear() { m_eIsDocWritable = UNTESTED; m_bNoMsg = m_bNeedRecheck = false; }

//ロード前後
void OnAfterLoad(const SLoadInfo& sLoadInfo);
Expand All @@ -41,14 +41,31 @@ class CDocLocker : public CDocListenerEx{
void OnAfterSave(const SSaveInfo& sSaveInfo);

//状態
bool IsDocWritable() const{ return m_bIsDocWritable; }
bool IsDocWritable() const;

//チェック
void CheckWritable(bool bMsg);

void CheckWritable() { m_bNeedRecheck = true; };
private:
bool m_bIsDocWritable;
void _CheckWritable();

enum WritableState { UNTESTED,WRITABLE,UNWRITABLE } m_eIsDocWritable;
bool m_bNoMsg;
bool m_bNeedRecheck;
};

inline bool CDocLocker::IsDocWritable() const
{
/*
CDocLocker の const 性とは何か。ファイルの属性だとすればそれは不定だ。
CDocLocker が保証できる const 性があるとすれば、テストしたある時点での
書き込み可能性がその後も提示され続けることではないか。Clear が呼ばれるまでは。
不明だったものを明らかにすることは CDocLocker の const 性を破らないと考える。
*/
if (m_eIsDocWritable == UNTESTED || m_bNeedRecheck) {
const_cast<CDocLocker*>(this)->_CheckWritable();
}
return m_eIsDocWritable == WRITABLE;
}

#endif /* SAKURA_CDOCLOCKER_5E410382_D36E_46CE_B212_07F2F346FD3C_H_ */
/*[EOF]*/
25 changes: 10 additions & 15 deletions sakura_core/doc/CEditDoc.cpp
Expand Up @@ -203,9 +203,6 @@ CEditDoc::CEditDoc(CEditApp* pcApp)
m_cDocFile.SetCodeSet( ref.m_encoding.m_eDefaultCodetype, ref.m_encoding.m_bDefaultBom );
m_cDocEditor.m_cNewLineCode = ref.m_encoding.m_eDefaultEoltype;

// 排他制御オプションを初期化
m_cDocFile.SetShareMode( GetDllShareData().m_Common.m_sFile.m_nFileShareMode );

#ifdef _DEBUG
{
// 編集禁止コマンドの並びをチェック
Expand Down Expand Up @@ -676,20 +673,18 @@ void CEditDoc::OnChangeSetting(
}

/* ファイルの排他モード変更 */
if( m_cDocFile.GetShareMode() != GetDllShareData().m_Common.m_sFile.m_nFileShareMode ){
m_cDocFile.SetShareMode( GetDllShareData().m_Common.m_sFile.m_nFileShareMode );

if(! m_cDocFile.IsFileLocking() || m_cDocFile.GetShareMode() != GetDllShareData().m_Common.m_sFile.m_nFileShareMode ){
/*
以前は ! m_cDocFile.IsFileLocking() に相当する条件がなかったため、
上書き不可から可能な状態に変化しても、排他オプションを変更するまで
排他制御のリトライが行われていなかった。その挙動は保存していない。
*/
/* ファイルの排他ロック解除 */
m_cDocFileOperation.DoFileUnlock();

// ファイル書込可能のチェック処理
bool bOld = m_cDocLocker.IsDocWritable();
m_cDocLocker.CheckWritable(bOld && !CAppMode::getInstance()->IsViewMode()); // 書込可から不可に遷移したときだけメッセージを出す(出過ぎると鬱陶しいよね?)

/* ファイルの排他ロック */
if( m_cDocLocker.IsDocWritable() ){
m_cDocFileOperation.DoFileLock();
}
//// 上書き可能かどうかファイルの状態の変化を反映できるようにする。
//m_cDocLocker.CheckWritable();
/* ファイルの排他ロック(必要がなければ実際にロックはしない) */
m_cDocFileOperation.DoFileLock();
}

/* 共有データ構造体のアドレスを返す */
Expand Down
2 changes: 1 addition & 1 deletion sakura_core/doc/CEditDoc.h
Expand Up @@ -96,7 +96,7 @@ class CEditDoc
bool GetDocumentBomExist() const; //!< ドキュメントのBOM付加を取得
void SetDocumentEncoding(ECodeType eCharCode, bool bBom); //!< ドキュメントの文字コードを設定
bool IsModificationForbidden( EFunctionCode nCommand ) const; //!< 指定コマンドによる書き換えが禁止されているかどうか //Aug. 14, 2000 genta
bool IsEditable() const { return !CAppMode::getInstance()->IsViewMode() && !(!m_cDocLocker.IsDocWritable() && GetDllShareData().m_Common.m_sFile.m_bUneditableIfUnwritable); } //!< 編集可能かどうか
bool IsEditable() const { return !CAppMode::getInstance()->IsViewMode() && ! (GetDllShareData().m_Common.m_sFile.m_bUneditableIfUnwritable && ! m_cDocLocker.IsDocWritable()); } //!< 編集可能かどうか
void GetSaveInfo(SSaveInfo* pSaveInfo) const; //!< セーブ情報を取得

//状態
Expand Down
4 changes: 3 additions & 1 deletion sakura_core/io/CFile.cpp
Expand Up @@ -9,7 +9,7 @@

CFile::CFile(LPCTSTR pszPath)
: m_hLockedFile( INVALID_HANDLE_VALUE )
, m_nFileShareModeOld( SHAREMODE_NOT_EXCLUSIVE )
, m_nFileShareMode( SHAREMODE_NOT_EXCLUSIVE )
{
if(pszPath){
SetFilePath(pszPath);
Expand Down Expand Up @@ -87,6 +87,7 @@ void CFile::FileUnlock()
if( m_hLockedFile != INVALID_HANDLE_VALUE ){
::CloseHandle( m_hLockedFile );
m_hLockedFile = INVALID_HANDLE_VALUE;
m_nFileShareMode = SHAREMODE_NOT_EXCLUSIVE;
}
}

Expand All @@ -104,6 +105,7 @@ bool CFile::FileLock( EShareMode eShareMode, bool bMsg )

// モード設定
if(eShareMode==SHAREMODE_NOT_EXCLUSIVE)return true;
m_nFileShareMode = eShareMode; // 設定はするけど IsFileLocking() でないなら意味のない値。

//フラグ
DWORD dwShareMode=0;
Expand Down
5 changes: 2 additions & 3 deletions sakura_core/io/CFile.h
Expand Up @@ -53,12 +53,11 @@ class CFile{
bool FileLock(EShareMode eShareMode, bool bMsg); //!< ファイルの排他ロック
void FileUnlock(); //!< ファイルの排他ロック解除
bool IsFileLocking() const{ return m_hLockedFile!=INVALID_HANDLE_VALUE; }
EShareMode GetShareMode() const{ return m_nFileShareModeOld; }
void SetShareMode(EShareMode eShareMode) { m_nFileShareModeOld = eShareMode; }
EShareMode GetShareMode() const{ return m_nFileShareMode; } // 意味のない値 unless IsFileLocking();
private:
CFilePath m_szFilePath; //!< ファイルパス
HANDLE m_hLockedFile; //!< ロックしているファイルのハンドル
EShareMode m_nFileShareModeOld; //!< ファイルの排他制御モード
EShareMode m_nFileShareMode; //!< ファイルの排他制御モード
};


Expand Down