int CColor_Quote::Match_QuoteStr( const wchar_t* pszQuote, int nQuoteLen, int nPos, const CStringRef& cLineStr, bool bEscape ) { int nCharChars; int i; const int nCompLen = cLineStr.GetLength() - nQuoteLen + 1; const WCHAR quote1 = pszQuote[0]; const WCHAR* pLine = cLineStr.GetPtr(); for( i = nPos; i < nCompLen; i += nCharChars ){ if( quote1 == pLine[i] && wmemcmp( pszQuote + 1, pLine + i + 1, nQuoteLen - 1 ) == 0 ){ return i + nQuoteLen; } nCharChars = (Int)t_max(CLogicInt(1), CNativeW::GetSizeOfChar( pLine, cLineStr.GetLength(), i )); if( bEscape && pLine[i] == L'\\' ){ i += (Int)t_max(CLogicInt(1), CNativeW::GetSizeOfChar( pLine, cLineStr.GetLength(), i + nCharChars )); } } return cLineStr.GetLength(); }
int CColor_Quote::Match_Quote( wchar_t wcQuote, int nPos, const CStringRef& cLineStr, int escapeType, bool* pbEscapeEnd ) { int nCharChars; int i; for( i = nPos; i < cLineStr.GetLength(); ++i ){ // 2005-09-02 D.S.Koba GetSizeOfChar nCharChars = (Int)t_max(CLogicInt(1), CNativeW::GetSizeOfChar( cLineStr.GetPtr(), cLineStr.GetLength(), i )); if( escapeType == STRING_LITERAL_CPP ){ // エスケープ \" if( 1 == nCharChars && cLineStr.At(i) == L'\\' ){ ++i; if( i < cLineStr.GetLength() && WCODE::IsLineDelimiter(cLineStr.At(i), GetDllShareData().m_Common.m_sEdit.m_bEnableExtEol) ){ if( pbEscapeEnd ){ *pbEscapeEnd = true; } } }else if( 1 == nCharChars && cLineStr.At(i) == wcQuote ){ return i + 1; } }else if( escapeType == STRING_LITERAL_PLSQL ){ // エスケープ "" if( 1 == nCharChars && cLineStr.At(i) == wcQuote ){ if( i + 1 < cLineStr.GetLength() && cLineStr.At(i + 1) == wcQuote ){ ++i; }else{ return i + 1; } } }else{ // エスケープなし if( 1 == nCharChars && cLineStr.At(i) == wcQuote ){ return i + 1; } } if( 2 == nCharChars ){ ++i; } } return cLineStr.GetLength() + 1; // 終端なしはLength + 1 }
//改行記号を描画した場合はtrueを返す? bool CEditView::DrawLayoutLine(SColorStrategyInfo* pInfo) { bool bDispEOF = false; CTypeSupport cTextType(this,COLORIDX_TEXT); const CLayout* pcLayout = pInfo->m_pDispPos->GetLayoutRef(); //m_pcEditDoc->m_cLayoutMgr.SearchLineByLayoutY( pInfo->pDispPos->GetLayoutLineRef() ); // レイアウト情報 if( pcLayout ){ pInfo->m_pLineOfLogic = pcLayout->GetDocLineRef()->GetPtr(); } else{ pInfo->m_pLineOfLogic = NULL; } //文字列参照 const CDocLine* pcDocLine = pInfo->GetDocLine(); CStringRef cLineStr = pcDocLine->GetStringRefWithEOL(); // 描画範囲外の場合は色切替だけで抜ける if(pInfo->m_pDispPos->GetDrawPos().y < GetTextArea().GetAreaTop()){ if(pcLayout){ bool bChange = false; int nPosTo = pcLayout->GetLogicOffset() + pcLayout->GetLengthWithEOL(); CColor3Setting cColor; while(pInfo->m_nPosInLogic < nPosTo){ //色切替 bChange |= pInfo->CheckChangeColor(cLineStr); //1文字進む pInfo->m_nPosInLogic += CNativeW::GetSizeOfChar( cLineStr.GetPtr(), cLineStr.GetLength(), pInfo->m_nPosInLogic ); } if( bChange ){ pInfo->DoChangeColor(&cColor); SetCurrentColor(pInfo->m_gr, cColor.eColorIndex, cColor.eColorIndex2, cColor.eColorIndexBg); } } return false; } // コンフィグ int nLineHeight = GetTextMetrics().GetHankakuDy(); //行の縦幅? CTypeSupport cCaretLineBg(this, COLORIDX_CARETLINEBG); CTypeSupport cEvenLineBg(this, COLORIDX_EVENLINEBG); CTypeSupport cPageViewBg(this, COLORIDX_PAGEVIEW); CEditView& cActiveView = m_pcEditWnd->GetActiveView(); CTypeSupport& cBackType = (cCaretLineBg.IsDisp() && GetCaret().GetCaretLayoutPos().GetY() == pInfo->m_pDispPos->GetLayoutLineRef() && !m_bMiniMap ? cCaretLineBg : cEvenLineBg.IsDisp() && pInfo->m_pDispPos->GetLayoutLineRef() % 2 == 1 && !m_bMiniMap ? cEvenLineBg : (cPageViewBg.IsDisp() && m_bMiniMap && cActiveView.GetTextArea().GetViewTopLine() <= pInfo->m_pDispPos->GetLayoutLineRef() && pInfo->m_pDispPos->GetLayoutLineRef() < cActiveView.GetTextArea().GetBottomLine()) ? cPageViewBg : cTextType); bool bTransText = IsBkBitmap(); if( bTransText ){ bTransText = cBackType.GetBackColor() == cTextType.GetBackColor(); } // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // // 行番号描画 // // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // GetTextDrawer().DispLineNumber( pInfo->m_gr, pInfo->m_pDispPos->GetLayoutLineRef(), pInfo->m_pDispPos->GetDrawPos().y ); // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // // 本文描画開始 // // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // pInfo->m_pDispPos->ResetDrawCol(); // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // // 行頭(インデント)背景描画 // // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // if(pcLayout && pcLayout->GetIndent()!=0) { RECT rcClip; if(!bTransText && GetTextArea().GenerateClipRect(&rcClip, *pInfo->m_pDispPos, pcLayout->GetIndent())){ cBackType.FillBack(pInfo->m_gr,rcClip); } //描画位置進める pInfo->m_pDispPos->ForwardDrawCol(pcLayout->GetIndent()); } // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // // 本文描画 // // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // bool bSkipRight = false; // 続きを描画しなくていい場合はスキップする if(pcLayout){ const CLayout* pcLayoutNext = pcLayout->GetNextLayout(); if( NULL == pcLayoutNext ){ bSkipRight = true; }else if( pcLayoutNext->GetLogicOffset() == 0 ){ bSkipRight = true; // 次の行は別のロジック行なのでスキップ可能 } if( !bSkipRight ){ bSkipRight = CColorStrategyPool::getInstance()->IsSkipBeforeLayout(); } } //行終端または折り返しに達するまでループ if(pcLayout){ int nPosTo = pcLayout->GetLogicOffset() + pcLayout->GetLengthWithEOL(); CFigureManager* pcFigureManager = CFigureManager::getInstance(); while(pInfo->m_nPosInLogic < nPosTo){ //色切替 if( pInfo->CheckChangeColor(cLineStr) ){ CColor3Setting cColor; pInfo->DoChangeColor(&cColor); SetCurrentColor(pInfo->m_gr, cColor.eColorIndex, cColor.eColorIndex2, cColor.eColorIndexBg); } //1文字情報取得 $$高速化可能 CFigure& cFigure = pcFigureManager->GetFigure(&cLineStr.GetPtr()[pInfo->GetPosInLogic()], cLineStr.GetLength() - pInfo->GetPosInLogic()); //1文字描画 cFigure.DrawImp(pInfo); if( bSkipRight && GetTextArea().GetAreaRight() < pInfo->m_pDispPos->GetDrawPos().x ){ pInfo->m_nPosInLogic = nPosTo; break; } } } // 必要ならEOF描画 void _DispEOF( CGraphics& gr, DispPos* pDispPos, const CEditView* pcView); if(pcLayout && pcLayout->GetNextLayout()==NULL && pcLayout->GetLayoutEol().GetLen()==0){ // 有文字行のEOF _DispEOF(pInfo->m_gr,pInfo->m_pDispPos,this); bDispEOF = true; } else if(!pcLayout && pInfo->m_pDispPos->GetLayoutLineRef()==m_pcEditDoc->m_cLayoutMgr.GetLineCount()){ // 空行のEOF const CLayout* pBottom = m_pcEditDoc->m_cLayoutMgr.GetBottomLayout(); if(pBottom==NULL || (pBottom && pBottom->GetLayoutEol().GetLen())){ _DispEOF(pInfo->m_gr,pInfo->m_pDispPos,this); bDispEOF = true; } } // 必要なら折り返し記号描画 if(pcLayout && pcLayout->GetLayoutEol().GetLen()==0 && pcLayout->GetNextLayout()!=NULL){ _DispWrap(pInfo->m_gr,pInfo->m_pDispPos,this,pInfo->m_pDispPos->GetLayoutLineRef()); } // 行末背景描画 RECT rcClip; bool rcClipRet = GetTextArea().GenerateClipRectRight(&rcClip,*pInfo->m_pDispPos); if(rcClipRet){ if( !bTransText ){ cBackType.FillBack(pInfo->m_gr,rcClip); } CTypeSupport cSelectType(this, COLORIDX_SELECT); if( GetSelectionInfo().IsTextSelected() && cSelectType.IsDisp() ){ // 選択範囲の指定色:必要ならテキストのない部分の矩形選択を作画 CLayoutRange selectArea = GetSelectionInfo().GetSelectAreaLine(pInfo->m_pDispPos->GetLayoutLineRef(), pcLayout); // 2010.10.04 スクロール分の足し忘れ CPixelXInt nSelectFromPx = GetTextMetrics().GetCharPxWidth(selectArea.GetFrom().x - GetTextArea().GetViewLeftCol()); CPixelXInt nSelectToPx = GetTextMetrics().GetCharPxWidth(selectArea.GetTo().x - GetTextArea().GetViewLeftCol()); if( nSelectFromPx < nSelectToPx && selectArea.GetTo().x != INT_MAX ){ RECT rcSelect; // Pixel rcSelect.top = pInfo->m_pDispPos->GetDrawPos().y; rcSelect.bottom = pInfo->m_pDispPos->GetDrawPos().y + GetTextMetrics().GetHankakuDy(); rcSelect.left = GetTextArea().GetAreaLeft() + nSelectFromPx; rcSelect.right = GetTextArea().GetAreaLeft() + nSelectToPx; RECT rcDraw; if( ::IntersectRect(&rcDraw, &rcClip, &rcSelect) ){ COLORREF color = GetBackColorByColorInfo2(cSelectType.GetColorInfo(), cBackType.GetColorInfo()); if( color != cBackType.GetBackColor() ){ pInfo->m_gr.FillSolidMyRect(rcDraw, color); } } } } } // ノート線描画 if( !m_bMiniMap ){ GetTextDrawer().DispNoteLine( pInfo->m_gr, pInfo->m_pDispPos->GetDrawPos().y, pInfo->m_pDispPos->GetDrawPos().y + nLineHeight, GetTextArea().GetAreaLeft(), GetTextArea().GetAreaRight() ); } // 指定桁縦線描画 GetTextDrawer().DispVerticalLines( pInfo->m_gr, pInfo->m_pDispPos->GetDrawPos().y, pInfo->m_pDispPos->GetDrawPos().y + nLineHeight, CLayoutInt(0), CLayoutInt(-1) ); // 折り返し桁縦線描画 if( !m_bMiniMap ){ GetTextDrawer().DispWrapLine( pInfo->m_gr, pInfo->m_pDispPos->GetDrawPos().y, pInfo->m_pDispPos->GetDrawPos().y + nLineHeight ); } // 反転描画 if( pcLayout && GetSelectionInfo().IsTextSelected() ){ DispTextSelected( pInfo->m_gr, pInfo->m_pDispPos->GetLayoutLineRef(), CMyPoint(pInfo->m_sDispPosBegin.GetDrawPos().x, pInfo->m_pDispPos->GetDrawPos().y), pcLayout->CalcLayoutWidth(m_pcEditDoc->m_cLayoutMgr) + CLayoutInt(pcLayout->GetLayoutEol().GetLen() ? (CTypeSupport(this, COLORIDX_EOL).IsDisp() ? (GetTextMetrics().GetLayoutXDefault()+CLayoutXInt(4)) // HACK:EOLの描画幅分だけ確保する。4pxはCRLFのはみ出している分 : CLayoutXInt(2)) // 非表示 = 2px : CLayoutInt(0)) ); } return bDispEOF; }
bool CColor_Quote::BeginColor(const CStringRef& cStr, int nPos) { if(!cStr.IsValid())return false; if( cStr.At(nPos) == m_cQuote ){ m_nCOMMENTEND = -1; int nStringType = m_pTypeData->m_nStringType; bool bPreString = true; /* クォーテーション文字列の終端があるか */ switch( nStringType ){ case STRING_LITERAL_CPP: if( IsCppRawString(cStr, nPos) ){ for( int i = nPos + 1; i < cStr.GetLength(); i++ ){ if( cStr.At(i) == '(' ){ if( nPos + 1 < i ){ m_tag = L')'; m_tag.append( cStr.GetPtr()+nPos+1, i - (nPos + 1) ); m_tag += L'"'; }else{ m_tag.assign(L")\"", 2); } m_nCOMMENTEND = Match_QuoteStr( m_tag.c_str(), m_tag.size(), i + 1, cStr, false ); m_nColorTypeIndex = 1; return true; } } } break; case STRING_LITERAL_HTML: { int i; for(i = nPos - 1; 0 <= i; i--){ if( cStr.At(i) != L' ' && cStr.At(i) != L'\t' ){ break; } } if( !(0 <= i && cStr.At(i) == L'=') ){ bPreString = false; } } break; case STRING_LITERAL_CSHARP: if( 0 < nPos && cStr.At(nPos - 1) == L'@' && m_cQuote == L'"' ){ m_nCOMMENTEND = Match_Quote( m_cQuote, nPos + 1, cStr, STRING_LITERAL_PLSQL ); m_nColorTypeIndex = 2; return true; } break; case STRING_LITERAL_PYTHON: if( nPos + 2 < cStr.GetLength() && cStr.At(nPos+1) == m_cQuote && cStr.At(nPos+2) == m_cQuote ){ m_nCOMMENTEND = Match_QuoteStr( m_szQuote, 3, nPos + 3, cStr, true ); m_nColorTypeIndex = 3; return true; } break; } m_bEscapeEnd = false; if( bPreString ){ m_nCOMMENTEND = Match_Quote( m_cQuote, nPos + 1, cStr, m_nEscapeType, m_pbEscapeEnd ); m_nColorTypeIndex = 0; } // 「文字列は行内のみ」(C++ Raw String、Pythonのlong string、@""は特別) if( m_pTypeData->m_bStringLineOnly && !m_bEscapeEnd && m_nCOMMENTEND == cStr.GetLength() + 1 ){ // 終了文字列がない場合は行末までを色分け if( m_pTypeData->m_bStringEndLine ){ // 改行コードを除く if( 0 < cStr.GetLength() && WCODE::IsLineDelimiter(cStr.At(cStr.GetLength()-1), GetDllShareData().m_Common.m_sEdit.m_bEnableExtEol) ){ if( 1 < cStr.GetLength() && cStr.At(cStr.GetLength()-2) == WCODE::CR && cStr.At(cStr.GetLength()-1) == WCODE::LF ){ m_nCOMMENTEND = cStr.GetLength() - 2; }else{ m_nCOMMENTEND = cStr.GetLength() - 1; } } return true; } // 終了文字列がない場合は色分けしない m_nCOMMENTEND = -1; return false; } if( 0 < m_nCOMMENTEND ){ return true; } } return false; }
/* 指定範囲のデータを置換(削除 & データを挿入) 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; }