EConvertResult CEuc::UnicodeToEUC(const CNativeW& cSrc, CMemory* pDstMem) { // エラー状態 bool bError = false; const wchar_t* pSrc = cSrc.GetStringPtr(); int nSrcLen = cSrc.GetStringLength(); // 必要なバッファサイズを調べてメモリを確保 char* pDst; try{ pDst = new char[nSrcLen * 2]; }catch( ... ){ pDst = NULL; } if( pDst == NULL ){ return RESULT_FAILURE; } // 変換 int nDstLen = UniToEucjp( pSrc, nSrcLen, pDst, &bError ); // pDstMem を更新 pDstMem->SetRawDataHoldBuffer( pDst, nDstLen ); // 後始末 delete [] pDst; if( bError == false ){ return RESULT_COMPLETE; }else{ return RESULT_LOSESOME; } }
/*! GREP置換ダイアログの表示 */ void CViewCommander::Command_GREP_REPLACE_DLG( void ) { CNativeW cmemCurText; CDlgGrepReplace& cDlgGrepRep = GetEditWindow()->m_cDlgGrepReplace; // 複数Grepウィンドウを使い分けている場合などに影響しないように、未設定のときだけHistoryを見る bool bGetHistory = cDlgGrepRep.m_bSetText == false; m_pCommanderView->GetCurrentTextForSearchDlg( cmemCurText, bGetHistory ); if( 0 < cmemCurText.GetStringLength() ){ cDlgGrepRep.m_strText = cmemCurText.GetStringPtr(); cDlgGrepRep.m_bSetText = true; } if( 0 < GetDllShareData().m_sSearchKeywords.m_aReplaceKeys.size() ){ if( cDlgGrepRep.m_nReplaceKeySequence < GetDllShareData().m_Common.m_sSearch.m_nReplaceKeySequence ){ cDlgGrepRep.m_strText2 = GetDllShareData().m_sSearchKeywords.m_aReplaceKeys[0]; } } int nRet = cDlgGrepRep.DoModal( G_AppInstance(), m_pCommanderView->GetHwnd(), GetDocument()->m_cDocFile.GetFilePath(), (LPARAM)m_pCommanderView ); if( !nRet ){ return; } HandleCommand(F_GREP_REPLACE, TRUE, 0, 0, 0, 0); // GREPコマンドの発行 }
void CNativeW::Replace( const wchar_t* pszFrom, int nFromLen, const wchar_t* pszTo, int nToLen ) { CNativeW cmemWork; int nBgnOld = 0; int nBgn = 0; while( nBgn <= GetStringLength() - nFromLen ){ if( 0 == wmemcmp( &GetStringPtr()[nBgn], pszFrom, nFromLen ) ){ if( nBgnOld == 0 && nFromLen <= nToLen ){ cmemWork.AllocStringBuffer( GetStringLength() ); } if( 0 < nBgn - nBgnOld ){ cmemWork.AppendString( &GetStringPtr()[nBgnOld], nBgn - nBgnOld ); } cmemWork.AppendString( pszTo, nToLen ); nBgn = nBgn + nFromLen; nBgnOld = nBgn; }else{ nBgn++; } } if( nBgnOld != 0 ){ if( 0 < GetStringLength() - nBgnOld ){ cmemWork.AppendString( &GetStringPtr()[nBgnOld], GetStringLength() - nBgnOld ); } SetNativeData( cmemWork ); }else{ if( this->GetStringPtr() == NULL ){ this->SetString(L""); } } }
/*! 外部ファイルを指定でのファイルを表示 */ BOOL CEditView::MakeDiffTmpFile2( TCHAR* tmpName, const TCHAR* orgName, ECodeType code, ECodeType saveCode ) { //一時 TCHAR* pszTmpName = _ttempnam( NULL, SAKURA_DIFF_TEMP_PREFIX ); if( NULL == pszTmpName ){ WarningMessage( NULL, LS(STR_DIFF_FAILED) ); return FALSE; } _tcscpy( tmpName, pszTmpName ); free( pszTmpName ); bool bBom = false; const STypeConfigMini* typeMini; CDocTypeManager().GetTypeConfigMini( CDocTypeManager().GetDocumentTypeOfPath( orgName ), &typeMini ); CFileLoad cfl( typeMini->m_encoding ); CTextOutputStream out(tmpName, saveCode, true, false); if(!out){ WarningMessage( NULL, LS(STR_DIFF_FAILED_TEMP) ); return FALSE; } try{ bool bBigFile; #ifdef _WIN64 bBigFile = true; #else bBigFile = false; #endif cfl.FileOpen( orgName, bBigFile, code, GetDllShareData().m_Common.m_sFile.GetAutoMIMEdecode(), &bBom ); CNativeW cLine; CEol cEol; while( RESULT_FAILURE != cfl.ReadLine( &cLine, &cEol ) ) { const wchar_t* pLineData; CLogicInt nLineLen; pLineData= cLine.GetStringPtr(&nLineLen); if( 0 == nLineLen || NULL == pLineData ) break; if( bBom ){ CNativeW cLine2(L"\ufeff"); cLine2.AppendString(pLineData, nLineLen); out.WriteString(cLine2.GetStringPtr(), cLine2.GetStringLength()); bBom = false; }else{ out.WriteString(pLineData,nLineLen); } } if( bBom ){ out.WriteString(L"\ufeff", 1); } } catch(...){ out.Close(); _tunlink( tmpName ); //関数の実行に失敗したとき、一時ファイルの削除は関数内で行う。 WarningMessage( NULL, LS(STR_DIFF_FAILED_TEMP) ); return FALSE; } return TRUE; }
/*! Profileをリソースから読み出す @param pName [in] リソース名 @param pType [in] リソースタイプ @retval true 成功 @retval false 失敗 @date 2010/5/19 MainMenu用に作成 1行300文字までに制限 */ bool CProfile::ReadProfileRes( const TCHAR* pName, const TCHAR* pType, std::vector<std::wstring>* pData ) { static const BYTE UTF8_BOM[]={0xEF,0xBB,0xBF}; HRSRC hRsrc; HGLOBAL hGlobal; size_t nSize; char* psMMres; char* p; char sLine[300+1]; char* pn; size_t lnsz; wstring line; CMemory cmLine; CNativeW cmLineW; m_strProfileName = _T("-Res-"); if (( hRsrc = ::FindResource( 0, pName, pType )) != NULL && ( hGlobal = ::LoadResource( 0, hRsrc )) != NULL && ( psMMres = (char *)::LockResource(hGlobal)) != NULL && ( nSize = (size_t)::SizeofResource( 0, hRsrc )) != 0) { p = psMMres; if (nSize >= sizeof(UTF8_BOM) && memcmp( p, UTF8_BOM, sizeof(UTF8_BOM) )==0) { // Skip BOM p += sizeof(UTF8_BOM); } for (; p < psMMres + nSize ; p = pn) { // 1行切り取り(長すぎた場合切捨て) pn = strpbrk(p, "\n"); if (pn == NULL) { // 最終行 pn = psMMres + nSize; } else { pn++; } lnsz = (pn-p)<=300 ? (pn-p) : 300; memcpy(sLine, p, lnsz); sLine[lnsz] = '\0'; if (sLine[lnsz-1] == '\n') sLine[--lnsz] = '\0'; if (sLine[lnsz-1] == '\r') sLine[--lnsz] = '\0'; // UTF-8 -> UNICODE cmLine.SetRawDataHoldBuffer( sLine, lnsz ); CUtf8::UTF8ToUnicode( cmLine, &cmLineW ); line = cmLineW.GetStringPtr(); if( pData ){ pData->push_back(line); }else{ //解析 ReadOneline(line); } } } return true; }
/* 外部ヘルプ1 @date 2012.09.26 Moca HTMLHELP対応 */ void CViewCommander::Command_EXTHELP1( void ) { retry:; if( CHelpManager().ExtWinHelpIsSet( &(GetDocument()->m_cDocType.GetDocumentAttribute()) ) == false){ // if( 0 == wcslen( GetDllShareData().m_Common.m_szExtHelp1 ) ){ ErrorBeep(); //From Here Sept. 15, 2000 JEPRO // [Esc]キーと[x]ボタンでも中止できるように変更 if( IDYES == ::MYMESSAGEBOX( NULL, MB_YESNOCANCEL | MB_ICONEXCLAMATION | MB_APPLMODAL | MB_TOPMOST, GSTR_APPNAME, //To Here Sept. 15, 2000 LS(STR_ERR_CEDITVIEW_CMD01) ) ){ /* 共通設定 プロパティシート */ if( !CEditApp::getInstance()->OpenPropertySheet( ID_PROPCOM_PAGENUM_HELPER ) ){ return; } goto retry; } // Jun. 15, 2000 genta else{ return; } } CNativeW cmemCurText; const TCHAR* helpfile = CHelpManager().GetExtWinHelp( &(GetDocument()->m_cDocType.GetDocumentAttribute()) ); /* 現在カーソル位置単語または選択範囲より検索等のキーを取得 */ m_pCommanderView->GetCurrentTextForSearch( cmemCurText, false ); TCHAR path[_MAX_PATH]; if( _IS_REL_PATH( helpfile ) ){ // 2003.06.23 Moca 相対パスは実行ファイルからのパス // 2007.05.21 ryoji 相対パスは設定ファイルからのパスを優先 GetInidirOrExedir( path, helpfile ); }else{ auto_strcpy( path, helpfile ); } // 2012.09.26 Moca HTMLHELP対応 TCHAR szExt[_MAX_EXT]; _tsplitpath( path, NULL, NULL, NULL, szExt ); if( 0 == _tcsicmp(szExt, _T(".chi")) || 0 == _tcsicmp(szExt, _T(".chm")) || 0 == _tcsicmp(szExt, _T(".col")) ){ std::wstring pathw = to_wchar(path); Command_EXTHTMLHELP( pathw.c_str(), cmemCurText.GetStringPtr() ); }else{ ::WinHelp( m_pCommanderView->m_hwndParent, path, HELP_KEY, (ULONG_PTR)cmemCurText.GetStringPtr() ); } return; }
/* uudecodeして保存 */ void CViewCommander::Command_UUDECODE( void ) { /* テキストが選択されているか */ if( !m_pCommanderView->GetSelectionInfo().IsTextSelected() ){ ErrorBeep(); return; } // 選択範囲のデータを取得 -> cmemBuf // 正常時はTRUE,範囲未選択の場合はFALSEを返す CNativeW ctextBuf; if( !m_pCommanderView->GetSelectedDataSimple(ctextBuf) ){ ErrorBeep(); return; } // uudecode(デコード) ctextBuf -> cmemBin, szPath CMemory cmemBin; TCHAR szPath[_MAX_PATH]=_T(""); CDecode_UuDecode decoder; if( !decoder.CallDecode(ctextBuf, &cmemBin) ){ return; } decoder.CopyFilename( szPath ); ctextBuf.Clear(); /* 保存ダイアログ モーダルダイアログの表示 */ if( !GetDocument()->m_cDocFileOperation.SaveFileDialog( szPath ) ){ return; } //データ int nDataLen; const void* pData = cmemBin.GetRawPtr(&nDataLen); //カキコ CBinaryOutputStream out(szPath); if( !out )goto err; if( nDataLen != out.Write(pData,nDataLen) )goto err; //完了 return; err: ErrorBeep(); ErrorMessage( m_pCommanderView->GetHwnd(), LS(STR_ERR_CEDITVIEW_CMD16), szPath ); }
/* 等しい内容か */ bool CNativeW::IsEqual( const CNativeW& cmem1, const CNativeW& cmem2 ) { if(&cmem1==&cmem2)return true; const wchar_t* psz1; const wchar_t* psz2; int nLen1; int nLen2; psz1 = cmem1.GetStringPtr( &nLen1 ); psz2 = cmem2.GetStringPtr( &nLen2 ); if( nLen1 == nLen2 ){ if( 0 == wmemcmp( psz1, psz2, nLen1 ) ){ return true; } } return false; }
/* Base64デコードして保存 */ void CViewCommander::Command_BASE64DECODE( void ) { /* テキストが選択されているか */ if( !m_pCommanderView->GetSelectionInfo().IsTextSelected() ){ ErrorBeep(); return; } /* 選択範囲のデータを取得 */ /* 正常時はTRUE,範囲未選択の場合はFALSEを返す */ CNativeW ctextBuf; if( !m_pCommanderView->GetSelectedDataSimple(ctextBuf) ){ ErrorBeep(); return; } /* Base64デコード */ CMemory cmemBuf; bool bret = CDecode_Base64Decode().CallDecode(ctextBuf, &cmemBuf); if( !bret ){ return; } ctextBuf.Clear(); /* 保存ダイアログ モーダルダイアログの表示 */ TCHAR szPath[_MAX_PATH] = _T(""); if( !GetDocument()->m_cDocFileOperation.SaveFileDialog( szPath ) ){ return; } //データ int nDataLen; const void* pData = cmemBuf.GetRawPtr(&nDataLen); //カキコ CBinaryOutputStream out(szPath); if(!out)goto err; if( nDataLen != out.Write(pData, nDataLen) )goto err; return; err: ErrorBeep(); ErrorMessage( m_pCommanderView->GetHwnd(), LS(STR_ERR_CEDITVIEW_CMD14), szPath ); }
// 文字コード表示用 UNICODE → Hex 変換 2008/6/9 Uchi EConvertResult CEuc::UnicodeToHex(const wchar_t* cSrc, const int iSLen, TCHAR* pDst, const CommonSetting_Statusbar* psStatusbar) { CNativeW cCharBuffer; EConvertResult res; int i; TCHAR* pd; unsigned char* ps; bool bbinary=false; // 2008/6/21 Uchi if (psStatusbar->m_bDispUniInEuc) { // Unicodeで表示 return CCodeBase::UnicodeToHex(cSrc, iSLen, pDst, psStatusbar); } // 1文字データバッファ cCharBuffer.SetString(cSrc, 1); if( IsBinaryOnSurrogate(cSrc[0]) ){ bbinary = true; } // EUC-JP 変換 res = UnicodeToEUC(cCharBuffer, cCharBuffer._GetMemory()); if (res != RESULT_COMPLETE) { return res; } // Hex変換 ps = reinterpret_cast<unsigned char*>( cCharBuffer._GetMemory()->GetRawPtr() ); pd = pDst; if( bbinary == false ){ for (i = cCharBuffer._GetMemory()->GetRawLength(); i >0; i--, ps ++, pd += 2) { auto_sprintf( pd, _T("%02X"), *ps); } }else{ auto_sprintf( pd, _T("?%02X"), *ps ); } return RESULT_COMPLETE; }
// 文字コード表示用 UNICODE → Hex 変換 2008/6/21 Uchi EConvertResult CUtf8::_UnicodeToHex(const wchar_t* cSrc, const int iSLen, TCHAR* pDst, const CommonSetting_Statusbar* psStatusbar, const bool bCESUMode) { CNativeW cBuff; EConvertResult res; int i; TCHAR* pd; unsigned char* ps; bool bbinary=false; if (psStatusbar->m_bDispUtf8Codepoint) { // Unicodeで表示 return CCodeBase::UnicodeToHex(cSrc, iSLen, pDst, psStatusbar); } cBuff.AllocStringBuffer(4); // 1文字データバッファ if (IsUTF16High(cSrc[0]) && iSLen >= 2 && IsUTF16Low(cSrc[1])) { cBuff._GetMemory()->SetRawDataHoldBuffer(cSrc, 4); } else { cBuff._GetMemory()->SetRawDataHoldBuffer(cSrc, 2); if( IsBinaryOnSurrogate(cSrc[0]) ){ bbinary = true; } } // UTF-8/CESU-8 変換 if (bCESUMode != true) { res = UnicodeToUTF8(cBuff, cBuff._GetMemory()); } else { res = UnicodeToCESU8(cBuff, cBuff._GetMemory()); } if (res != RESULT_COMPLETE) { return res; } // Hex変換 ps = reinterpret_cast<unsigned char*>( cBuff._GetMemory()->GetRawPtr() ); pd = pDst; if( bbinary == false ){ for (i = cBuff._GetMemory()->GetRawLength(); i >0; i--, ps ++, pd += 2) { auto_sprintf( pd, _T("%02X"), *ps); } }else{ auto_sprintf( pd, _T("?%02X"), *ps ); } return RESULT_COMPLETE; }
/*! GREPダイアログの表示 @date 2005.01.10 genta CEditView_Commandより移動 @author Yazaki */ void CViewCommander::Command_GREP_DIALOG( void ) { CNativeW cmemCurText; // 2014.07.01 複数Grepウィンドウを使い分けている場合などに影響しないように、未設定のときだけHistoryを見る bool bGetHistory = GetEditWindow()->m_cDlgGrep.m_bSetText == false; /* 現在カーソル位置単語または選択範囲より検索等のキーを取得 */ bool bSet = m_pCommanderView->GetCurrentTextForSearchDlg( cmemCurText, bGetHistory ); // 2006.08.23 ryoji ダイアログ専用関数に変更 if( bSet ){ GetEditWindow()->m_cDlgGrep.m_strText = cmemCurText.GetStringPtr(); GetEditWindow()->m_cDlgGrep.m_bSetText = true; } /* Grepダイアログの表示 */ int nRet = GetEditWindow()->m_cDlgGrep.DoModal( G_AppInstance(), m_pCommanderView->GetHwnd(), GetDocument()->m_cDocFile.GetFilePath() ); // MYTRACE( _T("nRet=%d\n"), nRet ); if( !nRet ){ return; } HandleCommand(F_GREP, true, 0, 0, 0, 0); // GREPコマンドの発行 }
/*! キーボードマクロの読み込み(ファイルから) エラーメッセージは出しません。呼び出し側でよきにはからってください。 */ BOOL CPPAMacroMgr::LoadKeyMacro( HINSTANCE hInstance, const TCHAR* pszPath ) { CTextInputStream in( pszPath ); if(!in) { m_nReady = false; return FALSE; } CNativeW cmemWork; // バッファ(cmemWork)にファイル内容を読み込み、m_cPPAに渡す。 while( in ) { wstring szLine = in.ReadLineW(); szLine += L"\n"; cmemWork.AppendString(szLine.c_str()); } in.Close(); m_cBuffer.SetNativeData( cmemWork ); // m_cBufferにコピー m_nReady = true; return TRUE; }
/*! カーソル行をクリップボードにコピーする @date 2007.10.08 ryoji 新規(Command_COPY()から処理抜き出し) */ void CEditView::CopyCurLine( bool bAddCRLFWhenCopy, //!< [in] 折り返し位置に改行コードを挿入するか? EEolType neweol, //!< [in] コピーするときのEOL。 bool bEnableLineModePaste //!< [in] ラインモード貼り付けを可能にする ) { if( GetSelectionInfo().IsTextSelected() ){ return; } const CLayout* pcLayout = m_pcEditDoc->m_cLayoutMgr.SearchLineByLayoutY( GetCaret().GetCaretLayoutPos().y ); if( NULL == pcLayout ){ return; } /* クリップボードに入れるべきテキストデータを、cmemBufに格納する */ CNativeW cmemBuf; cmemBuf.SetString( pcLayout->GetPtr(), pcLayout->GetLengthWithoutEOL() ); if( pcLayout->GetLayoutEol().GetLen() != 0 ){ cmemBuf.AppendString( ( neweol == EOL_UNKNOWN ) ? pcLayout->GetLayoutEol().GetValue2() : CEol(neweol).GetValue2() ); }else if( bAddCRLFWhenCopy ){ // 2007.10.08 ryoji bAddCRLFWhenCopy対応処理追加 cmemBuf.AppendString( ( neweol == EOL_UNKNOWN ) ? WCODE::CRLF : CEol(neweol).GetValue2() ); } /* クリップボードにデータcmemBufの内容を設定 */ BOOL bSetResult = MySetClipboardData( cmemBuf.GetStringPtr(), cmemBuf.GetStringLength(), false, bEnableLineModePaste ); if( !bSetResult ){ ErrorBeep(); } }
/*! バッファ内容をファイルに書き出す (テスト用) @note Windows用にコーディングしてある @date 2003.07.26 ryoji BOM引数追加 */ EConvertResult CWriteManager::WriteFile_From_CDocLineMgr( const CDocLineMgr& pcDocLineMgr, //!< [in] const SSaveInfo& sSaveInfo //!< [in] ) { EConvertResult nRetVal = RESULT_COMPLETE; std::auto_ptr<CCodeBase> pcCodeBase( CCodeFactory::CreateCodeBase(sSaveInfo.eCharCode,0) ); { // 変換テスト CNativeW buffer = L"abcde"; CMemory tmp; EConvertResult e = pcCodeBase->UnicodeToCode( buffer, &tmp ); if(e==RESULT_FAILURE){ nRetVal=RESULT_FAILURE; ErrorMessage( CEditWnd::getInstance()->GetHwnd(), LS(STR_FILESAVE_CONVERT_ERROR), sSaveInfo.cFilePath.c_str() ); return nRetVal; } } try { //ファイルオープン CBinaryOutputStream out(sSaveInfo.cFilePath,true); //各行出力 int nLineNumber = 0; const CDocLine* pcDocLine = pcDocLineMgr.GetDocLineTop(); // 1行目 { ++nLineNumber; CMemory cmemOutputBuffer; { CNativeW cstrSrc; CMemory cstrBomCheck; pcCodeBase->GetBom( &cstrBomCheck ); if( sSaveInfo.bBomExist && 0 < cstrBomCheck.GetRawLength() ){ // 1行目にはBOMを付加する。エンコーダでbomがある場合のみ付加する。 CUnicode().GetBom( cstrSrc._GetMemory() ); } if( pcDocLine ){ cstrSrc.AppendNativeData( pcDocLine->_GetDocLineDataWithEOL() ); } EConvertResult e = pcCodeBase->UnicodeToCode( cstrSrc, &cmemOutputBuffer ); if(e==RESULT_LOSESOME){ nRetVal=RESULT_LOSESOME; } if(e==RESULT_FAILURE){ nRetVal=RESULT_FAILURE; ErrorMessage( CEditWnd::getInstance()->GetHwnd(), LS(STR_FILESAVE_CONVERT_ERROR), sSaveInfo.cFilePath.c_str() ); throw CError_FileWrite(); } } out.Write(cmemOutputBuffer.GetRawPtr(), cmemOutputBuffer.GetRawLength()); if( pcDocLine ){ pcDocLine = pcDocLine->GetNextLine(); } } CMemory cmemOutputBuffer; while( pcDocLine ){ ++nLineNumber; //経過通知 if(pcDocLineMgr.GetLineCount()>0 && nLineNumber%1024==0){ NotifyProgress(nLineNumber * 100 / pcDocLineMgr.GetLineCount()); // 処理中のユーザー操作を可能にする if( !::BlockingHook( NULL ) ){ throw CAppExitException(); //中断検出 } } //1行出力 -> cmemOutputBuffer { // 書き込み時のコード変換 cstrSrc -> cmemOutputBuffer EConvertResult e = pcCodeBase->UnicodeToCode( pcDocLine->_GetDocLineDataWithEOL(), &cmemOutputBuffer ); if(e==RESULT_LOSESOME){ if(nRetVal==RESULT_COMPLETE)nRetVal=RESULT_LOSESOME; } if(e==RESULT_FAILURE){ nRetVal=RESULT_FAILURE; ErrorMessage( CEditWnd::getInstance()->GetHwnd(), LS(STR_FILESAVE_CONVERT_ERROR), sSaveInfo.cFilePath.c_str() ); break; } } //ファイルに出力 cmemOutputBuffer -> fp out.Write(cmemOutputBuffer.GetRawPtr(), cmemOutputBuffer.GetRawLength()); //次の行へ pcDocLine = pcDocLine->GetNextLine(); } //ファイルクローズ out.Close(); } catch(CError_FileOpen){ //########### 現時点では、この例外が発生した場合は正常に動作できない ErrorMessage( CEditWnd::getInstance()->GetHwnd(), LS(STR_SAVEAGENT_OTHER_APP), sSaveInfo.cFilePath.c_str() ); nRetVal = RESULT_FAILURE; } catch(CError_FileWrite){ nRetVal = RESULT_FAILURE; } catch(CAppExitException){ //中断検出 return RESULT_FAILURE; } return nRetVal; }
/* 指定範囲のデータを置換(削除 & データを挿入) Fromを含む位置からToの直前を含むデータを削除する Fromの位置へテキストを挿入する */ void CSearchAgent::ReplaceData( DocLineReplaceArg* pArg ) { // MY_RUNNINGTIMER( cRunningTimer, "CDocLineMgr::ReplaceData()" ); /* 挿入によって増えた行の数 */ pArg->nInsLineNum = CLogicInt(0); /* 削除した行の総数 */ pArg->nDeletedLineNum = CLogicInt(0); /* 削除されたデータ */ if( pArg->pcmemDeleted ){ pArg->pcmemDeleted->clear(); } CDocLine* pCDocLine; CDocLine* pCDocLinePrev; CDocLine* pCDocLineNext; int nWorkPos; int nWorkLen; const wchar_t* pLine; int nLineLen; int i; CLogicInt nAllLinesOld; int nProgress; CDocLine::MarkType markNext; // May 15, 2000 HWND hwndCancel = NULL; // 初期化 HWND hwndProgress = NULL; // 初期化 pArg->ptNewPos = pArg->sDelRange.GetFrom(); /* 大量のデータを操作するとき */ CDlgCancel* pCDlgCancel = NULL; class CDLgCandelCloser{ CDlgCancel*& m_pDlg; public: CDLgCandelCloser(CDlgCancel*& pDlg): m_pDlg(pDlg){} ~CDLgCandelCloser(){ if( NULL != m_pDlg ){ // 進捗ダイアログを表示しない場合と同じ動きになるようにダイアログは遅延破棄する // ここで pCDlgCancel を delete すると delete から戻るまでの間に // ダイアログ破棄 -> 編集画面へフォーカス移動 -> キャレット位置調整 // まで一気に動くので無効なレイアウト情報参照で異常終了することがある m_pDlg->DeleteAsync(); // 自動破棄を遅延実行する // 2008.05.28 ryoji } } }; CDLgCandelCloser closer(pCDlgCancel); const CLogicInt nDelLines = pArg->sDelRange.GetTo().y - pArg->sDelRange.GetFrom().y; const CLogicInt nEditLines = std::max<CLogicInt>(CLogicInt(1), nDelLines + CLogicInt(pArg->pInsData ? pArg->pInsData->size(): 0)); if( 3000 < nEditLines ){ /* 進捗ダイアログの表示 */ pCDlgCancel = new CDlgCancel; if( NULL != ( hwndCancel = pCDlgCancel->DoModeless( ::GetModuleHandle( NULL ), NULL, IDD_OPERATIONRUNNING ) ) ){ hwndProgress = ::GetDlgItem( hwndCancel, IDC_PROGRESS ); Progress_SetRange( hwndProgress, 0, 101 ); Progress_SetPos( hwndProgress, 0 ); } } int nProgressOld = 0; // バッファを確保 if( pArg->pcmemDeleted ){ pArg->pcmemDeleted->reserve( pArg->sDelRange.GetTo().y + CLogicInt(1) - pArg->sDelRange.GetFrom().y ); } // 2012.01.10 行内の削除&挿入のときの操作を1つにする bool bChangeOneLine = false; // 行内の挿入 bool bInsOneLine = false; bool bLastEOLReplace = false; // 「最後改行」を「最後改行」で置換 if( pArg->pInsData && 0 < pArg->pInsData->size() ){ const CNativeW& cmemLine = pArg->pInsData->back().cmemLine; int nLen = cmemLine.GetStringLength(); const wchar_t* pInsLine = cmemLine.GetStringPtr(); if( 0 < nLen && WCODE::IsLineDelimiter(pInsLine[nLen - 1], GetDllShareData().m_Common.m_sEdit.m_bEnableExtEol) ){ // 行挿入 bLastEOLReplace = true; // 仮。後で修正 }else{ if( 1 == pArg->pInsData->size() ){ bChangeOneLine = true; // 「abc\ndef」=>「123」のような置換もtrueなのに注意 } } } const wchar_t* pInsData = L""; int nInsLen = 0; int nSetSeq = 0; if( bChangeOneLine ){ nInsLen = pArg->pInsData->back().cmemLine.GetStringLength(); pInsData = pArg->pInsData->back().cmemLine.GetStringPtr(); nSetSeq = pArg->pInsData->back().nSeq; } /* 現在行の情報を得る */ pCDocLine = m_pcDocLineMgr->GetLine( pArg->sDelRange.GetTo().GetY2() ); i = pArg->sDelRange.GetTo().y; if( 0 < pArg->sDelRange.GetTo().y && NULL == pCDocLine ){ pCDocLine = m_pcDocLineMgr->GetLine( pArg->sDelRange.GetTo().GetY2() - CLogicInt(1) ); i--; } bool bFirstLine = true; bool bSetMark = false; /* 後ろから処理していく */ for( ; i >= pArg->sDelRange.GetFrom().y && NULL != pCDocLine; i-- ){ pLine = pCDocLine->GetPtr(); // 2002/2/10 aroka CMemory変更 nLineLen = pCDocLine->GetLengthWithEOL(); // 2002/2/10 aroka CMemory変更 pCDocLinePrev = pCDocLine->GetPrevLine(); pCDocLineNext = pCDocLine->GetNextLine(); /* 現在行の削除開始位置を調べる */ if( i == pArg->sDelRange.GetFrom().y ){ nWorkPos = pArg->sDelRange.GetFrom().x; }else{ nWorkPos = 0; } /* 現在行の削除データ長を調べる */ if( i == pArg->sDelRange.GetTo().y ){ nWorkLen = pArg->sDelRange.GetTo().x - nWorkPos; }else{ nWorkLen = nLineLen - nWorkPos; // 2002/2/10 aroka CMemory変更 } if( 0 == nWorkLen ){ /* 前の行へ */ goto prev_line; } /* 改行も削除するんかぃのぉ・・・? */ if( EOL_NONE != pCDocLine->GetEol() && nWorkPos + nWorkLen > nLineLen - pCDocLine->GetEol().GetLen() // 2002/2/10 aroka CMemory変更 ){ /* 削除する長さに改行も含める */ nWorkLen = nLineLen - nWorkPos; // 2002/2/10 aroka CMemory変更 } /* 行全体の削除 */ if( nWorkLen >= nLineLen ){ // 2002/2/10 aroka CMemory変更 /* 削除した行の総数 */ ++(pArg->nDeletedLineNum); /* 行オブジェクトの削除、リスト変更、行数-- */ if( pArg->pcmemDeleted ){ CLineData tmp; pArg->pcmemDeleted->push_back(tmp); CLineData& delLine = pArg->pcmemDeleted->back(); delLine.cmemLine.swap(pCDocLine->_GetDocLineData()); // CDocLine書き換え delLine.nSeq = CModifyVisitor().GetLineModifiedSeq(pCDocLine); } m_pcDocLineMgr->DeleteLine( pCDocLine ); pCDocLine = NULL; } /* 次の行と連結するような削除 */ else if( nWorkPos + nWorkLen >= nLineLen ){ // 2002/2/10 aroka CMemory変更 if( pArg->pcmemDeleted ){ if( pCDocLineNext && 0 == pArg->pcmemDeleted->size() ){ // 1行以内の行末削除のときだけ、次の行のseqが保存されないので必要 // 2014.01.07 最後が改行の範囲を最後が改行のデータで置換した場合を変更 if( !bLastEOLReplace ){ CLineData tmp; pArg->pcmemDeleted->push_back(tmp); CLineData& delLine = pArg->pcmemDeleted->back(); delLine.cmemLine.SetString(L""); delLine.nSeq = CModifyVisitor().GetLineModifiedSeq(pCDocLineNext); } } CLineData tmp; pArg->pcmemDeleted->push_back(tmp); CLineData& delLine = pArg->pcmemDeleted->back(); delLine.cmemLine.SetString(&pLine[nWorkPos], nWorkLen); delLine.nSeq = CModifyVisitor().GetLineModifiedSeq(pCDocLine); } /* 次の行がある */ if( pCDocLineNext ){ /* 次の行のデータを最後に追加 */ // 改行を削除するような置換 int nNewLen = nWorkPos + pCDocLineNext->GetLengthWithEOL() + nInsLen; if( nWorkLen <= nWorkPos && nLineLen <= nNewLen + 10 ){ // 行を連結して1行にするような操作の高速化 // 削除が元データの有効長以下で行の長さが伸びるか少し減る場合reallocを試みる static CDocLine* pDocLinePrevAccess = NULL; static int nAccessCount = 0; int nBufferReserve = nNewLen; if( pDocLinePrevAccess == pCDocLine ){ if( 100 < nAccessCount ){ if( 1000 < nNewLen ){ int n = 1000; while( n < nNewLen ){ n += n / 5; // 20%づつ伸ばす } nBufferReserve = n; } }else{ nAccessCount++; } }else{ pDocLinePrevAccess = pCDocLine; nAccessCount = 0; } CNativeW& ref = pCDocLine->_GetDocLineData(); ref.AllocStringBuffer(nBufferReserve); ref._SetStringLength(nWorkPos); ref.AppendString(pInsData, nInsLen); ref.AppendNativeData(pCDocLineNext->_GetDocLineDataWithEOL()); pCDocLine->SetEol(); }else{ CNativeW tmp; tmp.AllocStringBuffer(nNewLen); tmp.AppendString(pLine, nWorkPos); tmp.AppendString(pInsData, nInsLen); tmp.AppendNativeData(pCDocLineNext->_GetDocLineDataWithEOL()); pCDocLine->SetDocLineStringMove(&tmp); } if( bChangeOneLine ){ pArg->nInsSeq = CModifyVisitor().GetLineModifiedSeq(pCDocLine); CModifyVisitor().SetLineModified(pCDocLine, nSetSeq); if( !bInsOneLine ){ pArg->ptNewPos.x = pArg->ptNewPos.x + nInsLen; bInsOneLine = true; } }else{ CModifyVisitor().SetLineModified(pCDocLine, pArg->nDelSeq); // 削除される行のマーク類を保存 markNext = pCDocLineNext->m_sMark; bSetMark = true; } /* 次の行 行オブジェクトの削除 */ m_pcDocLineMgr->DeleteLine( pCDocLineNext ); pCDocLineNext = NULL; /* 削除した行の総数 */ ++(pArg->nDeletedLineNum); }else{ /* 行内データ削除 */ CNativeW tmp; tmp.SetString(pLine, nWorkPos); pCDocLine->SetDocLineStringMove(&tmp); CModifyVisitor().SetLineModified(pCDocLine, pArg->nDelSeq); /* 変更フラグ */ } } else{ /* 行内だけの削除 */ if( pArg->pcmemDeleted ){ CLineData tmp; pArg->pcmemDeleted->push_back(tmp); CLineData& delLine = pArg->pcmemDeleted->back(); delLine.cmemLine.SetString(&pLine[nWorkPos], nWorkLen); delLine.nSeq = CModifyVisitor().GetLineModifiedSeq(pCDocLine); } {// 20020119 aroka ブロック内に pWork を閉じ込めた // 2002/2/10 aroka CMemory変更 何度も GetLength,GetPtr をよばない。 int nNewLen = nLineLen - nWorkLen + nInsLen; int nAfterLen = nLineLen - (nWorkPos + nWorkLen); if( pCDocLine->_GetDocLineData().capacity() * 9 / 10 < nNewLen && nNewLen <= pCDocLine->_GetDocLineData().capacity() ){ CNativeW& ref = pCDocLine->_GetDocLineData(); WCHAR* pBuf = const_cast<WCHAR*>(ref.GetStringPtr()); if( nWorkLen != nInsLen ){ wmemmove(&pBuf[nWorkPos + nInsLen], &pLine[nWorkPos + nWorkLen], nAfterLen); } wmemcpy(&pBuf[nWorkPos], pInsData, nInsLen); ref._SetStringLength(nNewLen); }else{ int nBufferSize = 16; if( 1000 < nNewLen ){ nBufferSize = 1000; while( nBufferSize < nNewLen ){ nBufferSize += nBufferSize / 20; // 5%づつ伸ばす } } CNativeW tmp; tmp.AllocStringBuffer(nBufferSize); tmp.AppendString(pLine, nWorkPos); tmp.AppendString(pInsData, nInsLen); tmp.AppendString(&pLine[nWorkPos + nWorkLen], nAfterLen); pCDocLine->SetDocLineStringMove(&tmp); } } if( bChangeOneLine ){ pArg->nInsSeq = CModifyVisitor().GetLineModifiedSeq(pCDocLine); CModifyVisitor().SetLineModified(pCDocLine, nSetSeq); pArg->ptNewPos.x = pArg->ptNewPos.x + nInsLen; bInsOneLine = true; pInsData = L""; nInsLen = 0; }else{ CModifyVisitor().SetLineModified(pCDocLine, pArg->nDelSeq); } if( bFirstLine ){ bLastEOLReplace = false; } } bFirstLine = false; prev_line:; /* 直前の行のオブジェクトのポインタ */ pCDocLine = pCDocLinePrev; /* 最近参照した行番号と行データ */ --m_pcDocLineMgr->m_nPrevReferLine; m_pcDocLineMgr->m_pCodePrevRefer = pCDocLine; if( NULL != hwndCancel){ int nLines = pArg->sDelRange.GetTo().y - i; if( 0 == (nLines % 32) ){ nProgress = ::MulDiv(nLines, 100, nEditLines); if( nProgressOld != nProgress ){ nProgressOld = nProgress; Progress_SetPos( hwndProgress, nProgress + 1 ); Progress_SetPos( hwndProgress, nProgress ); } } } } if( pArg->pcmemDeleted ){ // 下から格納されているのでひっくり返す std::reverse(pArg->pcmemDeleted->begin(), pArg->pcmemDeleted->end()); } if( bInsOneLine ){ // 挿入済み return; } /* データ挿入処理 */ if( NULL == pArg->pInsData || 0 == pArg->pInsData->size() ){ pArg->nInsSeq = 0; return; } nAllLinesOld= m_pcDocLineMgr->GetLineCount(); pArg->ptNewPos.y = pArg->sDelRange.GetFrom().y; /* 挿入された部分の次の位置の行 */ pArg->ptNewPos.x = 0; /* 挿入された部分の次の位置のデータ位置 */ /* 挿入データを行終端で区切った行数カウンタ */ pCDocLine = m_pcDocLineMgr->GetLine( pArg->sDelRange.GetFrom().GetY2() ); int nInsSize = pArg->pInsData->size(); bool bInsertLineMode = false; bool bLastInsert = false; { CNativeW& cmemLine = pArg->pInsData->back().cmemLine; int nLen = cmemLine.GetStringLength(); const wchar_t* pInsLine = cmemLine.GetStringPtr(); if( 0 < nLen && WCODE::IsLineDelimiter(pInsLine[nLen - 1], GetDllShareData().m_Common.m_sEdit.m_bEnableExtEol) ){ if( 0 == pArg->sDelRange.GetFrom().x ){ // 挿入データの最後が改行で行頭に挿入するとき、現在行を維持する bInsertLineMode = true; if( pCDocLine && m_pcDocLineMgr->m_pCodePrevRefer == pCDocLine ){ m_pcDocLineMgr->m_pCodePrevRefer = pCDocLine->GetPrevLine(); if( m_pcDocLineMgr->m_pCodePrevRefer ){ m_pcDocLineMgr->m_nPrevReferLine--; } } } }else{ bLastInsert = true; nInsSize--; } } CStringRef cPrevLine; CStringRef cNextLine; CNativeW cmemCurLine; if( NULL == pCDocLine ){ /* ここでNULLが帰ってくるということは、*/ /* 全テキストの最後の次の行を追加しようとしていることを示す */ pArg->nInsSeq = 0; }else{ // 2002/2/10 aroka 何度も GetPtr を呼ばない if( !bInsertLineMode ){ cmemCurLine.swap(pCDocLine->_GetDocLineData()); pLine = cmemCurLine.GetStringPtr(&nLineLen); cPrevLine = CStringRef(pLine, pArg->sDelRange.GetFrom().x); cNextLine = CStringRef(&pLine[pArg->sDelRange.GetFrom().x], nLineLen - pArg->sDelRange.GetFrom().x); pArg->nInsSeq = CModifyVisitor().GetLineModifiedSeq(pCDocLine); }else{ pArg->nInsSeq = 0; } } int nCount; for( nCount = 0; nCount < nInsSize; nCount++ ){ CNativeW& cmemLine = (*pArg->pInsData)[nCount].cmemLine; #ifdef _DEBUG int nLen = cmemLine.GetStringLength(); const wchar_t* pInsLine = cmemLine.GetStringPtr(); assert( 0 < nLen && WCODE::IsLineDelimiter(pInsLine[nLen - 1], GetDllShareData().m_Common.m_sEdit.m_bEnableExtEol) ); #endif { if( NULL == pCDocLine ){ CDocLine* pCDocLineNew = m_pcDocLineMgr->AddNewLine(); /* 挿入データを行終端で区切った行数カウンタ */ if( 0 == nCount ){ CNativeW tmp; tmp.AllocStringBuffer(cPrevLine.GetLength() + cmemLine.GetStringLength()); tmp.AppendString(cPrevLine.GetPtr(), cPrevLine.GetLength()); tmp.AppendNativeData(cmemLine); pCDocLineNew->SetDocLineStringMove(&tmp); } else{ pCDocLineNew->SetDocLineStringMove(&cmemLine); } CModifyVisitor().SetLineModified(pCDocLineNew, (*pArg->pInsData)[nCount].nSeq); } else{ /* 挿入データを行終端で区切った行数カウンタ */ if( 0 == nCount && !bInsertLineMode ){ if( cmemCurLine.GetStringLength() - cPrevLine.GetLength() < cmemCurLine.GetStringLength() / 100 && cPrevLine.GetLength() + cmemLine.GetStringLength() <= cmemCurLine.GetStringLength() && cmemCurLine.capacity() / 2 <= cPrevLine.GetLength() + cmemLine.GetStringLength() ){ // 行のうちNextになるのが1%以下で行が短くなるなら再利用する(長い一行を分割する場合の最適化) CNativeW tmp; // Nextを退避 tmp.SetString(cNextLine.GetPtr(), cNextLine.GetLength()); cmemCurLine.swap(tmp); tmp._SetStringLength(cPrevLine.GetLength()); tmp.AppendNativeData(cmemLine); pCDocLine->SetDocLineStringMove(&tmp); cNextLine = CStringRef(cmemCurLine.GetStringPtr(), cmemCurLine.GetStringLength()); }else{ CNativeW tmp; tmp.AllocStringBuffer(cPrevLine.GetLength() + cmemLine.GetStringLength()); tmp.AppendString(cPrevLine.GetPtr(), cPrevLine.GetLength()); tmp.AppendNativeData(cmemLine); pCDocLine->SetDocLineStringMove(&tmp); } CModifyVisitor().SetLineModified(pCDocLine, (*pArg->pInsData)[nCount].nSeq); pCDocLine = pCDocLine->GetNextLine(); } else{ CDocLine* pCDocLineNew = m_pcDocLineMgr->InsertNewLine(pCDocLine); //pCDocLineの前に挿入 pCDocLineNew->SetDocLineStringMove(&cmemLine); CModifyVisitor().SetLineModified(pCDocLineNew, (*pArg->pInsData)[nCount].nSeq); } } /* 挿入データを行終端で区切った行数カウンタ */ ++(pArg->ptNewPos.y); /* 挿入された部分の次の位置の行 */ if( NULL != hwndCancel ){ if( 0 == (nCount % 32) ){ nProgress = ::MulDiv(nCount + nDelLines, 100, nEditLines); if( nProgressOld != nProgress ){ nProgressOld = nProgress; Progress_SetPos( hwndProgress, nProgress + 1 ); Progress_SetPos( hwndProgress, nProgress ); } } } } } if( bLastInsert || 0 < cNextLine.GetLength() ){ CNativeW cNull; CStringRef cNullStr(L"", 0); CNativeW& cmemLine = bLastInsert ? pArg->pInsData->back().cmemLine : cNull; const CStringRef& cPrevLine2 = ((0 == nCount) ? cPrevLine: cNullStr); int nSeq = pArg->pInsData->back().nSeq; int nLen = cmemLine.GetStringLength(); CNativeW tmp; tmp.AllocStringBuffer(cPrevLine2.GetLength() + cmemLine.GetStringLength() + cNextLine.GetLength()); tmp.AppendString(cPrevLine2.GetPtr(), cPrevLine2.GetLength()); tmp.AppendNativeData(cmemLine); tmp.AppendString(cNextLine.GetPtr(), cNextLine.GetLength()); if( NULL == pCDocLine ){ CDocLine* pCDocLineNew = m_pcDocLineMgr->AddNewLine(); //末尾に追加 pCDocLineNew->SetDocLineStringMove(&tmp); pCDocLineNew->m_sMark = markNext; if( !bLastEOLReplace || !bSetMark ){ CModifyVisitor().SetLineModified(pCDocLineNew, nSeq); } pArg->ptNewPos.x = nLen; /* 挿入された部分の次の位置のデータ位置 */ }else{ if( 0 == nCount ){ // 行の中間に挿入(削除データがなかった。1文字入力など) }else{ // 複数行挿入の最後の行 pCDocLine = m_pcDocLineMgr->InsertNewLine(pCDocLine); //pCDocLineの前に挿入 pCDocLine->m_sMark = markNext; } pCDocLine->SetDocLineStringMove(&tmp); if( !bLastEOLReplace || !bSetMark ){ CModifyVisitor().SetLineModified(pCDocLine, nSeq); } pArg->ptNewPos.x = cPrevLine2.GetLength() + nLen; /* 挿入された部分の次の位置のデータ位置 */ } } pArg->nInsLineNum = m_pcDocLineMgr->GetLineCount() - nAllLinesOld; return; }
/*! ファイルを読み込んで格納する(分割読み込みテスト版) @version 2.0 @note Windows用にコーディングしてある @retval TRUE 正常読み込み @retval FALSE エラー(またはユーザによるキャンセル?) @date 2002/08/30 Moca 旧ReadFileを元に作成 ファイルアクセスに関する部分をCFileLoadで行う @date 2003/07/26 ryoji BOMの状態の取得を追加 */ EConvertResult CReadManager::ReadFile_To_CDocLineMgr( CDocLineMgr* pcDocLineMgr, //!< [out] const SLoadInfo& sLoadInfo, //!< [in] SFileInfo* pFileInfo //!< [out] ) { LPCTSTR pszPath = sLoadInfo.cFilePath.c_str(); // 文字コード種別 const STypeConfigMini* type; CDocTypeManager().GetTypeConfigMini( sLoadInfo.nType, &type ); ECodeType eCharCode = sLoadInfo.eCharCode; if (CODE_AUTODETECT == eCharCode) { CCodeMediator cmediator( type->m_encoding ); eCharCode = cmediator.CheckKanjiCodeOfFile( pszPath ); } if (!IsValidCodeOrCPType( eCharCode )) { eCharCode = type->m_encoding.m_eDefaultCodetype; // 2011.01.24 ryoji デフォルト文字コード } bool bBom; if (eCharCode == type->m_encoding.m_eDefaultCodetype) { bBom = type->m_encoding.m_bDefaultBom; // 2011.01.24 ryoji デフォルトBOM } else{ bBom = CCodeTypeName( eCharCode ).IsBomDefOn(); } pFileInfo->SetCodeSet( eCharCode, bBom ); /* 既存データのクリア */ pcDocLineMgr->DeleteAllLine(); /* 処理中のユーザー操作を可能にする */ if( !::BlockingHook( NULL ) ){ return RESULT_FAILURE; //######INTERRUPT } EConvertResult eRet = RESULT_COMPLETE; try{ CFileLoad cfl(type->m_encoding); bool bBigFile; #ifdef _WIN64 bBigFile = true; #else bBigFile = false; #endif // ファイルを開く // ファイルを閉じるにはFileCloseメンバ又はデストラクタのどちらかで処理できます // Jul. 28, 2003 ryoji BOMパラメータ追加 cfl.FileOpen( pszPath, bBigFile, eCharCode, GetDllShareData().m_Common.m_sFile.GetAutoMIMEdecode(), &bBom ); pFileInfo->SetBomExist( bBom ); /* ファイル時刻の取得 */ FILETIME FileTime; if( cfl.GetFileTime( NULL, NULL, &FileTime ) ){ pFileInfo->SetFileTime( FileTime ); } // ReadLineはファイルから 文字コード変換された1行を読み出します // エラー時はthrow CError_FileRead を投げます int nLineNum = 0; CEol cEol; CNativeW cUnicodeBuffer; EConvertResult eRead; while( RESULT_FAILURE != (eRead = cfl.ReadLine( &cUnicodeBuffer, &cEol )) ){ if(eRead==RESULT_LOSESOME){ eRet = RESULT_LOSESOME; } const wchar_t* pLine = cUnicodeBuffer.GetStringPtr(); int nLineLen = cUnicodeBuffer.GetStringLength(); ++nLineNum; CDocEditAgent(pcDocLineMgr).AddLineStrX( pLine, nLineLen ); //経過通知 if(nLineNum%512==0){ NotifyProgress(cfl.GetPercent()); // 処理中のユーザー操作を可能にする if( !::BlockingHook( NULL ) ){ throw CAppExitException(); //中断検出 } } } // ファイルをクローズする cfl.FileClose(); } catch(CAppExitException){ //WM_QUITが発生した return RESULT_FAILURE; } catch( CError_FileOpen ){ eRet = RESULT_FAILURE; if( !fexist( pszPath )){ // ファイルがない ErrorMessage( CEditWnd::getInstance()->GetHwnd(), LS(STR_ERR_DLGDOCLM1), //Mar. 24, 2001 jepro 若干修正 pszPath ); } else if( -1 == _taccess( pszPath, 4 )){ // 読み込みアクセス権がない ErrorMessage( CEditWnd::getInstance()->GetHwnd(), LS(STR_ERR_DLGDOCLM2), pszPath ); } else{ ErrorMessage( CEditWnd::getInstance()->GetHwnd(), LS(STR_ERR_DLGDOCLM3), pszPath ); } } catch( CError_FileRead ){ eRet = RESULT_FAILURE; ErrorMessage( CEditWnd::getInstance()->GetHwnd(), LS(STR_ERR_DLGDOCLM4), pszPath ); /* 既存データのクリア */ pcDocLineMgr->DeleteAllLine(); } // 例外処理終わり NotifyProgress(0); /* 処理中のユーザー操作を可能にする */ if( !::BlockingHook( NULL ) ){ return RESULT_FAILURE; //####INTERRUPT } /* 行変更状態をすべてリセット */ // CModifyVisitor().ResetAllModifyFlag(pcDocLineMgr, 0); return eRet; }
//! バッファの最後にデータを追加する void CNativeW::AppendNativeData( const CNativeW& cmemData ) { CNative::AppendRawData(cmemData.GetStringPtr(), cmemData.GetRawLength()); }
void CDocLine::SetDocLineString(const CNativeW& cData) { SetDocLineString(cData.GetStringPtr(), cData.GetStringLength()); }
/*! キーボードマクロの読み込み エラーメッセージは出しません。呼び出し側でよきにはからってください。 */ BOOL CKeyMacroMgr::LoadKeyMacro( HINSTANCE hInstance, const TCHAR* pszPath ) { /* キーマクロのバッファをクリアする */ ClearAll(); CTextInputStream in( pszPath ); if(!in){ m_nReady = false; return FALSE; } WCHAR szFuncName[100]; WCHAR szFuncNameJapanese[256]; EFunctionCode nFuncID; int i; int nBgn, nEnd; CMacro* macro = NULL; // Jun. 16, 2002 genta m_nReady = true; // エラーがあればfalseになる std::tstring MACRO_ERROR_TITLE_string = LS(STR_ERR_DLGKEYMACMGR2); const TCHAR* MACRO_ERROR_TITLE = MACRO_ERROR_TITLE_string.c_str(); int line = 1; // エラー時に行番号を通知するため.1始まり. for( ; in.Good() ; ++line ){ std::wstring strLine = in.ReadLineW(); const WCHAR* szLine = strLine.c_str(); // '\0'終端文字列を取得 using namespace WCODE; int nLineLen = strLine.length(); // 先行する空白をスキップ for( i = 0; i < nLineLen; ++i ){ if( szLine[i] != SPACE && szLine[i] != TAB ){ break; } } nBgn = i; // Jun. 16, 2002 genta 空行を無視する if( nBgn == nLineLen || szLine[nBgn] == LTEXT('\0') ){ continue; } // コメント行の検出 //# パフォーマンス:'/'のときだけ2文字目をテスト if( szLine[nBgn] == LTEXT('/') && nBgn + 1 < nLineLen && szLine[nBgn + 1] == LTEXT('/') ){ continue; } // 関数名の取得 szFuncName[0]='\0';// 初期化 for( ; i < nLineLen; ++i ){ //# バッファオーバーランチェック if( szLine[i] == LTEXT('(') && (i - nBgn)< _countof(szFuncName) ){ auto_memcpy( szFuncName, &szLine[nBgn], i - nBgn ); szFuncName[i - nBgn] = L'\0'; ++i; nBgn = i; break; } } // 関数名にS_が付いていたら /* 関数名→機能ID,機能名日本語 */ //@@@ 2002.2.2 YAZAKI マクロをCSMacroMgrに統一 nFuncID = CSMacroMgr::GetFuncInfoByName( hInstance, szFuncName, szFuncNameJapanese ); if( -1 != nFuncID ){ macro = new CMacro( nFuncID ); // Jun. 16, 2002 genta プロトタイプチェック用に追加 int nArgs; const MacroFuncInfo* mInfo= CSMacroMgr::GetFuncInfoByID( nFuncID ); int nArgSizeMax = _countof( mInfo->m_varArguments ); if( mInfo->m_pData ){ nArgSizeMax = mInfo->m_pData->m_nArgMaxSize; } for(nArgs = 0; szLine[i] ; ++nArgs ) { // Jun. 16, 2002 genta プロトタイプチェック if( nArgs >= nArgSizeMax ){ ::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE, LS(STR_ERR_DLGKEYMACMGR3), line, i + 1 ); m_nReady = false; } VARTYPE type = VT_EMPTY; if( nArgs < 4 ){ type = mInfo->m_varArguments[nArgs]; }else{ if( mInfo->m_pData && nArgs < mInfo->m_pData->m_nArgMinSize ){ type = mInfo->m_pData->m_pVarArgEx[nArgs - 4]; } } // Skip Space while( szLine[i] == LTEXT(' ') || szLine[i] == LTEXT('\t') ) i++; //@@@ 2002.2.2 YAZAKI PPA.DLLマクロにあわせて仕様変更。文字列は''で囲む。 // Jun. 16, 2002 genta double quotationも許容する if( LTEXT('\'') == szLine[i] || LTEXT('\"') == szLine[i] ){ // 'で始まったら文字列だよきっと。 // Jun. 16, 2002 genta プロトタイプチェック // Jun. 27, 2002 genta 余分な引数を無視するよう,VT_EMPTYを許容する. if( type != VT_BSTR && type != VT_EMPTY ){ ::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE, LS(STR_ERR_DLGKEYMACMGR4), line, i + 1, szFuncName, nArgs + 1 ); m_nReady = false; break; } WCHAR cQuote = szLine[i]; ++i; nBgn = nEnd = i; // nBgnは引数の先頭の文字 // Jun. 16, 2002 genta // 行末の検出のため,ループ回数を1増やした for( ; i <= nLineLen; ++i ){ // 最後の文字+1までスキャン if( szLine[i] == LTEXT('\\') ){ // エスケープのスキップ ++i; continue; } if( szLine[i] == cQuote ){ // 始まりと同じquotationで終了。 nEnd = i; // nEndは終わりの次の文字(') break; } if( i == nLineLen ){ // 行末に来てしまった ::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE, LS(STR_ERR_DLGKEYMACMGR5), line, szFuncName, nArgs + 1, cQuote ); m_nReady = false; nEnd = i - 1; // nEndは終わりの次の文字(') break; } } // Jun. 16, 2002 genta if( !m_nReady ){ break; } CNativeW cmemWork; cmemWork.SetString( strLine.c_str() + nBgn, nEnd - nBgn ); // 2014.01.28 「"\\'"」のような場合の不具合を修正 cmemWork.Replace( L"\\\\", L"\\\1" ); // 一時置換(最初に必要) cmemWork.Replace( LTEXT("\\\'"), LTEXT("\'") ); // Jun. 16, 2002 genta double quotationもエスケープ解除 cmemWork.Replace( LTEXT("\\\""), LTEXT("\"") ); cmemWork.Replace( L"\\r", L"\r" ); cmemWork.Replace( L"\\n", L"\n" ); cmemWork.Replace( L"\\t", L"\t" ); { // \uXXXX 置換 size_t nLen = cmemWork.GetStringLength(); size_t nBegin = 0; const wchar_t* p = cmemWork.GetStringPtr(); CNativeW cmemTemp; for( size_t n = 0; n < nLen; n++ ){ if( n + 1 < nLen && p[n] == L'\\' && p[n+1] == L'u' ){ size_t k; for( k = n + 2; k < nLen && k < n + 2 + 4 && (WCODE::Is09(p[k]) || (L'a' <= p[k] && p[k] <= L'f') || (L'A' <= p[k] && p[k] <= L'F')); k++ ){ } cmemTemp.AppendString( p + nBegin, n - nBegin ); nBegin = k; if( 0 < k - n - 2 ){ wchar_t hex[5]; wcsncpy( hex, &p[n+2], k - n - 2 ); hex[k - n - 2] = L'\0'; wchar_t* pEnd = NULL; wchar_t c = static_cast<wchar_t>(wcstol(hex, &pEnd, 16)); cmemTemp.AppendString( &c, 1 ); } n = k - 1; } } if( nBegin != 0 ){ if( 0 < nLen - nBegin ){ cmemTemp.AppendString( p + nBegin, nLen - nBegin ); } cmemWork.swap( cmemTemp ); } } cmemWork.Replace( L"\\\1", L"\\" ); // 一時置換を\に戻す(最後でないといけない) macro->AddStringParam( cmemWork.GetStringPtr(), cmemWork.GetStringLength() ); // 引数を文字列として追加 } else if ( Is09(szLine[i]) || szLine[i] == L'-' ){ // 数字で始まったら数字列だ(-記号も含む)。 // Jun. 16, 2002 genta プロトタイプチェック // Jun. 27, 2002 genta 余分な引数を無視するよう,VT_EMPTYを許容する. if( type != VT_I4 && type != VT_EMPTY){ ::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE, LS(STR_ERR_DLGKEYMACMGR6), line, i + 1, szFuncName, nArgs + 1 ); m_nReady = false; break; } nBgn = nEnd = i; // nBgnは引数の先頭の文字 // 行末の検出のため,ループ回数を1増やした for( i = nBgn + 1; i <= nLineLen; ++i ){ // 最後の文字+1までスキャン if( Is09(szLine[i]) ){ // まだ数値 // ++i; continue; } else { nEnd = i; // 数字の最後の文字 i--; break; } } CNativeW cmemWork; cmemWork.SetString( strLine.c_str() + nBgn, nEnd - nBgn ); // Jun. 16, 2002 genta // 数字の中にquotationは入っていないよ //cmemWork.Replace( L"\\\'", L"\'" ); //cmemWork.Replace( L"\\\\", L"\\" ); macro->AddIntParam( _wtoi(cmemWork.GetStringPtr()) ); // 引数を数字として追加 } // Jun. 16, 2002 genta else if( szLine[i] == LTEXT(')') ){ // 引数無し break; } else { // Parse Error:文法エラーっぽい。 // Jun. 16, 2002 genta nBgn = nEnd = i; ::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE, LS(STR_ERR_DLGKEYMACMGR7), line, i + 1 ); m_nReady = false; break; } for( ; i < nLineLen; ++i ){ // 最後の文字までスキャン if( szLine[i] == LTEXT(')') || szLine[i] == LTEXT(',') ){ // ,もしくは)を読み飛ばす i++; break; } } if (szLine[i-1] == LTEXT(')')){ break; } } // Jun. 16, 2002 genta if( !m_nReady ){ // どこかでエラーがあったらしい delete macro; break; } /* キーマクロのバッファにデータ追加 */ Append( macro ); } else { ::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE, LS(STR_ERR_DLGKEYMACMGR8), line, szFuncName ); // Jun. 16, 2002 genta m_nReady = false; break; } } in.Close(); // Jun. 16, 2002 genta // マクロ中にエラーがあったら異常終了できるようにする. return m_nReady ? TRUE : FALSE; }
/* Uudecode (デコード)*/ bool CDecode_UuDecode::DoDecode( const CNativeW& pcSrc, CMemory* pcDst ) { const WCHAR *psrc, *pline; int nsrclen; char *pw, *pw_base; int nlinelen, ncuridx; CEol ceol; bool bsuccess = false; pcDst->Clear(); psrc = pcSrc.GetStringPtr(); nsrclen = pcSrc.GetStringLength(); if( nsrclen < 1 ){ pcDst->_AppendSz(""); return false; } pcDst->AllocBuffer( (nsrclen / 4) * 3 + 10 ); pw_base = pw = static_cast<char *>( pcDst->GetRawPtr() ); // 先頭の改行・空白文字をスキップ for( ncuridx = 0; ncuridx < nsrclen; ++ncuridx ){ WCHAR c = psrc[ncuridx]; if( !WCODE::IsLineDelimiterBasic(c) && c != L' ' && c != L'\t' ){ break; } } // ヘッダーを解析 pline = GetNextLineW( psrc, nsrclen, &nlinelen, &ncuridx, &ceol, false ); if( !CheckUUHeader(pline, nlinelen, m_aFilename) ){ pcDst->_AppendSz(""); return false; } // ボディーを処理 while( (pline = GetNextLineW(psrc, nsrclen, &nlinelen, &ncuridx, &ceol, false)) != NULL ){ if( ceol.GetType() != EOL_CRLF ){ pcDst->_AppendSz(""); return false; } if( nlinelen < 1 ){ pcDst->_AppendSz(""); return false; } if( nlinelen == 1 ){ // データの最後である場合 if( pline[0] == L' ' || pline[0] == L'`' || pline[0] == L'~' ){ bsuccess = true; break; } } pw += _DecodeUU_line( pline, nlinelen, pw ); } if( bsuccess == false ){ return false; } pline += 3; // '`' 'CR' 'LF' の分をスキップ // フッターを解析 if( !CheckUUFooter(pline, nsrclen-ncuridx) ){ pcDst->_AppendSz(""); return false; } pcDst->_SetRawLength( pw - pw_base ); return true; }
/*! @return 機能が割り当てられているキーストロークの数 @date Oct. 31, 2001 genta 動的な機能名に対応するため引数追加 @date 2007.02.22 ryoji デフォルト機能割り当てに関する処理を追加 */ int CKeyBind::CreateKeyBindList( HINSTANCE hInstance, //!< [in] インスタンスハンドル int nKeyNameArrNum, //!< [in] KEYDATA* pKeyNameArr, //!< [out] CNativeW& cMemList, //!< CFuncLookup* pcFuncLookup, //!< [in] 機能番号→名前の対応を取る BOOL bGetDefFuncCode //!< [in] ON:デフォルト機能割り当てを使う/OFF:使わない デフォルト:TRUE ) { int i; int j; int nValidKeys; WCHAR pszStr[256]; WCHAR szFuncName[256]; WCHAR szFuncNameJapanese[256]; nValidKeys = 0; cMemList.SetString(LTEXT("")); const WCHAR* pszSHIFT = LTEXT("Shift+"); const WCHAR* pszCTRL = LTEXT("Ctrl+"); const WCHAR* pszALT = LTEXT("Alt+"); const WCHAR* pszTAB = LTEXT("\t"); const WCHAR* pszCR = LTEXT("\r\n"); //\r=0x0d=CRを追加 cMemList.AppendString( LSW(STR_ERR_DLGKEYBIND1) ); cMemList.AppendString( pszCR ); cMemList.AppendString( LTEXT("-----\t-----\t-----\t-----\t-----") ); cMemList.AppendString( pszCR ); for( j = 0; j < 8; ++j ){ for( i = 0; i < nKeyNameArrNum; ++i ){ int iFunc = GetFuncCodeAt( pKeyNameArr[i], j, bGetDefFuncCode ); if( 0 != iFunc ){ nValidKeys++; if( j & _SHIFT ){ cMemList.AppendString( pszSHIFT ); } if( j & _CTRL ){ cMemList.AppendString( pszCTRL ); } if( j & _ALT ){ cMemList.AppendString( pszALT ); } cMemList.AppendString( to_wchar(pKeyNameArr[i].m_szKeyName) ); // Oct. 31, 2001 genta if( !pcFuncLookup->Funccode2Name( iFunc, szFuncNameJapanese, 255 )){ auto_strcpy( szFuncNameJapanese, LSW(STR_ERR_DLGKEYBIND2) ); } szFuncName[0] = LTEXT('\0'); /*"---unknown()--"*/ // /* 機能名日本語 */ // ::LoadString( // hInstance, // pKeyNameArr[i].m_nFuncCodeArr[j], // szFuncNameJapanese, 255 // ); cMemList.AppendString( pszTAB ); cMemList.AppendString( szFuncNameJapanese ); /* 機能ID→関数名,機能名日本語 */ //@@@ 2002.2.2 YAZAKI マクロをCSMacroMgrに統一 CSMacroMgr::GetFuncInfoByID( hInstance, iFunc, szFuncName, szFuncNameJapanese ); /* 関数名 */ cMemList.AppendString( pszTAB ); cMemList.AppendString( szFuncName ); /* 機能番号 */ cMemList.AppendString( pszTAB ); auto_sprintf( pszStr, LTEXT("%d"), iFunc ); cMemList.AppendString( pszStr ); /* キーマクロに記録可能な機能かどうかを調べる */ cMemList.AppendString( pszTAB ); //@@@ 2002.2.2 YAZAKI マクロをCSMacroMgrに統一 if( CSMacroMgr::CanFuncIsKeyMacro( iFunc ) ){ cMemList.AppendString( LTEXT("○") ); }else{ cMemList.AppendString( LTEXT("×") ); } cMemList.AppendString( pszCR ); } } } return nValidKeys; }
/*! 外部HTMLヘルプ @param helpfile [in] HTMLヘルプファイル名.NULLのときはタイプ別に設定されたファイル. @param kwd [in] 検索キーワード.NULLのときはカーソル位置or選択されたワード @date 2002.07.05 genta 任意のファイル・キーワードの指定ができるよう引数追加 */ void CViewCommander::Command_EXTHTMLHELP( const WCHAR* _helpfile, const WCHAR* kwd ) { std::tstring helpfile; if( _helpfile != NULL ){ helpfile = to_tchar(_helpfile); } HWND hwndHtmlHelp; int nLen; DEBUG_TRACE( _T("helpfile=%ts\n"), helpfile.c_str() ); // From Here Jul. 5, 2002 genta const TCHAR *filename = NULL; if ( 0 == helpfile.length() ){ while( !CHelpManager().ExtHTMLHelpIsSet( &(GetDocument()->m_cDocType.GetDocumentAttribute())) ){ ErrorBeep(); // From Here Sept. 15, 2000 JEPRO // [Esc]キーと[x]ボタンでも中止できるように変更 if( IDYES != ::MYMESSAGEBOX( NULL, MB_YESNOCANCEL | MB_ICONEXCLAMATION | MB_APPLMODAL | MB_TOPMOST, GSTR_APPNAME, // To Here Sept. 15, 2000 LS(STR_ERR_CEDITVIEW_CMD02) ) ){ return; } /* 共通設定 プロパティシート */ if( !CEditApp::getInstance()->OpenPropertySheet( ID_PROPCOM_PAGENUM_HELPER ) ){ return; } } filename = CHelpManager().GetExtHTMLHelp( &(GetDocument()->m_cDocType.GetDocumentAttribute()) ); } else { filename = helpfile.c_str(); } // To Here Jul. 5, 2002 genta // Jul. 5, 2002 genta // キーワードの外部指定を可能に CNativeW cmemCurText; if( kwd != NULL && kwd[0] != _T('\0') ){ cmemCurText.SetString( kwd ); } else { /* 現在カーソル位置単語または選択範囲より検索等のキーを取得 */ m_pCommanderView->GetCurrentTextForSearch( cmemCurText ); } /* HtmlHelpビューアはひとつ */ if( CHelpManager().HTMLHelpIsSingle( &(GetDocument()->m_cDocType.GetDocumentAttribute())) ){ // タスクトレイのプロセスにHtmlHelpを起動させる // 2003.06.23 Moca 相対パスは実行ファイルからのパス // 2007.05.21 ryoji 相対パスは設定ファイルからのパスを優先 TCHAR* pWork=GetDllShareData().m_sWorkBuffer.GetWorkBuffer<TCHAR>(); if( _IS_REL_PATH( filename ) ){ GetInidirOrExedir( pWork, filename ); }else{ _tcscpy( pWork, filename ); // Jul. 5, 2002 genta } nLen = _tcslen( pWork ); _tcscpy( &pWork[nLen + 1], cmemCurText.GetStringT() ); hwndHtmlHelp = (HWND)::SendMessageAny( GetDllShareData().m_sHandles.m_hwndTray, MYWM_HTMLHELP, (WPARAM)GetMainWindow(), 0 ); } else{ /* 自分でHtmlHelpを起動させる */ HH_AKLINK link; link.cbStruct = sizeof( link ) ; link.fReserved = FALSE ; link.pszKeywords = cmemCurText.GetStringT(); link.pszUrl = NULL; link.pszMsgText = NULL; link.pszMsgTitle = NULL; link.pszWindow = NULL; link.fIndexOnFail = TRUE; // 2003.06.23 Moca 相対パスは実行ファイルからのパス // 2007.05.21 ryoji 相対パスは設定ファイルからのパスを優先 if( _IS_REL_PATH( filename ) ){ TCHAR path[_MAX_PATH]; GetInidirOrExedir( path, filename ); // Jul. 6, 2001 genta HtmlHelpの呼び出し方法変更 hwndHtmlHelp = OpenHtmlHelp( NULL/*GetDllShareData().m_sHandles.m_hwndTray*/, path, // Jul. 5, 2002 genta HH_KEYWORD_LOOKUP, (DWORD_PTR)&link ); }else{ // Jul. 6, 2001 genta HtmlHelpの呼び出し方法変更 hwndHtmlHelp = OpenHtmlHelp( NULL/*GetDllShareData().m_sHandles.m_hwndTray*/, filename, // Jul. 5, 2002 genta HH_KEYWORD_LOOKUP, (DWORD_PTR)&link ); } } // Jul. 6, 2001 genta hwndHtmlHelpのチェックを追加 if( hwndHtmlHelp != NULL ){ ::BringWindowToTop( hwndHtmlHelp ); } return; }
wstring CTextInputStream::ReadLineW() { //$$ 非効率だけど今のところは許して。。 CNativeW line; line.AllocStringBuffer(60); for (;;) { int c=getc(GetFp()); if(c==EOF)break; //EOFで終了 if(c=='\r'){ c=getc(GetFp()); if(c!='\n')ungetc(c,GetFp()); break; } //"\r" または "\r\n" で終了 if(c=='\n')break; //"\n" で終了 if( line._GetMemory()->capacity() < line._GetMemory()->GetRawLength() + 10 ){ line._GetMemory()->AllocBuffer( line._GetMemory()->GetRawLength() * 2 ); } line._GetMemory()->AppendRawData(&c,sizeof(char)); } //UTF-8 → UNICODE if(m_bIsUtf8){ CUtf8::UTF8ToUnicode(*(line._GetMemory()), &line); } //Shift_JIS → UNICODE else{ CShiftJis::SJISToUnicode(*(line._GetMemory()), &line); } return wstring().assign( line.GetStringPtr(), line.GetStringLength() ); // EOL まで NULL 文字も含める }