// from CViewCommander_New.cpp //! ブックマークの設定・解除を行う(トグル動作) void CViewCommander::Command_BOOKMARK_SET(void) { CDocLine* pCDocLine; if( m_pCommanderView->GetSelectionInfo().IsTextSelected() && m_pCommanderView->GetSelectionInfo().m_sSelect.GetFrom().y<m_pCommanderView->GetSelectionInfo().m_sSelect.GetTo().y ){ CLogicPoint ptFrom; CLogicPoint ptTo; GetDocument()->m_cLayoutMgr.LayoutToLogic( CLayoutPoint(CLayoutInt(0), m_pCommanderView->GetSelectionInfo().m_sSelect.GetFrom().y), &ptFrom ); GetDocument()->m_cLayoutMgr.LayoutToLogic( CLayoutPoint(CLayoutInt(0), m_pCommanderView->GetSelectionInfo().m_sSelect.GetTo().y ), &ptTo ); for(CLogicInt nY=ptFrom.GetY2();nY<=ptTo.y;nY++){ pCDocLine=GetDocument()->m_cDocLineMgr.GetLine( nY ); CBookmarkSetter cBookmark(pCDocLine); if(pCDocLine)cBookmark.SetBookmark(!cBookmark.IsBookmarked()); } } else{ pCDocLine=GetDocument()->m_cDocLineMgr.GetLine( GetCaret().GetCaretLogicPos().GetY2() ); CBookmarkSetter cBookmark(pCDocLine); if(pCDocLine)cBookmark.SetBookmark(!cBookmark.IsBookmarked()); } // 2002.01.16 hor 分割したビューも更新 GetEditWindow()->Views_Redraw(); }
/*! @brief 半角対括弧の検索:逆方向 @author genta @param ptLayout [in] 検索開始点の物理座標 @param pptLayoutNew [out] 移動先のレイアウト座標 @param upChar [in] 括弧の始まりの文字 @param dnChar [in] 括弧を閉じる文字列 @param mode [in] bit0(in) : 表示領域外を調べるか? 0:調べない 1:調べる (このbitを参照) bit1(in) : 前方文字を調べるか? 0:調べない 1:調べる bit2(out) : 見つかった位置 0:後ろ 1:前 @retval true 成功 @retval false 失敗 */ bool CEditView::SearchBracketBackward( CLogicPoint ptPos, CLayoutPoint* pptLayoutNew, const wchar_t* dnChar, const wchar_t* upChar, int* mode ) { const CDocLine* ci; int len; const wchar_t* cPos; const wchar_t* pPos; const wchar_t* cline; int level = 1; CLayoutPoint ptColLine; CLayoutInt nSearchNum; // 02/09/19 ai // 初期位置の設定 m_pcEditDoc->m_cLayoutMgr.LogicToLayout( ptPos, &ptColLine ); // 02/09/19 ai nSearchNum = ptColLine.y - GetTextArea().GetViewTopLine(); // 02/09/19 ai ci = m_pcEditDoc->m_cDocLineMgr.GetLine( ptPos.GetY2() ); cline = ci->GetDocLineStrWithEOL( &len ); cPos = cline + ptPos.x; do { while( cPos > cline ){ pPos = CNativeW::GetCharPrev( cline, len, cPos ); if( cPos - pPos > 1 ){ // skip cPos = pPos; continue; } // 03/01/08 ai Start if( wcsncmp(upChar, pPos, 1) == 0 ){ ++level; } else if( wcsncmp(dnChar, pPos, 1) == 0 ){ --level; }// 03/01/08 ai End if( level == 0 ){ // 見つかった! ptPos.x = pPos - cline; m_pcEditDoc->m_cLayoutMgr.LogicToLayout( ptPos, pptLayoutNew ); return true; // Happy Ending } cPos = pPos; // 次の文字へ } // 02/09/19 ai Start nSearchNum--; if( ( 0 > nSearchNum ) && ( 0 == (*mode & 1 ) ) ) { // 表示領域外を調べないモードで表示領域の先頭の場合 //SendStatusMessage( "対括弧の検索を中断しました" ); break; } // 02/09/19 ai End // 次の行へ ptPos.y--; ci = ci->GetPrevLine(); // 次のアイテム if( ci == NULL ) break; // 終わりに達した cline = ci->GetDocLineStrWithEOL( &len ); cPos = cline + len; }while( cline != NULL ); return false; }
/*! @brief 対括弧の検索 カーソル位置の括弧に対応する括弧を探す。カーソル位置が括弧でない場合は カーソルの後ろの文字が括弧かどうかを調べる。 カーソルの前後いずれもが括弧でない場合は何もしない。 括弧が半角か全角か、及び始まりか終わりかによってこれに続く4つの関数に 制御を移す。 @param ptLayout [in] 検索開始点の物理座標 @param pptLayoutNew [out] 移動先のレイアウト座標 @param mode [in,out] bit0(in) : 表示領域外を調べるか? 0:調べない 1:調べる bit1(in) : 前方文字を調べるか? 0:調べない 1:調べる (このbitを参照) bit2(out) : 見つかった位置 0:後ろ 1:前 (このbitを更新) @retval true 成功 @retval false 失敗 @author genta @date Jun. 16, 2000 genta @date Feb. 03, 2001 MIK 全角括弧に対応 @date Sep. 18, 2002 ai modeの追加 */ bool CEditView::SearchBracket( const CLayoutPoint& ptLayout, CLayoutPoint* pptLayoutNew, int* mode ) { CLogicInt len; // 行の長さ CLogicPoint ptPos; m_pcEditDoc->m_cLayoutMgr.LayoutToLogic( ptLayout, &ptPos ); const wchar_t *cline = m_pcEditDoc->m_cDocLineMgr.GetLine(ptPos.GetY2())->GetDocLineStrWithEOL(&len); // Jun. 19, 2000 genta if( cline == NULL ) // 最後の行に本文がない場合 return false; // 括弧処理 2007.10.16 kobake { const KAKKO_T* p; for( p = g_aKakkos; p->sStr != NULL; p++ ) { if( wcsncmp(p->sStr, &cline[ptPos.x], 1) == 0 ) { return SearchBracketForward( ptPos, pptLayoutNew, p->sStr, p->eStr, mode ); } else if( wcsncmp(p->eStr, &cline[ptPos.x], 1) == 0 ) { return SearchBracketBackward( ptPos, pptLayoutNew, p->sStr, p->eStr, mode ); } } } // 02/09/18 ai Start if( 0 == ( *mode & 2 ) ){ /* カーソルの前方を調べない場合 */ return false; } *mode |= 4; // 02/09/18 ai End // 括弧が見つからなかったら,カーソルの直前の文字を調べる if( ptPos.x <= 0 ){ return false; // 前の文字はない } const wchar_t *bPos = CNativeW::GetCharPrev( cline, ptPos.x, cline + ptPos.x ); int nCharSize = cline + ptPos.x - bPos; // 括弧処理 2007.10.16 kobake if(nCharSize==1){ const KAKKO_T* p; ptPos.x = bPos - cline; for( p = g_aKakkos; p->sStr != NULL; p++ ) { if( wcsncmp(p->sStr, &cline[ptPos.x], 1) == 0 ) { return SearchBracketForward( ptPos, pptLayoutNew, p->sStr, p->eStr, mode ); } else if( wcsncmp(p->eStr, &cline[ptPos.x], 1) == 0 ) { return SearchBracketBackward( ptPos, pptLayoutNew, p->sStr, p->eStr, mode ); } } } return false; }
/* 文字列置換 */ void CLayoutMgr::ReplaceData_CLayoutMgr( LayoutReplaceArg* pArg ) { CLayoutInt nWork_nLines = m_nLines; //変更前の全行数の保存 @@@ 2002.04.19 MIK /* 置換先頭位置のレイアウト情報 */ EColorIndexType nCurrentLineType = COLORIDX_DEFAULT; CLayoutColorInfo* colorInfo = NULL; CLayoutInt nLineWork = pArg->sDelRange.GetFrom().GetY2(); CLayout* pLayoutWork = SearchLineByLayoutY( pArg->sDelRange.GetFrom().GetY2() ); if( pLayoutWork ){ while( 0 != pLayoutWork->GetLogicOffset() ){ pLayoutWork = pLayoutWork->GetPrevLayout(); nLineWork--; } nCurrentLineType = pLayoutWork->GetColorTypePrev(); colorInfo = pLayoutWork->GetLayoutExInfo()->DetachColorInfo(); }else if( GetLineCount() == pArg->sDelRange.GetFrom().GetY2() ){ // 2012.01.05 最終行のRedo/Undoでの色分けが正しくないのを修正 nCurrentLineType = m_nLineTypeBot; colorInfo = m_cLayoutExInfoBot.DetachColorInfo(); } /* || カーソル位置変換 || レイアウト位置(行頭からの表示桁位置、折り返しあり行位置) → || 物理位置(行頭からのバイト数、折り返し無し行位置) */ CLogicPoint ptFrom; CLogicPoint ptTo; LayoutToLogic( pArg->sDelRange.GetFrom(), &ptFrom ); LayoutToLogic( pArg->sDelRange.GetTo(), &ptTo ); /* 指定範囲のデータを置換(削除 & データを挿入) Fromを含む位置からToの直前を含むデータを削除する Fromの位置へテキストを挿入する */ DocLineReplaceArg DLRArg; DLRArg.sDelRange.SetFrom(ptFrom); //削除範囲from DLRArg.sDelRange.SetTo(ptTo); //削除範囲to DLRArg.pcmemDeleted = pArg->pcmemDeleted; // 削除されたデータを保存 DLRArg.pInsData = pArg->pInsData; // 挿入するデータ DLRArg.nDelSeq = pArg->nDelSeq; CSearchAgent(m_pcDocLineMgr).ReplaceData( &DLRArg ); pArg->nInsSeq = DLRArg.nInsSeq; /*--- 変更された行のレイアウト情報を再生成 ---*/ /* 論理行の指定範囲に該当するレイアウト情報を削除して */ /* 削除した範囲の直前のレイアウト情報のポインタを返す */ CLayoutInt nModifyLayoutLinesOld = CLayoutInt(0); CLayout* pLayoutPrev; CLogicInt nWork; nWork = t_max( DLRArg.nDeletedLineNum, DLRArg.nInsLineNum ); if( pLayoutWork ){ pLayoutPrev = DeleteLayoutAsLogical( pLayoutWork, nLineWork, ptFrom.GetY2(), ptFrom.GetY2() + nWork, ptFrom, &nModifyLayoutLinesOld ); /* 指定行より後の行のレイアウト情報について、論理行番号を指定行数だけシフトする */ /* 論理行が削除された場合は0より小さい行数 */ /* 論理行が挿入された場合は0より大きい行数 */ if( 0 != DLRArg.nInsLineNum - DLRArg.nDeletedLineNum ){ ShiftLogicalLineNum( pLayoutPrev, DLRArg.nInsLineNum - DLRArg.nDeletedLineNum ); } }else{ pLayoutPrev = m_pLayoutBot; } /* 指定レイアウト行に対応する論理行の次の論理行から指定論理行数だけ再レイアウトする */ CLogicInt nRowNum; if( NULL == pLayoutPrev ){ if( NULL == m_pLayoutTop ){ nRowNum = m_pcDocLineMgr->GetLineCount(); }else{ nRowNum = m_pLayoutTop->GetLogicLineNo(); } } else{ if( NULL == pLayoutPrev->GetNextLayout() ){ nRowNum = m_pcDocLineMgr->GetLineCount() - pLayoutPrev->GetLogicLineNo() - CLogicInt(1); }else{ nRowNum = pLayoutPrev->m_pNext->GetLogicLineNo() - pLayoutPrev->GetLogicLineNo() - CLogicInt(1); } } // 2009.08.28 nasukoji テキスト最大幅算出用の引数を設定 CalTextWidthArg ctwArg; ctwArg.ptLayout = pArg->sDelRange.GetFrom(); // 編集開始位置 ctwArg.nDelLines = pArg->sDelRange.GetTo().GetY2() - pArg->sDelRange.GetFrom().GetY2(); // 削除行数 - 1 ctwArg.nAllLinesOld = nWork_nLines; // 編集前のテキスト行数 ctwArg.bInsData = (pArg->pInsData && pArg->pInsData->size()) ? TRUE : FALSE; // 追加文字列の有無 /* 指定レイアウト行に対応する論理行の次の論理行から指定論理行数だけ再レイアウトする */ CLayoutInt nAddInsLineNum; pArg->nModLineTo = DoLayout_Range( pLayoutPrev, nRowNum, ptFrom, nCurrentLineType, colorInfo, &ctwArg, &nAddInsLineNum ); pArg->nAddLineNum = m_nLines - nWork_nLines; //変更後の全行数との差分 @@@ 2002.04.19 MIK if( 0 == pArg->nAddLineNum ) pArg->nAddLineNum = nModifyLayoutLinesOld - pArg->nModLineTo; /* 再描画ヒント レイアウト行の増減 */ pArg->nModLineFrom = pArg->sDelRange.GetFrom().GetY2(); /* 再描画ヒント 変更されたレイアウト行From */ pArg->nModLineTo += ( pArg->nModLineFrom - CLayoutInt(1) ) ; /* 再描画ヒント 変更されたレイアウト行To */ //2007.10.18 kobake LayoutReplaceArg::ptLayoutNewはここで算出するのが正しい LogicToLayout(DLRArg.ptNewPos, &pArg->ptLayoutNew); // 挿入された部分の次の位置 }
/* 見つからない場合は0を返す */ int CSearchAgent::SearchWord( CLogicPoint ptSerachBegin, //!< 検索開始位置 ESearchDirection eDirection, //!< 検索方向 CLogicRange* pMatchRange, //!< [out] マッチ範囲。ロジック単位。 const CSearchStringPattern& pattern //!< 検索パターン ) { CDocLine* pDocLine; CLogicInt nLinePos; CLogicInt nIdxPos; CLogicInt nIdxPosOld; const wchar_t* pLine; int nLineLen; const wchar_t* pszRes; CLogicInt nHitTo; CLogicInt nHitPos; CLogicInt nHitPosOld; int nRetVal = 0; const SSearchOption& sSearchOption = pattern.GetSearchOption(); CBregexp* pRegexp = pattern.GetRegexp(); #ifdef MEASURE_SEARCH_TIME long clockStart, clockEnd; clockStart = clock(); #endif //正規表現 if( sSearchOption.bRegularExp ){ nLinePos = ptSerachBegin.GetY2(); // 検索行=検索開始行 pDocLine = m_pcDocLineMgr->GetLine( nLinePos ); // 後方検索 if( eDirection == SEARCH_BACKWARD ){ // // 後方(↑)検索(正規表現) // nHitTo = ptSerachBegin.x; // 検索開始位置 nIdxPos = 0; while( NULL != pDocLine ){ pLine = pDocLine->GetDocLineStrWithEOL( &nLineLen ); nHitPos = -1; // -1:この行でマッチ位置なし for (;;) { nHitPosOld = nHitPos; nIdxPosOld = nIdxPos; // 長さ0でマッチしたので、この位置で再度マッチしないように、1文字進める if (nIdxPos == nHitPos) { // 2005-09-02 D.S.Koba GetSizeOfChar nIdxPos += (CNativeW::GetSizeOfChar( pLine, nLineLen, nIdxPos ) == 2 ? 2 : 1); } if ( nIdxPos <= pDocLine->GetLengthWithoutEOL() && pRegexp->Match( pLine, nLineLen, nIdxPos ) ){ // 検索にマッチした! nHitPos = pRegexp->GetIndex(); nIdxPos = pRegexp->GetLastIndex(); if( nHitPos >= nHitTo ){ // マッチしたのは、カーソル位置以降だった // すでにマッチした位置があれば、それを返し、なければ前の行へ break; } } else { // マッチしなかった // すでにマッチした位置があれば、それを返し、なければ前の行へ break; } } if ( -1 != nHitPosOld ) { // この行でマッチした位置が存在するので、この行で検索終了 pMatchRange->SetFromX( nHitPosOld ); // マッチ位置from pMatchRange->SetToX ( nIdxPosOld ); // マッチ位置to break; } else { // この行でマッチした位置が存在しないので、前の行を検索へ nLinePos--; pDocLine = pDocLine->GetPrevLine(); nIdxPos = 0; if( NULL != pDocLine ){ nHitTo = pDocLine->GetLengthWithEOL() + 1; // 前の行のNULL文字(\0)にもマッチさせるために+1 2003.05.16 かろと } } } } // 前方検索 else { // // 前方検索(正規表現) // nIdxPos = ptSerachBegin.x; while( NULL != pDocLine ){ pLine = pDocLine->GetDocLineStrWithEOL( &nLineLen ); if( nIdxPos <= pDocLine->GetLengthWithoutEOL() && pRegexp->Match( pLine, nLineLen, nIdxPos ) ){ // マッチした pMatchRange->SetFromX( pRegexp->GetIndex() ); // マッチ位置from pMatchRange->SetToX ( pRegexp->GetLastIndex() ); // マッチ位置to break; } ++nLinePos; pDocLine = pDocLine->GetNextLine(); nIdxPos = 0; } } // // 正規表現検索の後処理 if ( pDocLine != NULL ) { // マッチした行がある pMatchRange->SetFromY(nLinePos); // マッチ行 pMatchRange->SetToY (nLinePos); // マッチ行 nRetVal = 1; // レイアウト行では改行文字内の位置を表現できないため、マッチ開始位置を補正 if (pMatchRange->GetFrom().x > pDocLine->GetLengthWithoutEOL()) { // \r\n改行時に\nにマッチすると置換できない不具合となるため // 改行文字内でマッチした場合、改行文字の始めからマッチしたことにする pMatchRange->SetFromX( pDocLine->GetLengthWithoutEOL() ); } } } //単語のみ検索 else if( sSearchOption.bWordOnly ){ // 検索語を単語に分割して searchWordsに格納する。 const wchar_t* pszPattern = pattern.GetKey(); const int nPatternLen = pattern.GetLen(); std::vector<std::pair<const wchar_t*, CLogicInt> > searchWords; // 単語の開始位置と長さの配列。 CreateWordList( searchWords, pszPattern, nPatternLen ); /* 2001/06/23 Norio Nakatani 単語単位の検索を試験的に実装。単語はWhereCurrentWord()で判別してますので、 英単語やC/C++識別子などの検索条件ならヒットします。 */ // 後方検索 if( eDirection == SEARCH_BACKWARD ){ nLinePos = ptSerachBegin.GetY2(); pDocLine = m_pcDocLineMgr->GetLine( nLinePos ); CLogicInt nNextWordFrom; CLogicInt nNextWordFrom2; CLogicInt nNextWordTo2; CLogicInt nWork; nNextWordFrom = ptSerachBegin.GetX2(); while( NULL != pDocLine ){ if( PrevOrNextWord( nLinePos, nNextWordFrom, &nWork, TRUE, FALSE ) ){ nNextWordFrom = nWork; if( WhereCurrentWord( nLinePos, nNextWordFrom, &nNextWordFrom2, &nNextWordTo2 , NULL, NULL ) ){ size_t nSize = searchWords.size(); for( size_t iSW = 0; iSW < nSize; ++iSW ) { if( searchWords[iSW].second == nNextWordTo2 - nNextWordFrom2 ){ const wchar_t* pData = pDocLine->GetPtr(); // 2002/2/10 aroka CMemory変更 /* 1==大文字小文字の区別 */ if( (!sSearchOption.bLoHiCase && 0 == auto_memicmp( &(pData[nNextWordFrom2]) , searchWords[iSW].first, searchWords[iSW].second ) ) || (sSearchOption.bLoHiCase && 0 == auto_memcmp( &(pData[nNextWordFrom2]) , searchWords[iSW].first, searchWords[iSW].second ) ) ){ pMatchRange->SetFromY(nLinePos); // マッチ行 pMatchRange->SetToY (nLinePos); // マッチ行 pMatchRange->SetFromX(nNextWordFrom2); // マッチ位置from pMatchRange->SetToX (pMatchRange->GetFrom().x + searchWords[iSW].second);// マッチ位置to nRetVal = 1; goto end_of_func; } } } continue; } } /* 前の行を見に行く */ nLinePos--; pDocLine = pDocLine->GetPrevLine(); if( NULL != pDocLine ){ nNextWordFrom = pDocLine->GetLengthWithEOL() - pDocLine->GetEol().GetLen(); if( 0 > nNextWordFrom ){ nNextWordFrom = CLogicInt(0); } } } } // 前方検索 else{ nLinePos = ptSerachBegin.GetY2(); pDocLine = m_pcDocLineMgr->GetLine( nLinePos ); CLogicInt nNextWordFrom = ptSerachBegin.GetX2(); while( NULL != pDocLine ){ pLine = pDocLine->GetDocLineStrWithEOL( &nLineLen ); int nMatchLen; pszRes = SearchStringWord(pLine, nLineLen, nNextWordFrom, searchWords, sSearchOption.bLoHiCase, &nMatchLen); if( NULL != pszRes ){ pMatchRange->SetFromY(nLinePos); // マッチ行 pMatchRange->SetToY (nLinePos); // マッチ行 pMatchRange->SetFromX(CLogicInt(pszRes - pLine)); // マッチ位置from pMatchRange->SetToX (pMatchRange->GetFrom().x + nMatchLen);// マッチ位置to nRetVal = 1; goto end_of_func; } /* 次の行を見に行く */ nLinePos++; pDocLine = pDocLine->GetNextLine(); nNextWordFrom = CLogicInt(0); } } nRetVal = 0; goto end_of_func; } //普通の検索 (正規表現でも単語単位でもない) else{ const int nPatternLen = pattern.GetLen(); // 後方検索 if( eDirection == SEARCH_BACKWARD ){ nLinePos = ptSerachBegin.GetY2(); nHitTo = ptSerachBegin.x; nIdxPos = 0; pDocLine = m_pcDocLineMgr->GetLine( nLinePos ); while( NULL != pDocLine ){ pLine = pDocLine->GetDocLineStrWithEOL( &nLineLen ); nHitPos = -1; for (;;) { nHitPosOld = nHitPos; nIdxPosOld = nIdxPos; pszRes = SearchString( pLine, nLineLen, nIdxPos, pattern ); if( NULL != pszRes ){ nHitPos = pszRes - pLine; nIdxPos = nHitPos + nPatternLen; // マッチ文字列長進めるように変更 2005.10.28 Karoto if( nHitPos >= nHitTo ){ if( -1 != nHitPosOld ){ pMatchRange->SetFromY(nLinePos); // マッチ行 pMatchRange->SetToY (nLinePos); // マッチ行 pMatchRange->SetFromX(nHitPosOld); // マッチ位置from pMatchRange->SetToX (nIdxPosOld); // マッチ位置to nRetVal = 1; goto end_of_func; }else{ break; } } }else{ if( -1 != nHitPosOld ){ pMatchRange->SetFromY(nLinePos); // マッチ行 pMatchRange->SetToY (nLinePos); // マッチ行 pMatchRange->SetFromX(nHitPosOld); // マッチ位置from pMatchRange->SetToX (nIdxPosOld); // マッチ位置to nRetVal = 1; goto end_of_func; }else{ break; } } } nLinePos--; pDocLine = pDocLine->GetPrevLine(); nIdxPos = 0; if( NULL != pDocLine ){ nHitTo = pDocLine->GetLengthWithEOL(); } } nRetVal = 0; goto end_of_func; } // 前方検索 else{ nIdxPos = ptSerachBegin.x; nLinePos = ptSerachBegin.GetY2(); pDocLine = m_pcDocLineMgr->GetLine( nLinePos ); while( NULL != pDocLine ){ pLine = pDocLine->GetDocLineStrWithEOL( &nLineLen ); pszRes = SearchString( pLine, nLineLen, nIdxPos, pattern ); if( NULL != pszRes ){ pMatchRange->SetFromY(nLinePos); // マッチ行 pMatchRange->SetToY (nLinePos); // マッチ行 pMatchRange->SetFromX(CLogicInt(pszRes - pLine)); // マッチ位置from (文字単位) pMatchRange->SetToX (pMatchRange->GetFrom().x + nPatternLen); // マッチ位置to (文字単位) nRetVal = 1; goto end_of_func; } ++nLinePos; pDocLine = pDocLine->GetNextLine(); nIdxPos = 0; } nRetVal = 0; goto end_of_func; } } end_of_func:; #ifdef MEASURE_SEARCH_TIME clockEnd = clock(); TCHAR buf[100]; memset(buf, 0x00, sizeof(buf)); wsprintf( buf, _T("%d"), clockEnd - clockStart); ::MessageBox( NULL, buf, GSTR_APPNAME, MB_OK ); #endif return nRetVal; }