Index: sakura_core/CLoadAgent.cpp =================================================================== --- sakura_core/CLoadAgent.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/CLoadAgent.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -126,6 +126,9 @@ // 文書種別確定 pcDoc->m_cDocType.SetDocumentType( sLoadInfo.nType, true ); + // 色分け方法確定 <- 文書種別確定 + pcDoc->RebuildColorStrategy(); + //ファイルが存在する場合はファイルを読む if(fexist(sLoadInfo.cFilePath)){ //CDocLineMgrの構成 Index: sakura_core/doc/CDocTypeSetting.cpp =================================================================== --- sakura_core/doc/CDocTypeSetting.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CDocTypeSetting.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,79 +0,0 @@ -// 2000.10.08 JEPRO 背景色を真っ白RGB(255,255,255)→(255,251,240)に変更(眩しさを押さえた) -// 2000.12.09 Jepro note: color setting (詳細は CshareData.h を参照のこと) -// 2000.09.04 JEPRO シングルクォーテーション文字列に色を割り当てるが色分け表示はしない -// 2000.10.17 JEPRO 色分け表示するように変更(最初のFALSE→TRUE) -// 2008.03.27 kobake 大整理 - -#include "stdafx.h" -#include "CDocTypeSetting.h" - - -//! 色設定(保存用) -struct ColorInfoIni { - const TCHAR* m_pszName; //!< 項目名 - ColorInfoBase m_sColorInfo; //!< 色設定 -}; - -static ColorInfoIni ColorInfo_DEFAULT[] = { -// 項目名, 表示, 太字, 下線, 文字色, 背景色, - _T("テキスト"), TRUE, FALSE, FALSE, RGB( 0, 0, 0 ), RGB( 255, 251, 240 ), - _T("ルーラー"), TRUE, FALSE, FALSE, RGB( 0, 0, 0 ), RGB( 239, 239, 239 ), - _T("カーソル"), TRUE, FALSE, FALSE, RGB( 0, 0, 0 ), RGB( 255, 251, 240 ), // 2006.12.07 ryoji - _T("カーソル(IME ON)"), TRUE, FALSE, FALSE, RGB( 255, 0, 0 ), RGB( 255, 251, 240 ), // 2006.12.07 ryoji - _T("カーソル行アンダーライン"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), - _T("カーソル位置縦線"), FALSE, FALSE, FALSE, RGB( 128, 128, 255 ), RGB( 255, 251, 240 ), // 2007.09.09 Moca - _T("行番号"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 239, 239, 239 ), - _T("行番号(変更行)"), TRUE, TRUE, FALSE, RGB( 0, 0, 255 ), RGB( 239, 239, 239 ), - _T("TAB記号"), TRUE, FALSE, FALSE, RGB( 128, 128, 128 ), RGB( 255, 251, 240 ), //Jan. 19, 2001 JEPRO RGB(192,192,192)より濃いグレーに変更 - _T("半角空白") , FALSE, FALSE, FALSE, RGB( 192, 192, 192 ), RGB( 255, 251, 240 ), //2002.04.28 Add by KK - _T("日本語空白"), TRUE, FALSE, FALSE, RGB( 192, 192, 192 ), RGB( 255, 251, 240 ), - _T("コントロールコード"), TRUE, FALSE, FALSE, RGB( 255, 255, 0 ), RGB( 255, 251, 240 ), - _T("改行記号"), TRUE, FALSE, FALSE, RGB( 0, 128, 255 ), RGB( 255, 251, 240 ), - _T("折り返し記号"), TRUE, FALSE, FALSE, RGB( 255, 0, 255 ), RGB( 255, 251, 240 ), - _T("指定桁縦線"), FALSE, FALSE, FALSE, RGB( 192, 192, 192 ), RGB( 255, 251, 240 ), //2005.11.08 Moca - _T("EOF記号"), TRUE, FALSE, FALSE, RGB( 0, 255, 255 ), RGB( 0, 0, 0 ), - _T("半角数値"), FALSE, FALSE, FALSE, RGB( 235, 0, 0 ), RGB( 255, 251, 240 ), //@@@ 2001.02.17 by MIK //Mar. 7, 2001 JEPRO RGB(0,0,255)を変更 Mar.10, 2001 標準は色なしに - _T("検索文字列"), TRUE, FALSE, FALSE, RGB( 0, 0, 0 ), RGB( 255, 255, 0 ), - _T("強調キーワード1"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), - _T("強調キーワード2"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), RGB( 255, 251, 240 ), //Dec. 4, 2000 MIK added //Jan. 19, 2001 JEPRO キーワード1とは違う色に変更 - _T("強調キーワード3"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), RGB( 255, 251, 240 ), //Dec. 4, 2000 MIK added //Jan. 19, 2001 JEPRO キーワード1とは違う色に変更 - _T("強調キーワード4"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), RGB( 255, 251, 240 ), - _T("強調キーワード5"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), RGB( 255, 251, 240 ), - _T("強調キーワード6"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), RGB( 255, 251, 240 ), - _T("強調キーワード7"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), RGB( 255, 251, 240 ), - _T("強調キーワード8"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), RGB( 255, 251, 240 ), - _T("強調キーワード9"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), RGB( 255, 251, 240 ), - _T("強調キーワード10"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), RGB( 255, 251, 240 ), - _T("コメント"), TRUE, FALSE, FALSE, RGB( 0, 128, 0 ), RGB( 255, 251, 240 ), - _T("シングルクォーテーション文字列"), TRUE, FALSE, FALSE, RGB( 64, 128, 128 ), RGB( 255, 251, 240 ), - _T("ダブルクォーテーション文字列"), TRUE, FALSE, FALSE, RGB( 128, 0, 64 ), RGB( 255, 251, 240 ), - _T("URL"), TRUE, FALSE, TRUE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), - _T("正規表現キーワード1"), FALSE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), //@@@ 2001.11.17 add MIK - _T("正規表現キーワード2"), FALSE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), //@@@ 2001.11.17 add MIK - _T("正規表現キーワード3"), FALSE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), //@@@ 2001.11.17 add MIK - _T("正規表現キーワード4"), FALSE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), //@@@ 2001.11.17 add MIK - _T("正規表現キーワード5"), FALSE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), //@@@ 2001.11.17 add MIK - _T("正規表現キーワード6"), FALSE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), //@@@ 2001.11.17 add MIK - _T("正規表現キーワード7"), FALSE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), //@@@ 2001.11.17 add MIK - _T("正規表現キーワード8"), FALSE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), //@@@ 2001.11.17 add MIK - _T("正規表現キーワード9"), FALSE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), //@@@ 2001.11.17 add MIK - _T("正規表現キーワード10"), FALSE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 255, 251, 240 ), //@@@ 2001.11.17 add MIK - _T("DIFF差分表示(追加)"), FALSE, FALSE, FALSE, RGB( 0, 0, 0 ), RGB( 255, 251, 240 ), //@@@ 2002.06.01 MIK - _T("DIFF差分表示(変更)"), FALSE, FALSE, FALSE, RGB( 0, 0, 0 ), RGB( 255, 251, 240 ), //@@@ 2002.06.01 MIK - _T("DIFF差分表示(削除)"), FALSE, FALSE, FALSE, RGB( 0, 0, 0 ), RGB( 255, 251, 240 ), //@@@ 2002.06.01 MIK - _T("対括弧の強調表示"), FALSE, TRUE, FALSE, RGB( 128, 0, 0 ), RGB( 255, 251, 240 ), // 02/09/18 ai - _T("ブックマーク"), TRUE , FALSE, FALSE, RGB( 255, 251, 240 ), RGB( 0, 128, 192 ), // 02/10/16 ai -}; - -void GetDefaultColorInfo(ColorInfo* pColorInfo, int nIndex) -{ - ColorInfoBase* p = pColorInfo; - *p = ColorInfo_DEFAULT[nIndex].m_sColorInfo; //ColorInfoBase - _tcscpy(pColorInfo->m_szName, ColorInfo_DEFAULT[nIndex].m_pszName); - pColorInfo->m_nColorIdx = nIndex; -} - -int GetDefaultColorInfoCount() -{ - return _countof(ColorInfo_DEFAULT); -} Index: sakura_core/doc/CLayoutMgr_DoLayout.cpp =================================================================== --- sakura_core/doc/CLayoutMgr_DoLayout.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CLayoutMgr_DoLayout.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -12,7 +12,7 @@ #include "mem/CMemoryIterator.h" #include "doc/CEditDoc.h" /// 2003/07/20 genta #include "util/window.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" //レイアウト中の禁則タイプ //@@@ 2002.04.20 MIK @@ -66,7 +66,6 @@ this->pcDocLine, CLogicPoint(this->nBgn, this->nCurLine), this->nPos - this->nBgn, - this->pcColorStrategy_Prev->GetStrategyColorSafe(), this->nIndent, this->nPosX ); @@ -217,8 +216,6 @@ nEol_1 = 0; } - if(pWork->pcColorStrategy)pWork->pcColorStrategy->InitStrategyStatus(); - //1ロジック行を消化するまでループ while( pWork->nPos < pWork->cLineStr.GetLength() - CLogicInt(nEol_1) ){ // インデント幅の計算コストを下げるための方策 @@ -231,7 +228,7 @@ pWork->pLayoutCalculated = pWork->pLayout; } -SEARCH_START:; +//SEARCH_START:; //禁則処理中ならスキップする @@@ 2002.04.20 MIK if(_DoKinsokuSkip(pWork, pfOnLine)){ } else{ @@ -248,11 +245,6 @@ _DoGyomatsuKinsoku(pWork, pfOnLine); } - //@@@ 2002.09.22 YAZAKI - bool bGotoSEARCH_START = CColorStrategyPool::Instance()->CheckColorMODE( &pWork->pcColorStrategy, pWork->nPos, pWork->cLineStr ); - if ( bGotoSEARCH_START ) - goto SEARCH_START; - if( pWork->cLineStr.At(pWork->nPos) == WCODE::TAB ){ if(_DoTab(pWork, pfOnLine)){ continue; @@ -291,9 +283,7 @@ void CLayoutMgr::_OnLine1(SLayoutWork* pWork) { AddLineBottom( pWork->_CreateLayout(this) ); - m_nLineTypeBot = pWork->pcColorStrategy->GetStrategyColorSafe(); pWork->pLayout = m_pLayoutBot; - pWork->pcColorStrategy_Prev = pWork->pcColorStrategy; pWork->nBgn = pWork->nPos; // 2004.03.28 Moca pWork->nPosXはインデント幅を含むように変更(TAB位置調整のため) pWork->nPosX = pWork->nIndent = (this->*m_getIndentOffset)( pWork->pLayout ); @@ -339,8 +329,6 @@ SLayoutWork* pWork = &_sWork; pWork->pcDocLine = m_pcDocLineMgr->GetDocLineTop(); // 2002/2/10 aroka CDocLineMgr変更 pWork->pLayout = m_pLayoutBot; - pWork->pcColorStrategy = NULL; - pWork->pcColorStrategy_Prev = NULL; pWork->nCurLine = CLogicInt(0); while( NULL != pWork->pcDocLine ){ @@ -358,13 +346,7 @@ _MakeOneLine(pWork, &CLayoutMgr::_OnLine1); if( pWork->nPos - pWork->nBgn > 0 ){ -// 2002/03/13 novice - if( pWork->pcColorStrategy->GetStrategyColorSafe() == COLORIDX_COMMENT ){ /* 行コメントである */ - pWork->pcColorStrategy = NULL; - } AddLineBottom( pWork->_CreateLayout(this) ); - m_nLineTypeBot = pWork->pcColorStrategy->GetStrategyColorSafe(); - pWork->pcColorStrategy_Prev = pWork->pcColorStrategy; } // 次の行へ @@ -376,12 +358,6 @@ NotifyProgress(pWork->nCurLine * 100 / nAllLineNum); if( !::BlockingHook( NULL ) )return; } - -// 2002/03/13 novice - if( pWork->pcColorStrategy_Prev->GetStrategyColorSafe() == COLORIDX_COMMENT ){ /* 行コメントである */ - pWork->pcColorStrategy_Prev = NULL; - } - pWork->pcColorStrategy = pWork->pcColorStrategy_Prev; } m_nPrevReferLine = CLayoutInt(0); @@ -403,15 +379,7 @@ void CLayoutMgr::_OnLine2(SLayoutWork* pWork) { //@@@ 2002.09.23 YAZAKI 最適化 - if( pWork->bNeedChangeCOMMENTMODE ){ - pWork->pLayout = pWork->pLayout->GetNextLayout(); - pWork->pLayout->SetColorTypePrev(pWork->pcColorStrategy_Prev->GetStrategyColorSafe()); - (*pWork->pnExtInsLineNum)++; // 再描画してほしい行数+1 - } - else { - pWork->pLayout = InsertLineNext( pWork->pLayout, pWork->_CreateLayout(this) ); - } - pWork->pcColorStrategy_Prev = pWork->pcColorStrategy; + pWork->pLayout = InsertLineNext( pWork->pLayout, pWork->_CreateLayout(this) ); pWork->nBgn = pWork->nPos; // 2004.03.28 Moca pWork->nPosXはインデント幅を含むように変更(TAB位置調整のため) @@ -442,7 +410,6 @@ CLayout* pLayoutPrev, CLogicInt nLineNum, CLogicPoint _ptDelLogicalFrom, - EColorIndexType nCurrentLineType, const CalTextWidthArg* pctwArg, CLayoutInt* _pnExtInsLineNum ) @@ -459,9 +426,6 @@ SLayoutWork _sWork; SLayoutWork* pWork = &_sWork; pWork->pLayout = pLayoutPrev; - pWork->pcColorStrategy = CColorStrategyPool::Instance()->GetStrategyByColor(nCurrentLineType); - pWork->pcColorStrategy_Prev = pWork->pcColorStrategy; - pWork->bNeedChangeCOMMENTMODE = false; if( NULL == pWork->pLayout ){ pWork->nCurLine = CLogicInt(0); }else{ @@ -473,8 +437,6 @@ pWork->ptDelLogicalFrom = _ptDelLogicalFrom; pWork->pnExtInsLineNum = _pnExtInsLineNum; - if(pWork->pcColorStrategy)pWork->pcColorStrategy->InitStrategyStatus(); - while( NULL != pWork->pcDocLine ){ pWork->cLineStr = pWork->pcDocLine->GetStringRefWithEOL(); pWork->nKinsokuType = KINSOKU_TYPE_NONE; //@@@ 2002.04.20 MIK @@ -489,10 +451,6 @@ _MakeOneLine(pWork, &CLayoutMgr::_OnLine2); if( pWork->nPos - pWork->nBgn > 0 ){ -// 2002/03/13 novice - if( pWork->pcColorStrategy->GetStrategyColorSafe() == COLORIDX_COMMENT ){ /* 行コメントである */ - pWork->pcColorStrategy = NULL; - } //@@@ 2002.09.23 YAZAKI 最適化 _OnLine2(pWork); } @@ -503,27 +461,14 @@ /* 目的の行数(nLineNum)に達したか、または通り過ぎた(=行数が増えた)か確認 */ //@@@ 2002.09.23 YAZAKI 最適化 if( nLineNumWork >= nLineNum ){ - if( pWork->pLayout && pWork->pLayout->m_pNext - && ( pWork->pcColorStrategy_Prev->GetStrategyColorSafe() != pWork->pLayout->m_pNext->GetColorTypePrev() ) - ){ - // COMMENTMODEが異なる行が増えましたので、次の行→次の行と更新していきます。 - pWork->bNeedChangeCOMMENTMODE = true; - }else{ - break; // while( NULL != pWork->pcDocLine ) 終了 - } + break; } pWork->pcDocLine = pWork->pcDocLine->GetNextLine(); -// 2002/03/13 novice - if( pWork->pcColorStrategy_Prev->GetStrategyColorSafe() == COLORIDX_COMMENT ){ /* 行コメントである */ - pWork->pcColorStrategy_Prev = NULL; - } - pWork->pcColorStrategy = pWork->pcColorStrategy_Prev; } // 2004.03.28 Moca EOFだけの論理行の直前の行の色分けが確認・更新された if( pWork->nCurLine == m_pcDocLineMgr->GetLineCount() ){ - m_nLineTypeBot = pWork->pcColorStrategy_Prev->GetStrategyColorSafe(); // 2006.10.01 Moca 最終行が変更された。EOF位置情報を破棄する。 m_nEOFColumn = CLayoutInt(-1); m_nEOFLine = CLayoutInt(-1); Index: sakura_core/doc/CEditDoc.cpp =================================================================== --- sakura_core/doc/CEditDoc.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CEditDoc.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -22,6 +22,8 @@ */ #include "stdafx.h" +#include +#include #include #include #include // Apr. 03, 2003 genta @@ -58,6 +60,14 @@ #include "CControlTray.h" #include "docplus/CModifyManager.h" #include "CCodeChecker.h" +#include "view/colors/EColorIndexType.h" +#include "view/colors/ColorMLStrategy.h" +#include "view/colors/CColorML_RegexKeyword.h" +#include "view/colors/CColorML_KeywordSet.h" +#include "view/colors/CColorML_Comment.h" +#include "view/colors/CColorML_Numeric.h" +#include "view/colors/CColorML_Quote.h" +#include "view/colors/CColorML_Url.h" #define IDT_ROLLMOUSE 1 @@ -81,6 +91,7 @@ , m_cDocType(this) , m_cDocEditor(this) , m_cDocFileOperation(this) +, pColorStrategyMain( 0 ) { MY_RUNNINGTIMER( cRunningTimer, "CEditDoc::CEditDoc" ); @@ -115,6 +126,8 @@ // 文字コード種別を初期化 m_cDocFile.m_sFileInfo.eCharCode = static_cast( CShareData::getInstance()->GetShareData()->m_Types[0].m_eDefaultCodetype ); + + this->RebuildColorStrategy(); // 無題ドキュメントのために初期化。 } @@ -539,6 +552,9 @@ CLogicPoint* posSaveAry = m_pcEditWnd->SavePhysPosOfAllView(); + // 色分けロジックの再構築 + this->RebuildColorStrategy(); + /* レイアウト情報の作成 */ STypeConfig ref = m_cDocType.GetDocumentAttribute(); { @@ -690,3 +706,114 @@ bRunning = false; } +void CEditDoc::HighlightInfo( const CLogicInt nLineNumber, ColorMLStrategy::Result* const outResult ) +{ + if( ! outResult ) { + return; + } + if( this->pColorStrategyMain.get() ) { + this->pColorStrategyMain->HighlightLine( this, nLineNumber, outResult ); + } else { + *outResult = ColorMLStrategy::Result(); + outResult->colorInfo.resize( this->m_cDocLineMgr.GetLine( nLineNumber )->GetLengthWithEOL(), COLORIDX_DEFAULT ); + } +} + +void CEditDoc::NotifyLineChange( const CLogicInt nLineNumber ) +{ + if( this->pColorStrategyMain.get() ) { + this->pColorStrategyMain->NotifyLineChange( nLineNumber ); + } +} + +void CEditDoc::NotifyLineChangeAfter( const CLogicInt nLineNumber ) +{ + if( this->pColorStrategyMain.get() ) { + this->pColorStrategyMain->NotifyLineChangeAfter( nLineNumber ); + } +} + +void CEditDoc::RebuildColorStrategy() +{ + const STypeConfig& doctype = this->m_cDocType.GetDocumentAttribute(); + + /* + 検索語ハイライト以外すべての色分けを担当。 + 色分けユニットは追加された順に優先順位が高くなるのだが、 + 1. よりユーザーの意図を反映したもの。(設定項目の存在。設定の柔軟さ) + 2. 誤認識の影響の小ささ。(起こる可能性と起こった場合の影響範囲) + を基準に順番を決めた。 + (例外) 正規表現キーワードは難しいので強調キーワードの下にする。 + 何で思い通りに色分けされへんの?ムキー!ってなるでしょ。 + */ + std::auto_ptr pStrategy( new ColorMLStrategy( this ) ); + std::auto_ptr pUnit; + + for( int i = 0; i < MAX_KEYWORDSET_PER_TYPE; ++i ) { + // 強調キーワード1の方が強調キーワード10より優先度が高い。 + if( doctype.m_ColorInfoArr[ COLORIDX_KEYWORD1 + i ].m_bDisp + && doctype.m_nKeyWordSetIdx[ i ] != -1 + ) { + pUnit.reset( new CColorML_KeywordSet( static_cast( COLORIDX_KEYWORD1 + i ), doctype.m_nKeyWordSetIdx[ i ] ) ); + pStrategy->PushStrategyUnit( pUnit ); + } + } + + // iniファイルのあるディレクトリに rkw2/タイプ設定名.rkw2というファイルがあるかどうかが、 + // 色分けの ON/OFF設定を兼ねるので、ここでは無条件に作成する。 + pUnit.reset( new CColorML_RegexKeyword() ); + pStrategy->PushStrategyUnit( pUnit ); + + if( doctype.m_ColorInfoArr[ COLORIDX_COMMENT ].m_bDisp ) { + // コメントは開始文字の長い順に登録する。 + std::auto_ptr comments[ COMMENT_DELIMITER_NUM + BLOCKCOMMENT_NUM ]; + std::pair index_and_size[ COMMENT_DELIMITER_NUM + BLOCKCOMMENT_NUM ]; + for( int i = 0; i < COMMENT_DELIMITER_NUM; ++i ) { + const int index = i; + const size_t size = wcslen( doctype.m_cLineComment.getLineComment( i ) ); + index_and_size[index] = std::make_pair( index, size ); + if( 0 < size ) { + comments[index].reset( new CColorML_LineComment( doctype.m_cLineComment.getLineComment( i ), doctype.m_cLineComment.getLineCommentPos( i ) ) ); + } + } + for( int i = 0; i < BLOCKCOMMENT_NUM; ++i ) { + const int index = COMMENT_DELIMITER_NUM + i; + const size_t lenStart = wcslen( doctype.m_cBlockComments[ i ].getBlockCommentFrom() ); + const size_t lenEnd = wcslen( doctype.m_cBlockComments[ i ].getBlockCommentTo() ); + const size_t size = 0 != lenStart * lenEnd ? lenStart : 0; + index_and_size[index] = std::make_pair( index, size ); + if( 0 < size ) { + comments[index].reset( new CColorML_BlockComment( doctype.m_cBlockComments[ i ].getBlockCommentFrom(), doctype.m_cBlockComments[ i ].getBlockCommentTo() ) ); + } + } + const struct { + bool operator()( std::pair& lhs, std::pair& rhs ) const + { return lhs.second > rhs.second; } // 2番目の値( 開始文字の長さ )の長い順。 + } Pred; + std::sort( index_and_size, index_and_size + _countof(index_and_size), Pred ); + for( int i = 0; i < _countof(index_and_size); ++i ) { + if( index_and_size[i].second == 0 ) { + break; + } + pStrategy->PushStrategyUnit( comments[ index_and_size[i].first ] ); + } + } + + if( doctype.m_ColorInfoArr[ COLORIDX_URL ].m_bDisp ) { + pUnit.reset( new CColorML_Url() ); + pStrategy->PushStrategyUnit( pUnit ); + } + if( doctype.m_ColorInfoArr[ COLORIDX_DIGIT ].m_bDisp ) { + pUnit.reset( new CColorML_Numeric() ); + pStrategy->PushStrategyUnit( pUnit ); + } + if( doctype.m_ColorInfoArr[ COLORIDX_WSTRING ].m_bDisp ) { + pUnit.reset( new CColorML_WQuote() ); + pStrategy->PushStrategyUnit( pUnit ); + } + if( doctype.m_ColorInfoArr[ COLORIDX_SSTRING ].m_bDisp ) { + pUnit.reset( new CColorML_SQuote() ); + pStrategy->PushStrategyUnit( pUnit ); + } + this->pColorStrategyMain = pStrategy; +} Index: sakura_core/doc/CDocType.h =================================================================== --- sakura_core/doc/CDocType.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CDocType.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -6,6 +6,7 @@ #pragma once #include "types/CType.h" // CTypeConfig +#include "env/CDocTypeManager.h" class CDocType{ public: Index: sakura_core/doc/CLayoutMgr_New2.cpp =================================================================== --- sakura_core/doc/CLayoutMgr_New2.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CLayoutMgr_New2.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -19,10 +19,10 @@ #include #include "doc/CLayout.h" // 2002/2/10 aroka #include "doc/CDocLineMgr.h" // 2002/2/10 aroka -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" +#include "view/colors/ColorMLStrategy.h" - /* 文字列置換 */ void CLayoutMgr::ReplaceData_CLayoutMgr( LayoutReplaceArg* pArg @@ -32,7 +32,6 @@ /* 置換先頭位置のレイアウト情報 */ CLayout* pLayout = SearchLineByLayoutY( pArg->sDelRange.GetFrom().GetY2() ); - EColorIndexType nCurrentLineType = COLORIDX_DEFAULT; CLayoutInt nLineWork = pArg->sDelRange.GetFrom().GetY2(); CLayout* pLayoutWork = pLayout; @@ -41,7 +40,6 @@ pLayoutWork = pLayoutWork->GetPrevLayout(); nLineWork--; } - nCurrentLineType = pLayoutWork->GetColorTypePrev(); } @@ -69,6 +67,11 @@ &DLRArg ); +if( DLRArg.nDeletedLineNum == DLRArg.nInsLineNum ) { + this->m_pcEditDoc->NotifyLineChange( ptFrom.GetY2() ); +} else { + this->m_pcEditDoc->NotifyLineChangeAfter( ptFrom.GetY2() ); +} /*--- 変更された行のレイアウト情報を再生成 ---*/ /* 論理行の指定範囲に該当するレイアウト情報を削除して */ @@ -138,7 +141,6 @@ pLayoutPrev, nRowNum, ptFrom, - nCurrentLineType, &ctwArg, &nAddInsLineNum ); Index: sakura_core/doc/CLineComment.h =================================================================== --- sakura_core/doc/CLineComment.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CLineComment.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -38,7 +38,7 @@ void CopyTo( const int n, const wchar_t* buffer, int nCommentPos ); // 行コメントデリミタをコピーする bool Match( int nPos, const CStringRef& cStr ) const; // 行コメントに値するか確認する - const wchar_t* getLineComment( const int n ){ + const wchar_t* getLineComment( const int n ) const { return m_pszLineComment[n]; }; int getLineCommentPos( const int n ) const { Index: sakura_core/doc/CLayoutMgr_Color.cpp =================================================================== --- sakura_core/doc/CLayoutMgr_Color.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CLayoutMgr_Color.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,3 +1,3 @@ #include "stdafx.h" #include "CLayoutMgr.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" Index: sakura_core/doc/CLayout.h =================================================================== --- sakura_core/doc/CLayout.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CLayout.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -41,7 +41,6 @@ const CDocLine* pcDocLine, //!< 実データへの参照 CLogicPoint ptLogicPos, //!< 実データ参照位置 CLogicInt nLength, //!< 実データ内データ長 - EColorIndexType nTypePrev, CLayoutInt nTypeIndent ) { @@ -50,7 +49,7 @@ m_pCDocLine = pcDocLine; m_ptLogicPos = ptLogicPos; // 実データ参照位置 m_nLength = nLength; // 実データ内データ長 - m_nTypePrev = nTypePrev; // タイプ 0=通常 1=行コメント 2=ブロックコメント 3=シングルクォーテーション文字列 4=ダブルクォーテーション文字列 +// m_nTypePrev = nTypePrev; // タイプ 0=通常 1=行コメント 2=ブロックコメント 3=シングルクォーテーション文字列 4=ダブルクォーテーション文字列 m_nIndent = nTypeIndent; // このレイアウト行のインデント数 @@@ 2002.09.23 YAZAKI } ~CLayout(); @@ -67,15 +66,10 @@ CLogicInt GetLogicLineNo() const{ if(this)return m_ptLogicPos.GetY2(); else return CLogicInt(-1); } //$$$高速化 CLogicInt GetLogicOffset() const{ return m_ptLogicPos.GetX2(); } CLogicPoint GetLogicPos() const{ return m_ptLogicPos; } - EColorIndexType GetColorTypePrev() const{ return m_nTypePrev; } //#########汚っ CLayoutInt GetLayoutWidth() const{ return m_nLayoutWidth; } // 2009.08.28 nasukoji このレイアウト行の改行を含むレイアウト長を返す //変更インターフェース void OffsetLogicLineNo(CLogicInt n){ m_ptLogicPos.y+=n; } - void SetColorTypePrev(EColorIndexType n) - { - m_nTypePrev=n; - } void SetLayoutWidth(CLayoutInt nWidth){ m_nLayoutWidth = nWidth; } //!レイアウト幅を計算。インデントも改行も含まない。2007.10.11 kobake @@ -109,7 +103,6 @@ CLogicInt m_nLength; //!< このレイアウト行の長さ。文字単位。 //その他属性 - EColorIndexType m_nTypePrev; //!< タイプ 0=通常 1=行コメント 2=ブロックコメント 3=シングルクォーテーション文字列 4=ダブルクォーテーション文字列 CLayoutInt m_nIndent; //!< このレイアウト行のインデント数 @@@ 2002.09.23 YAZAKI CEol m_cEol; CLayoutInt m_nLayoutWidth; //!< このレイアウト行の改行を含むレイアウト長(「折り返さない」選択時のみ) */ // 2009.08.28 nasukoji Index: sakura_core/doc/CLayoutMgr.cpp =================================================================== --- sakura_core/doc/CLayoutMgr.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CLayoutMgr.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -28,10 +28,10 @@ #include "mem/CMemory.h"/// 2002/2/10 aroka #include "mem/CMemoryIterator.h" // 2006.07.29 genta #include "basis/SakuraBasis.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" +#include "view/colors/ColorMLStrategy.h" - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // // 生成と破棄 // // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // @@ -359,7 +359,6 @@ CDocLine* pCDocLine, CLogicPoint ptLogicPos, CLogicInt nLength, - EColorIndexType nTypePrev, CLayoutInt nIndent, CLayoutInt nPosX ) @@ -368,7 +367,6 @@ pCDocLine, ptLogicPos, nLength, - nTypePrev, nIndent ); @@ -532,7 +530,6 @@ CLogicInt nRowNum; CLogicInt nDelStartLogicalLine; CLogicInt nDelStartLogicalPos; - EColorIndexType nCurrentLineType; CLayoutInt nLineWork; /* 現在行のデータを取得 */ @@ -550,7 +547,6 @@ pLayoutWork = pLayoutWork->GetPrevLayout(); --nLineWork; } - nCurrentLineType = pLayoutWork->GetColorTypePrev(); /* テキストのデータを削除 */ CDocEditAgent(m_pcDocLineMgr).DeleteData_CDocLineMgr( @@ -566,6 +562,16 @@ // DUMP(); +/* + ここは実行されてないね。 + CLayoutMgr::ReplaceData_CLayoutMgr()@docCLayoutMgr_New2.cpp を見よ。 +*/ +if( 0 == nDelLineOldNum ) { + this->m_pcEditDoc->NotifyLineChange( std::min( nDelStartLogicalLine, nModLineOldFrom ) ); +} else { + this->m_pcEditDoc->NotifyLineChangeAfter( std::min( nDelStartLogicalLine, nModLineOldFrom ) ); +} + /*--- 変更された行のレイアウト情報を再生成 ---*/ /* 論理行の指定範囲に該当するレイアウト情報を削除して */ /* 削除した範囲の直前のレイアウト情報のポインタを返す */ @@ -617,7 +623,6 @@ pLayoutPrev, nRowNum, CLogicPoint(nDelStartLogicalPos, nDelStartLogicalLine), - nCurrentLineType, &ctwArg, &nAddInsLineNum ); @@ -653,7 +658,6 @@ CLogicInt nInsStartLogicalPos; CLogicInt nInsLineNum; CLogicInt nRowNum; - EColorIndexType nCurrentLineType; CLayoutInt nLineWork; @@ -673,7 +677,6 @@ nLineWork = CLayoutInt(0); nInsStartLogicalLine = m_pcDocLineMgr->GetLineCount(); nInsStartLogicalPos = CLogicInt(0); - nCurrentLineType = COLORIDX_DEFAULT; } else{ using namespace WCODE; @@ -687,7 +690,6 @@ nLineWork = CLayoutInt(0); nInsStartLogicalLine = m_pcDocLineMgr->GetLineCount(); nInsStartLogicalPos = CLogicInt(0); - nCurrentLineType = m_nLineTypeBot; } else{ /* 空でないテキストの最後の行を変更する場合 */ @@ -699,7 +701,6 @@ nInsStartLogicalLine = pLayout->GetLogicLineNo(); nInsStartLogicalPos = nInsPos + pLayout->GetLogicOffset(); - nCurrentLineType = pLayout->GetColorTypePrev(); } } }else{ @@ -709,7 +710,6 @@ nInsStartLogicalLine = pLayout->GetLogicLineNo(); nInsStartLogicalPos = nInsPos + pLayout->GetLogicOffset(); - nCurrentLineType = pLayout->GetColorTypePrev(); } if( pLayout ){ @@ -718,11 +718,6 @@ pLayoutWork = pLayoutWork->GetPrevLayout(); nLineWork--; } - if( NULL != pLayoutWork ){ - nCurrentLineType = pLayoutWork->GetColorTypePrev(); - }else{ - nCurrentLineType = COLORIDX_DEFAULT; - } } @@ -737,6 +732,11 @@ &ptNewPos ); +if( 0 == nInsLineNum ) { + this->m_pcEditDoc->NotifyLineChange( nInsStartLogicalLine ); +} else { + this->m_pcEditDoc->NotifyLineChangeAfter( nInsStartLogicalLine ); +} //--- 変更された行のレイアウト情報を再生成 --- // 論理行の指定範囲に該当するレイアウト情報を削除して @@ -796,7 +796,6 @@ pLayoutPrev, nRowNum, CLogicPoint(nInsStartLogicalPos, nInsStartLogicalLine), - nCurrentLineType, &ctwArg, &nAddInsLineNum ); @@ -902,7 +901,6 @@ pLayout = pLayoutNext; } // MYTRACE_A( "(*pnDeleteLines)=%d\n", (*pnDeleteLines) ); - return pLayoutWork; } @@ -1277,7 +1275,7 @@ else{ pptLogic->y = m_pcDocLineMgr->GetLineCount() - 1; // 2002/2/10 aroka CDocLineMgr変更 bEOF = TRUE; - nX = CLayoutInt(MAXLINEKETAS); + nX = MAXLINEKETAS; goto checkloop; } Index: sakura_core/doc/CLayoutMgr_New.cpp =================================================================== --- sakura_core/doc/CLayoutMgr_New.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CLayoutMgr_New.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -30,7 +30,7 @@ #include "mem/CMemoryIterator.h" #include "doc/CEditDoc.h" /// 2003/07/20 genta #include "util/window.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" Index: sakura_core/doc/CDocType.cpp =================================================================== --- sakura_core/doc/CDocType.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CDocType.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -8,6 +8,7 @@ { } + // 文書種別の設定 void CDocType::SetDocumentType(CTypeConfig type, bool force, bool bTypeOnly ) { Index: sakura_core/doc/CDocTypeSetting.h =================================================================== --- sakura_core/doc/CDocTypeSetting.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CDocTypeSetting.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,37 +1,6 @@ #pragma once -#include "CRegexKeyword.h" //struct RegexKeywordInfo - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// 色設定 // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -//! 色設定 -struct ColorInfoBase{ - bool m_bDisp; //!< 表示 - bool m_bFatFont; //!< 太字 - bool m_bUnderLine; //!< 下線 - COLORREF m_colTEXT; //!< 文字色 - COLORREF m_colBACK; //!< 背景色 -}; - -//! 名前とインデックス付き色設定 -struct NamedColorInfo : public ColorInfoBase{ - int m_nColorIdx; //!< インデックス - TCHAR m_szName[64]; //!< 名前 -}; - - -typedef NamedColorInfo ColorInfo; - - -//デフォルト色設定 -void GetDefaultColorInfo(ColorInfo* pColorInfo, int nIndex); -int GetDefaultColorInfoCount(); - - - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // // 辞書 // // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // //@@@ 2006.04.10 fon ADD-start @@ -42,6 +11,3 @@ SFilePath m_szPath; //!< ファイルパス }; //@@@ 2006.04.10 fon ADD-end - - -#include "types/CType.h" Index: sakura_core/doc/CEditDoc.h =================================================================== --- sakura_core/doc/CEditDoc.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CEditDoc.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -43,8 +43,10 @@ #include "CDocFile.h" #include "CDocFileOperation.h" #include "CDocOutline.h" -#include "CDocType.h" +#include "doc/CDocType.h" #include "CDocLocker.h" +#include +#include "view/colors/ColorMLStrategy.h" class CImageListMgr; // 2002/2/10 aroka class CSMacroMgr; // 2002/2/10 aroka @@ -52,6 +54,7 @@ struct EditInfo; // 20050705 aroka class CFuncInfoArr; class CEditApp; +class ColorMLStrategy; typedef CEditWnd* P_CEditWnd; /*! @@ -98,6 +101,13 @@ void RunAutoMacro( int idx, LPCTSTR pszSaveFilePath = NULL ); // 2006.09.01 ryoji マクロ自動実行 + // 色分け +public: + void HighlightInfo( const CLogicInt nLineNumber, ColorMLStrategy::Result* outResult ); + void NotifyLineChange( const CLogicInt nLinenumber ); // ドキュメントの行の内容が変化した。ハイライト情報をリセット・再構築しなければいけない。とドキュメントに知らせる。 + void NotifyLineChangeAfter( const CLogicInt nLinenumber ); // ドキュメントに行の削除や挿入があった。ハイライト情報をリセット・再構築しなければいけない。とドキュメントに知らせる。 + void RebuildColorStrategy(); // ファイルを読み込んだり、タイプ別設定の変更があったときに呼ぶ。 + // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // // メンバ変数群 // // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // @@ -136,12 +146,13 @@ public: int m_nTextWrapMethodCur; // 折り返し方法 // 2008.05.30 nasukoji bool m_bTextWrapMethodCurTemp; // 折り返し方法一時設定適用中 // 2008.05.30 nasukoji + + // 色分け +private: + std::auto_ptr pColorStrategyMain; }; /////////////////////////////////////////////////////////////////////// #endif /* _CEDITDOC_H_ */ - - - Index: sakura_core/doc/CLayoutMgr.h =================================================================== --- sakura_core/doc/CLayoutMgr.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/doc/CLayoutMgr.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -31,6 +31,7 @@ #include "basis/SakuraBasis.h" #include #include "util/container.h" +#include "doc/CDocListener.h" class CBregexp;// 2002/2/10 aroka class CLayout;// 2002/2/10 aroka @@ -41,7 +42,6 @@ struct STypeConfig;// 2005.11.20 Moca class CColorStrategy; #include "basis/SakuraBasis.h" -enum EColorIndexType; struct LayoutReplaceArg { CLayoutRange sDelRange; //!< 削除範囲。レイアウト単位。 @@ -241,7 +241,7 @@ void _DoLayout(); /* 現在の折り返し文字数に合わせて全データのレイアウト情報を再生成します */ // 2005.11.21 Moca 引用符の色分け情報を引数から除去 // 2009.08.28 nasukoji テキスト最大幅算出用引数追加 - CLayoutInt DoLayout_Range( CLayout* , CLogicInt, CLogicPoint, EColorIndexType, const CalTextWidthArg*, CLayoutInt* ); /* 指定レイアウト行に対応する論理行の次の論理行から指定論理行数だけ再レイアウトする */ + CLayoutInt DoLayout_Range( CLayout* , CLogicInt, CLogicPoint, const CalTextWidthArg*, CLayoutInt* ); /* 指定レイアウト行に対応する論理行の次の論理行から指定論理行数だけ再レイアウトする */ void CalculateTextWidth_Range( const CalTextWidthArg* pctwArg ); /* テキストが編集されたら最大幅を算出する */ // 2009.08.28 nasukoji CLayout* DeleteLayoutAsLogical( CLayout*, CLayoutInt, CLogicInt , CLogicInt, CLogicPoint, CLayoutInt* ); /* 論理行の指定範囲に該当するレイアウト情報を削除 */ void ShiftLogicalLineNum( CLayout* , CLogicInt ); /* 指定行より後の行のレイアウト情報について、論理行番号を指定行数だけシフトする */ @@ -262,15 +262,12 @@ //ループ外 CDocLine* pcDocLine; CLayout* pLayout; - CColorStrategy* pcColorStrategy; - CColorStrategy* pcColorStrategy_Prev; CLogicInt nCurLine; //ループ外 (DoLayoutのみ) // CLogicInt nLineNum; //ループ外 (DoLayout_Rangeのみ) - bool bNeedChangeCOMMENTMODE; CLayoutInt nModifyLayoutLinesNew; //ループ外 (DoLayout_Range引数) @@ -326,7 +323,7 @@ */ //@@@ 2002.09.23 YAZAKI // 2009.08.28 nasukoji nPosX引数追加 - CLayout* CreateLayout( CDocLine* pCDocLine, CLogicPoint ptLogicPos, CLogicInt nLength, EColorIndexType nTypePrev, CLayoutInt nIndent, CLayoutInt nPosX ); + CLayout* CreateLayout( CDocLine* pCDocLine, CLogicPoint ptLogicPos, CLogicInt nLength, CLayoutInt nIndent, CLayoutInt nPosX ); CLayout* InsertLineNext( CLayout*, CLayout* ); void AddLineBottom( CLayout* ); @@ -356,7 +353,6 @@ CalcIndentProc m_getIndentOffset; // Oct. 1, 2002 genta インデント幅計算関数を保持 //フラグ等 - EColorIndexType m_nLineTypeBot; //!< タイプ 0=通常 1=行コメント 2=ブロックコメント 3=シングルクォーテーション文字列 4=ダブルクォーテーション文字列 CLayoutInt m_nLines; // 全レイアウト行数 mutable CLayoutInt m_nPrevReferLine; Index: sakura_core/CRegexKeyword.h =================================================================== --- sakura_core/CRegexKeyword.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/CRegexKeyword.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -69,7 +69,7 @@ //@@@ 2001.11.17 add start MIK struct RegexKeywordInfo { wchar_t m_szKeyword[100]; //正規表現キーワード - int m_nColorIndex; //色指定番号 + EColorIndexType m_nColorIndex; //色指定番号 }; //@@@ 2001.11.17 add end MIK Index: sakura_core/CPrintPreview.cpp =================================================================== --- sakura_core/CPrintPreview.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/CPrintPreview.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -31,7 +31,7 @@ #include "util/window.h" #include "util/shell.h" #include "env/CSakuraEnvironment.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" using namespace std; #define MIN_PREVIEW_ZOOM 10 Index: sakura_core/types/CType_Cobol.cpp =================================================================== --- sakura_core/types/CType_Cobol.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Cobol.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -2,7 +2,7 @@ #include "types/CType.h" #include "doc/CDocOutline.h" #include "outline/CFuncInfoArr.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* COBOL */ void CType_Cobol::InitTypeConfigImp(STypeConfig* pType) Index: sakura_core/types/CType_Basis.cpp =================================================================== --- sakura_core/types/CType_Basis.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Basis.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,6 +1,6 @@ #include "stdafx.h" #include "types/CType.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" void CType_Basis::InitTypeConfigImp(STypeConfig* pType) { Index: sakura_core/types/CPropTypes_P4_Regex.cpp =================================================================== --- sakura_core/types/CPropTypes_P4_Regex.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CPropTypes_P4_Regex.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -31,7 +31,7 @@ #include "io/CTextStream.h" #include "util/shell.h" #include "util/file.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" using namespace std; @@ -95,7 +95,8 @@ RegexKeywordInfo pRegexKey[MAX_REGEX_KEYWORD]; TCHAR buff[1024]; - int i, j, k; + int i, j; + EColorIndexType color; j = 0; while(in) { @@ -117,27 +118,18 @@ p++; if( p[0] && RegexKakomiCheck(to_wchar(p)) ) //囲みがある { - //色指定名に対応する番号を探す - k = GetColorIndexByName( &buff[11] ); //@@@ 2002.04.30 - if( k != -1 ) /* 3文字カラー名からインデックス番号に変換 */ - { - pRegexKey[j].m_nColorIndex = k; + // 色名から色インデックスへ + color = GetColorIndexFromShortName( &buff[11] ); /* 3文字カラー名からインデックス番号に変換 */ + if( color == COLORIDX_DEFAULT ) { + color = GetColorIndexFromLongName( buff + 11 ); /* 日本語名からインデックス番号に変換する */ + } + if( color != COLORIDX_DEFAULT ) { + pRegexKey[j].m_nColorIndex = color; _tcstowcs(pRegexKey[j].m_szKeyword, p, _countof(pRegexKey[j].m_szKeyword)); j++; + } else { + // 色指定が無効。無視する。 } - else - { /* 日本語名からインデックス番号に変換する */ - for(k = 0; k < COLORIDX_LAST; k++) - { - if( auto_strcmp(m_Types.m_ColorInfoArr[k].m_szName, &buff[11]) == 0 ) - { - pRegexKey[j].m_nColorIndex = k; - _tcstowcs(pRegexKey[j].m_szKeyword, p, _countof(pRegexKey[j].m_szKeyword)); - j++; - break; - } - } - } } } } @@ -215,7 +207,7 @@ { if( _tcscmp( m_Types.m_ColorInfoArr[k].m_szName, szColorIndex ) == 0 ) { - p = GetColorNameByIndex(k); + p = GetShortNameFromColorIndex( EColorIndexType(k) ); break; } } @@ -752,8 +744,6 @@ /* ダイアログデータの設定 正規表現キーワード */ void CPropTypes::SetData_Regex( HWND hwndDlg ) { - HWND hwndWork; - int i, j; LV_ITEM lvi; DWORD dwStyle; @@ -762,15 +752,17 @@ ::DlgItem_SetText( hwndDlg, IDC_EDIT_REGEX, _T("//k") ); /* 正規表現 */ /* 色種類のリスト */ - hwndWork = ::GetDlgItem( hwndDlg, IDC_COMBO_REGEX_COLOR ); - ::SendMessageAny( hwndWork, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0 ); /* コンボボックスを空にする */ - for( i = 0; i < COLORIDX_LAST; i++ ) + const HWND hwndColorComboBox = ::GetDlgItem( hwndDlg, IDC_COMBO_REGEX_COLOR ); + ::SendMessageAny( hwndColorComboBox, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0 ); /* コンボボックスを空にする */ + for( int i = 0; i < COLORIDX_LAST; i++ ) { - if ( 0 == (g_ColorAttributeArr[i].fAttribute & COLOR_ATTRIB_NO_BACK) ) // 2006.12.18 ryoji フラグ利用で簡素化 + if ( ! (g_ColorAttributeArr[i].fAttribute & COLOR_ATTRIB_NO_BACK) ) // 2006.12.18 ryoji フラグ利用で簡素化 { - j = ::SendMessage( hwndWork, CB_ADDSTRING, (WPARAM)0, (LPARAM)m_Types.m_ColorInfoArr[i].m_szName ); - if( m_Types.m_ColorInfoArr[i].m_nColorIdx == COLORIDX_REGEX1 ) - ::SendMessageAny( hwndWork, CB_SETCURSEL, (WPARAM)j, (LPARAM)0 ); /* コンボボックスのデフォルト選択 */ + int itemIndex = ::SendMessage( hwndColorComboBox, CB_ADDSTRING, (WPARAM)0, (LPARAM)m_Types.m_ColorInfoArr[i].m_szName ); + ::SendMessage( hwndColorComboBox, CB_SETITEMDATA, static_cast(itemIndex), static_cast(i) ); + if( m_Types.m_ColorInfoArr[i].m_nColorIdx == COLORIDX_REGEX1 ) { + ::SendMessageAny( hwndColorComboBox, CB_SETCURSEL, (WPARAM)itemIndex, (LPARAM)0 ); /* 正規表現キーワード1をデフォルトで選択 */ + } } } @@ -780,32 +772,33 @@ CheckDlgButton( hwndDlg, IDC_CHECK_REGEX, BST_UNCHECKED ); /* リスト */ - hwndWork = ::GetDlgItem( hwndDlg, IDC_LIST_REGEX ); - ListView_DeleteAllItems(hwndWork); /* リストを空にする */ + const HWND hwndRKList = ::GetDlgItem( hwndDlg, IDC_LIST_REGEX ); + ListView_DeleteAllItems(hwndRKList); /* リストを空にする */ /* 行選択 */ - dwStyle = (DWORD)::SendMessageAny( hwndWork, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0 ); + dwStyle = (DWORD)::SendMessageAny( hwndRKList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0 ); dwStyle |= LVS_EX_FULLROWSELECT; - ::SendMessageAny( hwndWork, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle ); + ::SendMessageAny( hwndRKList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle ); /* データ表示 */ - for(i = 0; i < MAX_REGEX_KEYWORD; i++) + for( int i = 0; i < MAX_REGEX_KEYWORD; i++ ) { if( m_Types.m_RegexKeywordArr[i].m_szKeyword[0] == L'\0' ) break; lvi.mask = LVIF_TEXT | LVIF_PARAM; - lvi.pszText = const_cast(to_tchar(m_Types.m_RegexKeywordArr[i].m_szKeyword)); lvi.iItem = i; lvi.iSubItem = 0; - lvi.lParam = 0; //m_Types.m_RegexKeywordArr[i].m_nColorIndex; - ListView_InsertItem( hwndWork, &lvi ); + lvi.pszText = const_cast(to_tchar(m_Types.m_RegexKeywordArr[i].m_szKeyword)); + lvi.lParam = 0; //static_cast(m_Types.m_RegexKeywordArr[i].m_nColorIndex); + ListView_InsertItem( hwndRKList, &lvi ); + lvi.mask = LVIF_TEXT; lvi.iItem = i; lvi.iSubItem = 1; lvi.pszText = m_Types.m_ColorInfoArr[m_Types.m_RegexKeywordArr[i].m_nColorIndex].m_szName; - ListView_SetItem( hwndWork, &lvi ); + ListView_SetItem( hwndRKList, &lvi ); } - ListView_SetItemState( hwndWork, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED ); + ListView_SetItemState( hwndRKList, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED ); return; } @@ -813,10 +806,6 @@ /* ダイアログデータの取得 正規表現キーワード */ int CPropTypes::GetData_Regex( HWND hwndDlg ) { - HWND hwndList; - int nIndex, i, j; - TCHAR szKeyWord[256], szColorIndex[256]; - //@@@ 2002.01.03 YAZAKI 最後に表示していたシートを正しく覚えていないバグ修正 // //自分のページ番号 // m_nPageNum = 3; @@ -828,34 +817,23 @@ m_Types.m_bUseRegexKeyword = false; //リストに登録されている情報を配列に取り込む - hwndList = GetDlgItem( hwndDlg, IDC_LIST_REGEX ); - nIndex = ListView_GetItemCount(hwndList); - for(i = 0; i < MAX_REGEX_KEYWORD; i++) - { - if( i < nIndex ) - { - szKeyWord[0] = _T('\0'); - szColorIndex[0] = _T('\0'); - ListView_GetItemText(hwndList, i, 0, szKeyWord, _countof(szKeyWord) ); - ListView_GetItemText(hwndList, i, 1, szColorIndex, _countof(szColorIndex)); - _tcstowcs(m_Types.m_RegexKeywordArr[i].m_szKeyword, szKeyWord, _countof(m_Types.m_RegexKeywordArr[i].m_szKeyword)); - //色指定文字列を番号に変換する - m_Types.m_RegexKeywordArr[i].m_nColorIndex = COLORIDX_REGEX1; - for(j = 0; j < COLORIDX_LAST; j++) - { - if(_tcscmp(m_Types.m_ColorInfoArr[j].m_szName, szColorIndex) == 0) - { - m_Types.m_RegexKeywordArr[i].m_nColorIndex = j; - break; - } - } - } - else //未登録部分はクリアする - { - m_Types.m_RegexKeywordArr[i].m_szKeyword[0] = L'\0'; - m_Types.m_RegexKeywordArr[i].m_nColorIndex = COLORIDX_REGEX1; - } + const HWND hwndList = GetDlgItem( hwndDlg, IDC_LIST_REGEX ); + const int itemCount = std::min( ListView_GetItemCount(hwndList), static_cast(MAX_REGEX_KEYWORD) ); + TCHAR szKeyword[256], szLongColorName[256]; + for( int i = 0; i < itemCount; ++i ) { + szKeyword[0] = _T('\0'); + szLongColorName[0] = _T('\0'); + ListView_GetItemText(hwndList, i, 0, szKeyword, _countof(szKeyword) ); + ListView_GetItemText(hwndList, i, 1, szLongColorName, _countof(szLongColorName)); + _tcstowcs(m_Types.m_RegexKeywordArr[i].m_szKeyword, szKeyword, _countof(m_Types.m_RegexKeywordArr[i].m_szKeyword)); + EColorIndexType color = GetColorIndexFromLongName( szLongColorName ); + m_Types.m_RegexKeywordArr[i].m_nColorIndex = color == COLORIDX_DEFAULT ? COLORIDX_TEXT : color; } + //未登録部分をクリアする + for( int i = itemCount; i < MAX_REGEX_KEYWORD; ++i ) { + m_Types.m_RegexKeywordArr[i].m_szKeyword[0] = L'\0'; + m_Types.m_RegexKeywordArr[i].m_nColorIndex = COLORIDX_REGEX1; + } //タイプ設定の変更があった m_Types.m_nRegexKeyMagicNumber++; Index: sakura_core/types/CPropTypes_P2_Color.cpp =================================================================== --- sakura_core/types/CPropTypes_P2_Color.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CPropTypes_P2_Color.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -11,7 +11,7 @@ #include "CDlgSameColor.h" #include "CDlgKeywordSelect.h" #include "util/shell.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" #include "env/CShareData_IO.h" using namespace std; @@ -982,7 +982,7 @@ valueEnd = szVertLine[offset] - '0' + valueEnd * 10; } if( valueEnd <= 0 ){ - valueEnd = MAXLINEKETAS; + valueEnd = static_cast(MAXLINEKETAS); } if( szVertLine[offset] != ')' ){ break; Index: sakura_core/types/CType_Html.cpp =================================================================== --- sakura_core/types/CType_Html.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Html.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -2,7 +2,7 @@ #include "types/CType.h" #include "doc/CDocOutline.h" #include "outline/CFuncInfoArr.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* HTML */ //Oct. 31, 2000 JEPRO VC++の生成するテキストファイルも読み込めるようにする Index: sakura_core/types/CPropTypes.cpp =================================================================== --- sakura_core/types/CPropTypes.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CPropTypes.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -21,7 +21,7 @@ #include "stdafx.h" #include "CPropTypes.h" #include "util/shell.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" using namespace std; Index: sakura_core/types/CType_Vb.cpp =================================================================== --- sakura_core/types/CType_Vb.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Vb.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -2,7 +2,7 @@ #include "types/CType.h" #include "doc/CDocOutline.h" #include "outline/CFuncInfoArr.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* Visual Basic */ //JUl. 10, 2001 JEPRO VB ユーザに贈る Index: sakura_core/types/CType.cpp =================================================================== --- sakura_core/types/CType.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,13 +1,12 @@ #include "stdafx.h" #include "CType.h" -#include "view/Colors/CColorStrategy.h" void _DefaultConfig(STypeConfig* pType); // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // // CTypeConfig // // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -STypeConfig* CTypeConfig::GetTypeConfig() +STypeConfig* CTypeConfig::GetTypeConfig() const { return &CDocTypeManager().GetTypeSetting(*this); } @@ -140,7 +139,7 @@ /************************/ pType->m_nTextWrapMethod = WRAP_SETTING_WIDTH; // テキストの折り返し方法 // 2008.05.30 nasukoji - pType->m_nMaxLineKetas = CLayoutInt(MAXLINEKETAS); /* 折り返し桁数 */ + pType->m_nMaxLineKetas = MAXLINEKETAS; /* 折り返し桁数 */ pType->m_nColmSpace = 0; /* 文字と文字の隙間 */ pType->m_nLineSpace = 1; /* 行間のすきま */ pType->m_nTabSpace = CLayoutInt(4); /* TABの文字数 */ @@ -190,7 +189,7 @@ for( int i = 0; i < COLORIDX_LAST; ++i ){ - GetDefaultColorInfo(&pType->m_ColorInfoArr[i],i); + GetDefaultColorInfo( pType->m_ColorInfoArr + i, EColorIndexType( i ) ); } pType->m_bLineNumIsCRLF = true; /* 行番号の表示 FALSE=折り返し単位/TRUE=改行単位 */ pType->m_nLineTermType = 1; /* 行番号区切り 0=なし 1=縦線 2=任意 */ Index: sakura_core/types/CType_Asm.cpp =================================================================== --- sakura_core/types/CType_Asm.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Asm.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -2,7 +2,7 @@ #include "types/CType.h" #include "doc/CDocOutline.h" #include "outline/CFuncInfoArr.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* アセンブラ */ // 2004.05.01 MIK/genta Index: sakura_core/types/CType_Java.cpp =================================================================== --- sakura_core/types/CType_Java.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Java.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -2,7 +2,7 @@ #include "types/CType.h" #include "doc/CDocOutline.h" #include "outline/CFuncInfoArr.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* Java */ void CType_Java::InitTypeConfigImp(STypeConfig* pType) Index: sakura_core/types/CType_Tex.cpp =================================================================== --- sakura_core/types/CType_Tex.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Tex.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -2,7 +2,7 @@ #include "types/CType.h" #include "doc/CDocOutline.h" #include "outline/CFuncInfoArr.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* TeX */ //Oct. 31, 2000 JEPRO TeX ユーザに贈る Index: sakura_core/types/CType_Perl.cpp =================================================================== --- sakura_core/types/CType_Perl.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Perl.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -2,7 +2,7 @@ #include "types/CType.h" #include "doc/CDocOutline.h" #include "outline/CFuncInfoArr.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* Perl */ //Jul. 08, 2001 JEPRO Perl ユーザに贈る Index: sakura_core/types/CPropTypes_P1_Screen.cpp =================================================================== --- sakura_core/types/CPropTypes_P1_Screen.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CPropTypes_P1_Screen.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -234,10 +234,10 @@ --nVal; } if( nVal < MINLINEKETAS ){ - nVal = MINLINEKETAS; + nVal = static_cast(MINLINEKETAS); } if( nVal > MAXLINEKETAS ){ - nVal = MAXLINEKETAS; + nVal = static_cast(MAXLINEKETAS); } ::SetDlgItemInt( hwndDlg, IDC_EDIT_MAXLINELEN, nVal, FALSE ); return TRUE; @@ -533,11 +533,11 @@ /* 折り返し桁数 */ m_Types.m_nMaxLineKetas = CLayoutInt(::GetDlgItemInt( hwndDlg, IDC_EDIT_MAXLINELEN, NULL, FALSE )); - if( m_Types.m_nMaxLineKetas < CLayoutInt(MINLINEKETAS) ){ - m_Types.m_nMaxLineKetas = CLayoutInt(MINLINEKETAS); + if( m_Types.m_nMaxLineKetas < MINLINEKETAS ){ + m_Types.m_nMaxLineKetas = MINLINEKETAS; } - if( m_Types.m_nMaxLineKetas > CLayoutInt(MAXLINEKETAS) ){ - m_Types.m_nMaxLineKetas = CLayoutInt(MAXLINEKETAS); + if( m_Types.m_nMaxLineKetas > MAXLINEKETAS ){ + m_Types.m_nMaxLineKetas = MAXLINEKETAS; } /* 文字の間隔 */ Index: sakura_core/types/CType_Pascal.cpp =================================================================== --- sakura_core/types/CType_Pascal.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Pascal.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,6 +1,6 @@ #include "stdafx.h" #include "types/CType.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* Pascal */ //Mar. 10, 2001 JEPRO 半角数値を色分け表示 Index: sakura_core/types/CDlgSameColor.cpp =================================================================== --- sakura_core/types/CDlgSameColor.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CDlgSameColor.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -33,7 +33,7 @@ #include "sakura.hh" #include "CDlgSameColor.h" #include "util/shell.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" static const DWORD p_helpids[] = { // 2006.10.10 ryoji IDOK, HIDOK_SAMECOLOR, // OK Index: sakura_core/types/CType_Ini.cpp =================================================================== --- sakura_core/types/CType_Ini.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Ini.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,6 +1,6 @@ #include "stdafx.h" #include "types/CType.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* 設定ファイル */ //Nov. 9, 2000 JEPRO Windows標準のini, inf, cnfファイルとsakuraキーワード設定ファイル.kwd, 色設定ファイル.col も読めるようにする Index: sakura_core/types/CTypeSupport.h =================================================================== --- sakura_core/types/CTypeSupport.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CTypeSupport.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -3,7 +3,7 @@ #include "view/CEditView.h" #include "env/CShareData.h" #include "doc/CEditDoc.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" //2007.08.28 kobake 追加 //!タイプサポートクラス @@ -14,9 +14,8 @@ public: CTypeSupport(const CEditView* pEditView,EColorIndexType eColorIdx) : m_pFontset(&pEditView->GetFontset()) - , m_nColorIdx(ToColorInfoArrIndex(eColorIdx)) + , m_nColorIdx(ActualColor(eColorIdx)) { - assert(0 <= m_nColorIdx); m_pTypes = &pEditView->m_pcEditDoc->m_cDocType.GetDocumentAttribute(); m_gr=NULL; Index: sakura_core/types/CType_Cpp.cpp =================================================================== --- sakura_core/types/CType_Cpp.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Cpp.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -3,7 +3,7 @@ #include "doc/CDocOutline.h" #include "outline/CFuncInfoArr.h" #include "COpeBlk.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" //!CPPキーワードで始まっていれば true inline bool IsHeadCppKeyword(const wchar_t* pData) Index: sakura_core/types/CType_Text.cpp =================================================================== --- sakura_core/types/CType_Text.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Text.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -2,7 +2,7 @@ #include "types/CType.h" #include "doc/CDocOutline.h" #include "outline/CFuncInfoArr.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* テキスト */ //Sep. 20, 2000 JEPRO テキストの規定値を80→120に変更(不具合一覧.txtがある程度読みやすい桁数) Index: sakura_core/types/CType_Rich.cpp =================================================================== --- sakura_core/types/CType_Rich.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType_Rich.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,6 +1,6 @@ #include "stdafx.h" #include "types/CType.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* リッチテキスト */ //JUl. 10, 2001 JEPRO WinHelp作るのにいるケンね Index: sakura_core/types/CType.h =================================================================== --- sakura_core/types/CType.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/types/CType.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,5 +1,6 @@ #pragma once +#include "CRegexKeyword.h" //struct RegexKeywordInfo #include "doc/CDocTypeSetting.h" #include "config/maxdata.h" //MAX_REGEX_KEYWORD #include "doc/CLineComment.h" @@ -58,13 +59,13 @@ int m_nKeyWordSetIdx[MAX_KEYWORDSET_PER_TYPE]; /*!< キーワードセット */ CLineComment m_cLineComment; /*!< 行コメントデリミタ */ //@@@ 2002.09.22 YAZAKI - CBlockComment m_cBlockComments[2]; /*!< ブロックコメントデリミタ */ //@@@ 2002.09.22 YAZAKI + CBlockComment m_cBlockComments[BLOCKCOMMENT_NUM]; /*!< ブロックコメントデリミタ */ //@@@ 2002.09.22 YAZAKI int m_nStringType; /*!< 文字列区切り記号エスケープ方法 0=[\"][\'] 1=[""][''] */ wchar_t m_szIndentChars[64]; /*!< その他のインデント対象文字 */ + ColorInfo m_ColorInfoArr[COLORIDX_LAST]; /*!< 色設定配列 */ int m_nColorInfoArrNum; /*!< 色設定配列の有効数 */ - ColorInfo m_ColorInfoArr[64]; /*!< 色設定配列 */ bool m_bLineNumIsCRLF; /*!< 行番号の表示 FALSE=折り返し単位/TRUE=改行単位 */ int m_nLineTermType; /*!< 行番号区切り 0=なし 1=縦線 2=任意 */ @@ -164,7 +165,7 @@ //共有データへの簡易アクセサ STypeConfig* operator->(){ return GetTypeConfig(); } - STypeConfig* GetTypeConfig(); + STypeConfig* GetTypeConfig() const; private: int m_nType; }; Index: sakura_core/env/CShareData.cpp =================================================================== --- sakura_core/env/CShareData.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/env/CShareData.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -361,8 +361,8 @@ m_pShareData->m_Common.m_sWindow.m_nWinPosX = CW_USEDEFAULT; m_pShareData->m_Common.m_sWindow.m_nWinPosY = 0; - m_pShareData->m_Common.m_sGeneral.m_bUseTaskTray = TRUE; /* タスクトレイのアイコンを使う */ - m_pShareData->m_Common.m_sGeneral.m_bStayTaskTray = TRUE; /* タスクトレイのアイコンを常駐 */ + m_pShareData->m_Common.m_sGeneral.m_bUseTaskTray = FALSE; /* タスクトレイのアイコンを使う */ + m_pShareData->m_Common.m_sGeneral.m_bStayTaskTray = FALSE; /* タスクトレイのアイコンを常駐 */ m_pShareData->m_Common.m_sGeneral.m_wTrayMenuHotKeyCode = L'Z'; /* タスクトレイ左クリックメニュー キー */ m_pShareData->m_Common.m_sGeneral.m_wTrayMenuHotKeyMods = HOTKEYF_ALT | HOTKEYF_CONTROL; /* タスクトレイ左クリックメニュー キー */ m_pShareData->m_Common.m_sEdit.m_bUseOLE_DragDrop = TRUE; /* OLEによるドラッグ & ドロップを使う */ Index: sakura_core/env/CDocTypeManager.h =================================================================== --- sakura_core/env/CDocTypeManager.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/env/CDocTypeManager.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -9,20 +9,13 @@ //! ドキュメントタイプ管理 class CDocTypeManager{ public: - CDocTypeManager() - { - m_pShareData = &GetDllShareData(); - } CTypeConfig GetDocumentTypeOfPath( const TCHAR* pszFilePath ); /* ファイルパスを渡して、ドキュメントタイプ(数値)を取得する */ CTypeConfig GetDocumentTypeOfExt( const TCHAR* pszExt ); /* 拡張子を渡して、ドキュメントタイプ(数値)を取得する */ STypeConfig& GetTypeSetting(CTypeConfig cDocumentType) { int n = cDocumentType.GetIndex(); - assert(n>=0 && n<_countof(m_pShareData->m_Types)); - return m_pShareData->m_Types[n]; + assert(n>=0 && n<_countof(GetDllShareData().m_Types)); + return GetDllShareData().m_Types[n]; } - -private: - DLLSHAREDATA* m_pShareData; }; Index: sakura_core/env/CShareData_IO.cpp =================================================================== --- sakura_core/env/CShareData_IO.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/env/CShareData_IO.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,10 +1,10 @@ //2008.XX.XX kobake CShareDataから分離 #include "stdafx.h" +#include "util/window.h" +#include "util/string_ex2.h" #include "env/CShareData_IO.h" -#include "util/string_ex2.h" -#include "util/window.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" /* 共有データのロード */ bool CShareData_IO::LoadShareData() @@ -1261,9 +1261,15 @@ if( p ) { *p = LTEXT('\0'); - types.m_RegexKeywordArr[j].m_nColorIndex = GetColorIndexByName(to_tchar(szKeyData)); //@@@ 2002.04.30 - if( types.m_RegexKeywordArr[j].m_nColorIndex == -1 ) //名前でない - types.m_RegexKeywordArr[j].m_nColorIndex = _wtoi(szKeyData); + EColorIndexType color = GetColorIndexFromShortName(to_tchar(szKeyData)); //@@@ 2002.04.30 + if( color == COLORIDX_DEFAULT ) { // 有効な短い色名でなかったら + color = GetColorIndexFromLongName(to_tchar(szKeyData)); // 日本語の色名? + } + if( color == COLORIDX_DEFAULT ) { + int colorIndex = _wtoi(szKeyData); // 番号? + color = 0 <= colorIndex && colorIndex < COLORIDX_LAST ? EColorIndexType(colorIndex) : COLORIDX_TEXT; + } + types.m_RegexKeywordArr[j].m_nColorIndex = color; p++; wcscpy(types.m_RegexKeywordArr[j].m_szKeyword, p); if( types.m_RegexKeywordArr[j].m_nColorIndex < 0 @@ -1278,7 +1284,7 @@ else if(wcslen(types.m_RegexKeywordArr[j].m_szKeyword)) { auto_sprintf( szKeyData, LTEXT("%ls,%ls"), - GetColorNameByIndex( types.m_RegexKeywordArr[j].m_nColorIndex ), + GetShortNameFromColorIndex( types.m_RegexKeywordArr[j].m_nColorIndex ), types.m_RegexKeywordArr[j].m_szKeyword); cProfile.IOProfileData( pszSecName, szKeyName, MakeStringBufferW(szKeyData) ); } @@ -1559,7 +1565,7 @@ int j; for( j = 0; j < COLORIDX_LAST; ++j ){ static const WCHAR* pszForm = LTEXT("%d,%d,%06x,%06x,%d"); - auto_sprintf( szKeyName, LTEXT("C[%ts]"), g_ColorAttributeArr[j].szName ); //Stonee, 2001/01/12, 2001/01/15 + auto_sprintf( szKeyName, LTEXT("C[%ts]"), g_ColorAttributeArr[j].szShortName ); //Stonee, 2001/01/12, 2001/01/15 if( pcProfile->IsReadingMode() ){ if( pcProfile->IOProfileData( pszSecName, szKeyName, MakeStringBufferW(szKeyData) ) ){ pColorInfoArr[j].m_bUnderLine = false; Index: sakura_core/env/DLLSHAREDATA.h =================================================================== --- sakura_core/env/DLLSHAREDATA.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/env/DLLSHAREDATA.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -65,7 +65,7 @@ struct DLLSHAREDATA{ void OnInit(); - + // -- -- バージョン -- -- // /*! データ構造 Version // Oct. 27, 2000 genta Index: sakura_core/CKeyWordSetMgr.h =================================================================== --- sakura_core/CKeyWordSetMgr.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/CKeyWordSetMgr.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -114,7 +114,7 @@ /// @name 検索 //int SearchKeyWord( int , const char*, int ); /* n番目のセットから指定キーワードをサーチ 無いときは-1を返す */ BOOL IsModify( CKeyWordSetMgr&, BOOL* pnModifyFlagArr ); /* 変更状況を調査 */ - int SearchKeyWord2( int , const wchar_t*, int ); /* n番目のセットから指定キーワードをバイナリサーチ 無いときは-1を返す */ //MIK + int SearchKeyWord2( const int iKwdSet , const wchar_t* const szTestword, const size_t testwordLength ); /* n番目のセットから指定キーワードをバイナリサーチ 無いときは-1を返す */ //MIK //@} // From Here 2004.07.29 Moca 追加 可変長記憶 Index: sakura_core/basis/CStrictInteger.h =================================================================== --- sakura_core/basis/CStrictInteger.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/basis/CStrictInteger.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -30,6 +30,7 @@ */ #pragma once +#include "basis/primitive.h" //int以外の整数型もintにキャストして扱う #define STRICTINT_OTHER_TYPE_AS_INT(TYPE) \ @@ -77,7 +78,9 @@ CStrictInteger(const Me& rhs){ m_value=rhs.m_value; } //intからの変換は、「明示的に指定したときのみ」可能 - explicit CStrictInteger(int value){ m_value=value; } + /*explicit*/ CStrictInteger(int value){ m_value=value; } + // キャストの乱用につながり好ましくない。intを経由して、種類の違う + // StrictIntegerが相互変換できてしまうことさえ避けられればよい。 //算術演算子 (加算、減算は同クラス同士でしか許さない) Me& operator += (const Me& rhs) { m_value += rhs.m_value; return *this; } Index: sakura_core/basis/CStrictPoint.h =================================================================== --- sakura_core/basis/CStrictPoint.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/basis/CStrictPoint.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -25,6 +25,8 @@ CStrictPoint(int _x,int _y){ x=SuperIntType(_x); y=SuperIntType(_y); } #ifdef USE_STRICT_INT CStrictPoint(IntType _x,IntType _y){ x=SuperIntType(_x); y=SuperIntType(_y); } + CStrictPoint(int _x,IntType _y){ x=SuperIntType(_x); y=SuperIntType(_y); } + CStrictPoint(IntType _x,int _y){ x=SuperIntType(_x); y=SuperIntType(_y); } #endif CStrictPoint(const SUPER& rhs){ x=rhs.x; y=rhs.y; } @@ -73,7 +75,7 @@ return x<0 || y<0; } - //! x,y どちらも自然数であれば true + //! x,y どちらも0以上であれば true bool BothNatural() const { return x>=0 && y>=0; Index: sakura_core/docplus/CDiffManager.cpp =================================================================== --- sakura_core/docplus/CDiffManager.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/docplus/CDiffManager.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,6 +1,6 @@ #include "stdafx.h" #include "docplus/CDiffManager.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" #include "types/CTypeSupport.h" // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // Index: sakura_core/CSearchAgent.h =================================================================== --- sakura_core/CSearchAgent.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/CSearchAgent.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -10,7 +10,7 @@ const wchar_t* pszPattern, int nPatternLen, int* pnCharCharsArr, - bool bLoHiCase + bool bCaseSensitive ); // 検索条件の情報 Index: sakura_core/window/CEditWnd.cpp =================================================================== --- sakura_core/window/CEditWnd.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/window/CEditWnd.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -4274,14 +4274,28 @@ */ void CEditWnd::RedrawAllViews( CEditView* pcViewExclude ) { - int i; + int i, j, tmp; CEditView* pcView; + int sortedViewIndices[ _countof( m_pcEditViewArr ) ]; + for( i = 0; i < _countof( m_pcEditViewArr ); ++i ) { + sortedViewIndices[i] = i; + } + for( i = 0; i < _countof( m_pcEditViewArr ) - 1; ++i ) { + for( j = i; j < _countof( m_pcEditViewArr ) - 1; ++j ) { + if( m_pcEditViewArr[sortedViewIndices[j+1]]->GetTextArea().GetViewTopLine() + < m_pcEditViewArr[sortedViewIndices[j]]->GetTextArea().GetViewTopLine() + ) { + tmp = sortedViewIndices[j]; sortedViewIndices[j] = sortedViewIndices[j+1]; sortedViewIndices[j+1] = tmp; + } + } + } for( i = 0; i < _countof( m_pcEditViewArr ); i++ ){ - pcView = m_pcEditViewArr[i]; + j = sortedViewIndices[i]; + pcView = m_pcEditViewArr[j]; if( pcView == pcViewExclude ) continue; - if( i == m_nActivePaneIndex ){ + if( j == m_nActivePaneIndex ){ pcView->RedrawAll(); }else{ pcView->Redraw(); Index: sakura_core/CSearchAgent.cpp =================================================================== --- sakura_core/CSearchAgent.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/CSearchAgent.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,4 +1,6 @@ #include "stdafx.h" +#include +#include #include "CSearchAgent.h" #include "parse/CWordParse.h" #include "dlg/CDlgCancel.h" @@ -196,7 +198,7 @@ */ /* 見つからない場合は0を返す */ int CSearchAgent::SearchWord( - CLogicPoint ptSerachBegin, //!< 検索開始位置 + CLogicPoint ptSearchBegin, //!< 検索開始位置 const wchar_t* pszPattern, //!< 検索条件 ESearchDirection eDirection, //!< 検索方向 const SSearchOption& sSearchOption, //!< 検索オプション @@ -229,65 +231,50 @@ //正規表現 if( sSearchOption.bRegularExp ){ - nLinePos = ptSerachBegin.GetY2(); // 検索行=検索開始行 + nLinePos = ptSearchBegin.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:この行でマッチ位置なし - while( 1 ){ - 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; + CLogicInt matchIndex = -1; // 非負かどうかでマッチの有無判定も兼ねる。 + CLogicInt matchLastIndex = -1; + for( ++nLinePos; pDocLine; pDocLine = pDocLine->GetPrevLine() ) { + --nLinePos; + const wchar_t* const szLine = pDocLine->GetPtr(); + const CLogicInt lineLen = pDocLine->GetLengthWithEOL(); + const CLogicInt maxLastIndex = nLinePos == ptSearchBegin.GetY2() ? ptSearchBegin.GetX2() : lineLen; // マッチがここを超えたらそれは無効。 + for( CLogicInt pos = 0; pos <= maxLastIndex; pos += std::max( CLogicInt(1), CNativeW::GetSizeOfChar( szLine, lineLen, pos ) ) ) { + if( pRegexp->Match( szLine, lineLen, pos ) && pRegexp->GetLastIndex() <= maxLastIndex ) { + // マッチ後端が maxLastIndexに一番近くて、範囲が一番広いものを最終結果とする。 + if( matchLastIndex < pRegexp->GetLastIndex() ) { + matchIndex = pRegexp->GetIndex(); + matchLastIndex = pRegexp->GetLastIndex(); + if( matchLastIndex == maxLastIndex ) { + break; + } } } else { - // マッチしなかった - // すでにマッチした位置があれば、それを返し、なければ前の行へ break; } } - - if ( -1 != nHitPosOld ) { - // この行でマッチした位置が存在するので、この行で検索終了 - pMatchRange->SetFromX( nHitPosOld ); // マッチ位置from - pMatchRange->SetToX ( nIdxPosOld ); // マッチ位置to + if( 0 <= matchIndex && 0 <= matchLastIndex ) { break; - } else { - // この行でマッチした位置が存在しないので、前の行を検索へ - nLinePos--; - pDocLine = pDocLine->GetPrevLine(); - nIdxPos = 0; - if( NULL != pDocLine ){ - nHitTo = pDocLine->GetLengthWithEOL() + 1; // 前の行のNULL文字(\0)にもマッチさせるために+1 2003.05.16 かろと - } } } + if( 0 <= matchIndex && 0 <= matchLastIndex ) { + pMatchRange->SetXs( matchIndex, matchLastIndex ); + } else { + pDocLine = NULL; + } } //後方検索 else { // // 後方検索(正規表現) // - nIdxPos = ptSerachBegin.x; + nIdxPos = ptSearchBegin.x; while( NULL != pDocLine ){ pLine = pDocLine->GetDocLineStrWithEOL( &nLineLen ); if( nIdxPos <= pDocLine->GetLengthWithoutEOL() @@ -319,6 +306,23 @@ } //単語のみ検索 else if( sSearchOption.bWordOnly ){ + // 検索語を単語に分割して searchWordsに格納する。 + std::vector > searchWords; // 単語の開始位置と長さの配列。 + for( CLogicInt pos = 0; pos < nPatternLen; ) { + CLogicInt begin, end; // 検索語に含まれる単語?の posを基準とした相対位置。WhereCurrentWord_2()の仕様では空白文字列も単語に含まれる。 + if( CWordParse::WhereCurrentWord_2( pszPattern + pos, nPatternLen - pos, 0, &begin, &end, NULL, NULL ) + && begin == 0 && begin < end + ) { + if( ! WCODE::IsWordDelimiter( pszPattern[pos] ) ) { + // pszPattern[pos]...pszPattern[pos + end] が検索語に含まれる単語。 + searchWords.push_back( std::make_pair( pszPattern + pos, end ) ); + } + pos += end; + } else { + pos += std::max( CLogicInt(1), CNativeW::GetSizeOfChar( pszPattern, nPatternLen, pos ) ); + } + } + /* 2001/06/23 Norio Nakatani 単語単位の検索を試験的に実装。単語はWhereCurrentWord()で判別してますので、 @@ -327,29 +331,31 @@ // 前方検索 if( eDirection == SEARCH_BACKWARD ){ - nLinePos = ptSerachBegin.GetY2(); + nLinePos = ptSearchBegin.GetY2(); pDocLine = m_pcDocLineMgr->GetLine( nLinePos ); CLogicInt nNextWordFrom; CLogicInt nNextWordFrom2; CLogicInt nNextWordTo2; CLogicInt nWork; - nNextWordFrom = ptSerachBegin.GetX2(); + nNextWordFrom = ptSearchBegin.GetX2(); while( NULL != pDocLine ){ if( PrevOrNextWord( nLinePos, nNextWordFrom, &nWork, TRUE, FALSE ) ){ nNextWordFrom = nWork; if( WhereCurrentWord( nLinePos, nNextWordFrom, &nNextWordFrom2, &nNextWordTo2 , NULL, NULL ) ){ - if( nPatternLen == nNextWordTo2 - nNextWordFrom2 ){ - const wchar_t* pData = pDocLine->GetPtr(); // 2002/2/10 aroka CMemory変更 - /* 1==大文字小文字の区別 */ - if( (!sSearchOption.bLoHiCase && 0 == auto_memicmp( &(pData[nNextWordFrom2]) , pszPattern, nPatternLen ) ) || - (sSearchOption.bLoHiCase && 0 == auto_memcmp( &(pData[nNextWordFrom2]) , pszPattern, nPatternLen ) ) - ){ - pMatchRange->SetFromY(nLinePos); // マッチ行 - pMatchRange->SetToY (nLinePos); // マッチ行 - pMatchRange->SetFromX(nNextWordFrom2); // マッチ位置from - pMatchRange->SetToX (pMatchRange->GetFrom().x + nPatternLen);// マッチ位置to - nRetVal = 1; - goto end_of_func; + for( unsigned iSW = 0; iSW < searchWords.size(); ++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; @@ -368,27 +374,29 @@ } // 後方検索 else{ - nLinePos = ptSerachBegin.GetY2(); + nLinePos = ptSearchBegin.GetY2(); pDocLine = m_pcDocLineMgr->GetLine( nLinePos ); CLogicInt nNextWordFrom; CLogicInt nNextWordFrom2; CLogicInt nNextWordTo2; - nNextWordFrom = ptSerachBegin.GetX2(); + nNextWordFrom = ptSearchBegin.GetX2(); while( NULL != pDocLine ){ if( WhereCurrentWord( nLinePos, nNextWordFrom, &nNextWordFrom2, &nNextWordTo2 , NULL, NULL ) ){ - if( nPatternLen == nNextWordTo2 - nNextWordFrom2 ){ - const wchar_t* pData = pDocLine->GetPtr(); // 2002/2/10 aroka CMemory変更 - /* 1==大文字小文字の区別 */ - if( (!sSearchOption.bLoHiCase && 0 == auto_memicmp( &(pData[nNextWordFrom2]) , pszPattern, nPatternLen ) ) || - (sSearchOption.bLoHiCase && 0 == auto_memcmp( &(pData[nNextWordFrom2]) , pszPattern, nPatternLen ) ) - ){ - pMatchRange->SetFromY(nLinePos); // マッチ行 - pMatchRange->SetToY (nLinePos); // マッチ行 - pMatchRange->SetFromX(nNextWordFrom2); // マッチ位置from - pMatchRange->SetToX (pMatchRange->GetFrom().x + nPatternLen);// マッチ位置to - nRetVal = 1; - goto end_of_func; + for( unsigned iSW = 0; iSW < searchWords.size(); ++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; + } } } /* 現在位置の左右の単語の先頭位置を調べる */ @@ -410,8 +418,8 @@ else{ //前方検索 if( eDirection == SEARCH_BACKWARD ){ - nLinePos = ptSerachBegin.GetY2(); - nHitTo = ptSerachBegin.x; + nLinePos = ptSearchBegin.GetY2(); + nHitTo = ptSearchBegin.x; nIdxPos = 0; pDocLine = m_pcDocLineMgr->GetLine( nLinePos ); @@ -470,8 +478,8 @@ } //後方検索 else{ - nIdxPos = ptSerachBegin.x; - nLinePos = ptSerachBegin.GetY2(); + nIdxPos = ptSearchBegin.x; + nLinePos = ptSearchBegin.GetY2(); pDocLine = m_pcDocLineMgr->GetLine( nLinePos ); while( NULL != pDocLine ){ pLine = pDocLine->GetDocLineStrWithEOL( &nLineLen ); Index: sakura_core/CViewCommander.cpp =================================================================== --- sakura_core/CViewCommander.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/CViewCommander.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -2949,157 +2949,143 @@ /* 前を検索 */ void CViewCommander::Command_SEARCH_PREV( bool bReDraw, HWND hwndParent ) { - bool bSelecting; - bool bSelectingLock_Old; - bool bFound = false; - bool bRedo = false; // hor - CLayoutInt nLineNumOld; - CLogicInt nIdxOld; - const CLayout* pcLayout = NULL; - CLayoutInt nLineNum; - CLogicInt nIdx; - - CLayoutRange sRangeA; - sRangeA.Set(GetCaret().GetCaretLayoutPos()); - - CLayoutRange sSelectBgn_Old; - CLayoutRange sSelect_Old; - - // bFlag1 = FALSE; - bSelecting = FALSE; if( L'\0' == GetDllShareData().m_sSearchKeywords.m_aSearchKeys[0][0] ){ - goto end_of_func; + return; // 検索文字列が空だった。 } - if( m_pCommanderView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - sSelectBgn_Old = m_pCommanderView->GetSelectionInfo().m_sSelectBgn; //範囲選択(原点) - sSelect_Old = GetSelect(); - - bSelectingLock_Old = m_pCommanderView->GetSelectionInfo().m_bSelectingLock; - - /* 矩形範囲選択中か */ - if( !m_pCommanderView->GetSelectionInfo().IsBoxSelecting() && TRUE == m_pCommanderView->GetSelectionInfo().m_bSelectingLock ){ /* 選択状態のロック */ - bSelecting = TRUE; + + // マッチ結果で選択範囲を置き換えるか、既存の範囲を拡張(縮小)するか。 + const bool preserveCurrentSelection = m_pCommanderView->GetSelectionInfo().IsTextSelected() + && m_pCommanderView->GetSelectionInfo().m_bSelectingLock + && ! m_pCommanderView->GetSelectionInfo().IsBoxSelecting(); + + // 検索開始位置( レイアウト行、レイアウト行内の文字数でのオフセット )をキャレットの位置から決定する。 + struct SearchPos { + CLayoutInt y ; + CLogicInt x; ///< 文字(wchar_t)数でのオフセットなので CLayoutIntではない。 + } searchPos = { -1, -1 }; + const CLayoutPoint& caretPos = GetCaret().GetCaretLayoutPos(); + const CLayout* pLayout = GetDocument()->m_cLayoutMgr.SearchLineByLayoutY( caretPos.GetY2() ); + if( pLayout ) { + searchPos.y = caretPos.GetY2(); + /* 指定された桁に対応する行のデータ内の位置を調べる */ + searchPos.x = m_pCommanderView->LineColmnToIndex( pLayout, caretPos.GetX2() ); + } else if( 0 < caretPos.GetY2() ) { // pLayoutが NULLとなるのは、[EOF]から前検索した場合。1行前の行末からの検索にする。 + pLayout = GetDocument()->m_cLayoutMgr.SearchLineByLayoutY( caretPos.GetY2() - 1 ); + if( pLayout ) { + searchPos.y = caretPos.GetY2() - 1; + // カーソル左移動はやめて nIdxは行の長さとしないと[EOF]から改行を前検索した時に最後の改行を検索できない 2003.05.04 かろと + searchPos.x = CLogicInt( pLayout->GetDocLineRef()->GetLengthWithEOL() + 1 ); // 行末のヌル文字(\0)にマッチさせるために+1 2003.05.16 かろと + // 行文字列末尾のヌル文字は文字列の内部表現に過ぎない(編集テキストの一部ではない)が、マッチさせる必要はある? } - else{ - /* 現在の選択範囲を非選択状態に戻す */ - m_pCommanderView->GetSelectionInfo().DisableSelectArea( bReDraw ); - } } - nLineNum = GetCaret().GetCaretLayoutPos().GetY2(); - pcLayout = GetDocument()->m_cLayoutMgr.SearchLineByLayoutY( nLineNum ); + // 2002.01.16 hor + if( ! m_pCommanderView->ChangeCurRegexp() ) { + return; // パターン検索だったが正規表現ライブラリが利用可能でなかった。 + } + this->m_pCommanderView->lastSearchInfo.pos = CLogicPoint( -1, -1 ); - if( NULL == pcLayout ){ - // pcLayoutはNULLとなるのは、[EOF]から前検索した場合 - // 1行前に移動する処理 - nLineNum--; - if( nLineNum < 0 ){ - goto end_of_func; + /* 現在位置より前の位置を検索する */ + bool found = false; + CLogicRange matchLogicRange = CLogicRange( CLogicPoint( -1, -1 ), CLogicPoint( -1, -1 ) ); + CLayoutRange matchLayoutRange = CLayoutRange( CLayoutPoint( -1, -1 ), CLayoutPoint( -1, -1 ) ); + const SearchPos originalSearchPos = searchPos; + if( pLayout ) { + bool retried = false; ///< 末尾から再検索したかどうか。 + for(;;) { + found = 0 != GetDocument()->m_cLayoutMgr.SearchWord( + searchPos.y, searchPos.x, // 検索開始位置 + m_pCommanderView->m_szCurSrchKey, // 検索条件 + SEARCH_BACKWARD, // 0==前方検索 1==後方検索 + m_pCommanderView->m_sCurSearchOption, // 検索オプション + &matchLayoutRange, // マッチレイアウト範囲 + &m_pCommanderView->m_CurRegexp // 正規表現コンパイルデータ + ); + if( retried ) { + break; + } + if( ! found && GetDllShareData().m_Common.m_sSearch.m_bSearchAll ) { + // From Here 2002.01.26 hor 見つからなかったので末尾から再検索する。 + searchPos.y = GetDocument()->m_cLayoutMgr.GetLineCount() - 1; + searchPos.x = static_cast( MAXLINEKETAS ); // とにかく大きければよい。 + retried = true; + continue; + } + if( found ) { + this->GetDocument()->m_cLayoutMgr.LayoutToLogic( matchLayoutRange, &matchLogicRange ); + + // 検索開始位置での幅0マッチはなかったことにして一つ前から探す。 + if( matchLayoutRange.GetFrom() == matchLayoutRange.GetTo() + && matchLayoutRange.GetFrom().GetY2() == originalSearchPos.y + && matchLogicRange.GetFrom().GetX2() == originalSearchPos.x + ) { + searchPos.x -= 1; + found = false; + continue; + } + } + break; } - pcLayout = GetDocument()->m_cLayoutMgr.SearchLineByLayoutY( nLineNum ); - if( NULL == pcLayout ){ - goto end_of_func; - } - // カーソル左移動はやめて nIdxは行の長さとしないと[EOF]から改行を前検索した時に最後の改行を検索できない 2003.05.04 かろと - CLayout* pCLayout = GetDocument()->m_cLayoutMgr.SearchLineByLayoutY( nLineNum ); - nIdx = CLogicInt(pCLayout->GetDocLineRef()->GetLengthWithEOL() + 1); // 行末のヌル文字(\0)にマッチさせるために+1 2003.05.16 かろと - } else { - /* 指定された桁に対応する行のデータ内の位置を調べる */ - nIdx = m_pCommanderView->LineColmnToIndex( pcLayout, GetCaret().GetCaretLayoutPos().GetX2() ); } - // 2002.01.16 hor - // 共通部分のくくりだし - if(!m_pCommanderView->ChangeCurRegexp())return; - bRedo = TRUE; // hor - nLineNumOld = nLineNum; // hor - nIdxOld = nIdx; // hor -re_do:; // hor - /* 現在位置より前の位置を検索する */ - if( GetDocument()->m_cLayoutMgr.SearchWord( - nLineNum, // 検索開始レイアウト行 - nIdx, // 検索開始データ位置 - m_pCommanderView->m_szCurSrchKey, // 検索条件 - SEARCH_BACKWARD, // 0==前方検索 1==後方検索 - m_pCommanderView->m_sCurSearchOption, // 検索オプション - &sRangeA, // マッチレイアウト範囲 - &m_pCommanderView->m_CurRegexp // 正規表現コンパイルデータ - ) ){ - if( bSelecting ){ + if( found ) { + this->GetDocument()->m_cLayoutMgr.LayoutToLogic( matchLayoutRange, &matchLogicRange ); + + // 検索結果により選択範囲を更新する。 + if( preserveCurrentSelection ) { /* 現在のカーソル位置によって選択範囲を変更 */ - m_pCommanderView->GetSelectionInfo().ChangeSelectAreaByCurrentCursor( sRangeA.GetFrom() ); - m_pCommanderView->GetSelectionInfo().m_bSelectingLock = bSelectingLock_Old; /* 選択状態のロック */ - }else{ - /* 選択範囲の変更 */ + m_pCommanderView->GetSelectionInfo().ChangeSelectAreaByCurrentCursor( matchLayoutRange.GetFrom() ); + } else { + /* マッチ範囲を選択する */ // 2005.06.24 Moca - m_pCommanderView->GetSelectionInfo().SetSelectArea( sRangeA ); - + m_pCommanderView->GetSelectionInfo().DisableSelectArea( bReDraw ); + m_pCommanderView->GetSelectionInfo().SetSelectArea( matchLayoutRange ); if( bReDraw ){ - /* 選択領域描画 */ m_pCommanderView->GetSelectionInfo().DrawSelectArea(); } } + /* カーソル移動 */ // Sep. 8, 2000 genta m_pCommanderView->AddCurrentLineToHistory(); - GetCaret().MoveCursor( sRangeA.GetFrom(), bReDraw ); + GetCaret().MoveCursor( matchLayoutRange.GetFrom(), bReDraw ); GetCaret().m_nCaretPosX_Prev = GetCaret().GetCaretLayoutPos().GetX2(); - bFound = TRUE; - }else{ + + if( originalSearchPos.y < searchPos.y + || originalSearchPos.y == searchPos.y && originalSearchPos.x < searchPos.x + ) { + m_pCommanderView->SendStatusMessage(_T("▲末尾から再検索しました")); + } + + // ハイライトのために検索結果の頭の位置を保存。 + this->m_pCommanderView->lastSearchInfo.pos = matchLogicRange.GetFrom(); + } else { /* フォーカス移動時の再描画 */ // m_pCommanderView->RedrawAll(); hor コメント化 - if( m_pCommanderView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - /* 現在の選択範囲を非選択状態に戻す */ + + // 範囲選択をキャンセル。 + if( ! preserveCurrentSelection ) { m_pCommanderView->GetSelectionInfo().DisableSelectArea( bReDraw ); } - if( bSelecting ){ - m_pCommanderView->GetSelectionInfo().m_bSelectingLock = bSelectingLock_Old; /* 選択状態のロック */ - /* 選択範囲の変更 */ - m_pCommanderView->GetSelectionInfo().m_sSelectBgn = sSelectBgn_Old; - GetSelect() = sSelect_Old; - /* カーソル移動 */ - GetCaret().MoveCursor( sRangeA.GetFrom(), bReDraw ); - GetCaret().m_nCaretPosX_Prev = GetCaret().GetCaretLayoutPos().GetX2(); - /* 選択領域描画 */ - m_pCommanderView->GetSelectionInfo().DrawSelectArea(); - } - } -end_of_func:; -// From Here 2002.01.26 hor 先頭(末尾)から再検索 - if(GetDllShareData().m_Common.m_sSearch.m_bSearchAll){ - if(!bFound && // 見つからなかった - bRedo // 最初の検索 - ){ - nLineNum=GetDocument()->m_cLayoutMgr.GetLineCount()-CLayoutInt(1); - nIdx=CLogicInt(MAXLINEKETAS); - bRedo=FALSE; - goto re_do; // 末尾から再検索 - } - } - if(bFound){ - if((nLineNumOld < nLineNum)||(nLineNumOld == nLineNum && nIdxOld < nIdx)) - m_pCommanderView->SendStatusMessage(_T("▲末尾から再検索しました")); - }else{ m_pCommanderView->SendStatusMessage(_T("△見つかりませんでした")); -// if( !bFound ){ -// To Here 2002.01.26 hor ErrorBeep(); - if( bReDraw && - GetDllShareData().m_Common.m_sSearch.m_bNOTIFYNOTFOUND /* 検索/置換 見つからないときメッセージを表示 */ - ){ - if( NULL == hwndParent ){ - hwndParent = m_pCommanderView->GetHwnd(); - } +// To Here 2002.01.26 hor + if( bReDraw && GetDllShareData().m_Common.m_sSearch.m_bNOTIFYNOTFOUND ) { /* 検索/置換 見つからないときメッセージを表示 */ InfoMessage( - hwndParent, + hwndParent ? hwndParent : m_pCommanderView->GetHwnd(), _T("前方(↑) に文字列 '%ls' が1つも見つかりません。"), //Jan. 25, 2001 jepro メッセージを若干変更 m_pCommanderView->m_szCurSrchKey ); } } - return; + if( this->m_pCommanderView->pColorML_Found ) { + this->m_pCommanderView->pColorML_Found->SearchConditionChanged(); // 検索条件が変わったので以前のハイライト情報をリセット。 + } + if( this->m_pCommanderView->m_bCurSrchKeyMark ) { + this->m_pCommanderView->Redraw(); + } } @@ -3206,10 +3192,11 @@ // 2004.05.30 Moca CEditViewの現在設定されている検索パターンを使えるように if(bChangeCurRegexp && !m_pCommanderView->ChangeCurRegexp())return; - bool bRedo = TRUE; // hor + this->m_pCommanderView->lastSearchInfo.pos = CLogicPoint( -1, -1 ); + + bool bFirstTime = TRUE; // hor nLineNumOld = nLineNum; // hor int nIdxOld = nIdx; // hor - re_do:; /* 現在位置より後ろの位置を検索する */ // 2004.05.30 Moca 引数をGetShareData()からメンバ変数に変更。他のプロセス/スレッドに書き換えられてしまわないように。 @@ -3280,12 +3267,12 @@ // From Here 2002.01.26 hor 先頭(末尾)から再検索 if(GetDllShareData().m_Common.m_sSearch.m_bSearchAll){ if(!bFound && // 見つからなかった - bRedo && // 最初の検索 + bFirstTime && // 最初の検索 m_pCommanderView->GetDrawSwitch() // 全て置換の実行中じゃない ){ nLineNum=CLayoutInt(0); nIdx=CLogicInt(0); - bRedo=FALSE; + bFirstTime=FALSE; goto re_do; // 先頭から再検索 } } @@ -3293,6 +3280,9 @@ if(bFound){ if((nLineNumOld > nLineNum)||(nLineNumOld == nLineNum && nIdxOld > nIdx)) m_pCommanderView->SendStatusMessage(_T("▼先頭から再検索しました")); + + // ハイライトのために検索語の頭の位置を保存。 + this->GetDocument()->m_cLayoutMgr.LayoutToLogic( sRangeA.GetFrom(), &(this->m_pCommanderView->lastSearchInfo.pos) ); } else{ GetCaret().ShowEditCaret(); // 2002/04/18 YAZAKI @@ -3318,6 +3308,12 @@ } } } + if( this->m_pCommanderView->pColorML_Found ) { + this->m_pCommanderView->pColorML_Found->SearchConditionChanged(); // 検索条件が変わったので以前のハイライト情報をリセット。 + } + if( this->m_pCommanderView->m_bCurSrchKeyMark ) { + this->m_pCommanderView->Redraw(); + } } @@ -3340,19 +3336,11 @@ /* 範囲選択開始 */ void CViewCommander::Command_BEGIN_SELECT( void ) { - if( !m_pCommanderView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - /* 現在のカーソル位置から選択を開始する */ - m_pCommanderView->GetSelectionInfo().BeginSelectArea(); + CViewSelect& selection = m_pCommanderView->GetSelectionInfo(); + if( ! selection.IsTextSelected() ) { + selection.BeginSelectArea(); /* 現在のカーソル位置から選択を開始する */ + selection.m_bSelectingLock = ! selection.m_bSelectingLock; // ロックの解除切り替え } - - // ロックの解除切り替え - if ( m_pCommanderView->GetSelectionInfo().m_bSelectingLock ) { - m_pCommanderView->GetSelectionInfo().m_bSelectingLock = FALSE; /* 選択状態のロック解除 */ - } - else { - m_pCommanderView->GetSelectionInfo().m_bSelectingLock = TRUE; /* 選択状態のロック */ - } - return; } @@ -3364,19 +3352,13 @@ if( !GetDllShareData().m_Common.m_sView.m_bFontIs_FIXED_PITCH ){ /* 現在のフォントは固定幅フォントである */ return; } - -//@@@ 2002.01.03 YAZAKI 範囲選択中にShift+F6を実行すると選択範囲がクリアされない問題に対処 - if( m_pCommanderView->GetSelectionInfo().IsTextSelected() ){ /* テキストが選択されているか */ - /* 現在の選択範囲を非選択状態に戻す */ - m_pCommanderView->GetSelectionInfo().DisableSelectArea( TRUE ); + CViewSelect& selection = m_pCommanderView->GetSelectionInfo(); + if( ! selection.IsTextSelected() ) { + /* 現在のカーソル位置から選択を開始する */ + selection.BeginSelectArea(); + selection.m_bSelectingLock = true; /* 選択状態のロック */ + selection.SetBoxSelect(true); /* 矩形範囲選択中 */ } - - /* 現在のカーソル位置から選択を開始する */ - m_pCommanderView->GetSelectionInfo().BeginSelectArea(); - - m_pCommanderView->GetSelectionInfo().m_bSelectingLock = true; /* 選択状態のロック */ - m_pCommanderView->GetSelectionInfo().SetBoxSelect(true); /* 矩形範囲選択中 */ - return; } @@ -8103,53 +8085,8 @@ //検索マークの切替え // 2001.12.03 hor クリア を 切替え に変更 void CViewCommander::Command_SEARCH_CLEARMARK( void ) { -// From Here 2001.12.03 hor - - //検索マークのセット - - if(m_pCommanderView->GetSelectionInfo().IsTextSelected()){ - - // 検索文字列取得 - CNativeW cmemCurText; - m_pCommanderView->GetCurrentTextForSearch( cmemCurText ); - - // 検索文字列設定 - int i,j; - wcscpy( m_pCommanderView->m_szCurSrchKey, cmemCurText.GetStringPtr() ); - for( i = 0; i < GetDllShareData().m_sSearchKeywords.m_aSearchKeys.size(); ++i ){ - if( 0 == wcscmp( m_pCommanderView->m_szCurSrchKey, GetDllShareData().m_sSearchKeywords.m_aSearchKeys[i] ) ){ - break; - } - } - if( i < GetDllShareData().m_sSearchKeywords.m_aSearchKeys.size() ){ - for( j = i; j > 0; j-- ){ - wcscpy( GetDllShareData().m_sSearchKeywords.m_aSearchKeys[j], GetDllShareData().m_sSearchKeywords.m_aSearchKeys[j - 1] ); - } - } - else{ - for( j = MAX_SEARCHKEY - 1; j > 0; j-- ){ - wcscpy( GetDllShareData().m_sSearchKeywords.m_aSearchKeys[j], GetDllShareData().m_sSearchKeywords.m_aSearchKeys[j - 1] ); - } - GetDllShareData().m_sSearchKeywords.m_aSearchKeys.resize( t_min(MAX_SEARCHKEY, GetDllShareData().m_sSearchKeywords.m_aSearchKeys.size()+1) ); - } - wcscpy( GetDllShareData().m_sSearchKeywords.m_aSearchKeys[0], cmemCurText.GetStringPtr() ); - - // 検索オプション設定 - GetDllShareData().m_Common.m_sSearch.m_sSearchOption.bRegularExp=false; //正規表現使わない - GetDllShareData().m_Common.m_sSearch.m_sSearchOption.bWordOnly=false; //単語で検索しない - m_pCommanderView->ChangeCurRegexp(); // 2002.11.11 Moca 正規表現で検索した後,色分けができていなかった - - // 再描画 - m_pCommanderView->RedrawAll(); - return; - } -// To Here 2001.12.03 hor - - //検索マークのクリア - - m_pCommanderView->m_bCurSrchKeyMark = false; /* 検索文字列のマーク */ - /* フォーカス移動時の再描画 */ - m_pCommanderView->RedrawAll(); + this->m_pCommanderView->m_bCurSrchKeyMark = ! this->m_pCommanderView->m_bCurSrchKeyMark; + this->m_pCommanderView->Redraw(); return; } @@ -8755,7 +8692,7 @@ if( pcDoc->m_nTextWrapMethodCur == nWrapMethod ) return; - int nWidth; + CLayoutInt nWidth; switch( nWrapMethod ){ case WRAP_NO_TEXT_WRAP: // 折り返さない @@ -8763,12 +8700,12 @@ break; case WRAP_SETTING_WIDTH: // 指定桁で折り返す - nWidth = (Int)pcDoc->m_cDocType.GetDocumentAttribute().m_nMaxLineKetas; + nWidth = pcDoc->m_cDocType.GetDocumentAttribute().m_nMaxLineKetas; break; case WRAP_WINDOW_WIDTH: // 右端で折り返す // ウィンドウが左右に分割されている場合は左側のウィンドウ幅を使用する - nWidth = (Int)m_pCommanderView->ViewColNumToWrapColNum( GetEditWindow()->m_pcEditViewArr[0]->GetTextArea().m_nViewColNum ); + nWidth = m_pCommanderView->ViewColNumToWrapColNum( GetEditWindow()->m_pcEditViewArr[0]->GetTextArea().m_nViewColNum ); break; default: @@ -8781,7 +8718,7 @@ pcDoc->m_bTextWrapMethodCurTemp = !( pcDoc->m_cDocType.GetDocumentAttribute().m_nTextWrapMethod == nWrapMethod ); // 折り返し位置を変更 - GetEditWindow()->ChangeLayoutParam( false, pcDoc->m_cLayoutMgr.GetTabSpace(), (CLayoutInt)nWidth ); + GetEditWindow()->ChangeLayoutParam( false, pcDoc->m_cLayoutMgr.GetTabSpace(), nWidth ); // 2009.08.28 nasukoji 「折り返さない」ならテキスト最大幅を算出、それ以外は変数をクリア if( pcDoc->m_nTextWrapMethodCur == WRAP_NO_TEXT_WRAP ){ Index: sakura_core/global.h =================================================================== --- sakura_core/global.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/global.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -115,23 +115,8 @@ //右クリックメニューで使うカスタムメニューのインデックス //@@@ 2003.06.13 MIK #define CUSTMENU_INDEX_FOR_RBUTTONUP 0 +#include "view/colors/EColorIndexType.h" -/*!< 色タイプ */ -//@@@ From Here 2006.12.18 ryoji -#define COLOR_ATTRIB_FORCE_DISP 0x00000001 -//#define COLOR_ATTRIB_NO_TEXT 0x00000010 予約値 -#define COLOR_ATTRIB_NO_BACK 0x00000020 -#define COLOR_ATTRIB_NO_BOLD 0x00000100 -#define COLOR_ATTRIB_NO_UNDERLINE 0x00000200 -//#define COLOR_ATTRIB_NO_ITALIC 0x00000400 予約値 -#define COLOR_ATTRIB_NO_EFFECTS 0x00000F00 - -struct SColorAttributeData{ - TCHAR* szName; - unsigned int fAttribute; -}; -SAKURA_CORE_API extern const SColorAttributeData g_ColorAttributeArr[]; - //@@@ To Here 2006.12.18 ryoji /*!< 設定値の上限・下限 */ Index: sakura_core/config/app_constants.h =================================================================== --- sakura_core/config/app_constants.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/config/app_constants.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,4 +1,5 @@ #pragma once +#include "basis/SakuraBasis.h" // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // // 名前 // @@ -35,7 +36,7 @@ // Aug. 14, 2005 genta 定数定義追加 // 2007.09.07 kobake 定数名変更: MAXLINESIZE→MAXLINEKETAS // 2007.09.07 kobake 定数名変更: MINLINESIZE→MINLINEKETAS -const int MAXLINEKETAS = 10240; //!< 1行の桁数の最大値 -const int MINLINEKETAS = 10; //!< 1行の桁数の最小値 +const CLayoutInt MAXLINEKETAS = 10240; //!< 1行の桁数の最大値 +const CLayoutInt MINLINEKETAS = 10; //!< 1行の桁数の最小値 Index: sakura_core/util/file.cpp =================================================================== --- sakura_core/util/file.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/util/file.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -349,10 +349,34 @@ } +bool TranslateForbiddenFileCharacterToZenkaku( wchar_t* const dst, const wchar_t* const src ) +{ + if( ! dst || ! src ) { + return false; + } + const wchar_t szForbidden[10] = L"\"*/:<>?\\|"; + const wchar_t szZenkaku[10] = L"”*/:<>?\|"; + wchar_t* const dstend = dst + _MAX_FNAME - 1; + wchar_t* d = dst; + const wchar_t* s = src; + for( ; *s && d < dstend; ++s ) { + if( 0 <= *s && *s < 0x20 ) { + // 制御文字はコピーしない。条件式の正しさにはさっぱり自信がない。 + } else if( const wchar_t* const forbidden = wcschr( szForbidden, *s ) ) { + *d++ = szZenkaku[ forbidden - szForbidden ]; + } else { + *d++ = *s; + } + } + if( dstend <= d ) { + *dstend = L'\0'; + return !*s; + } else { + *d = L'\0'; + return true; + } +} - - - /*! @brief ディレクトリの深さを計算する 与えられたパス名からディレクトリの深さを計算する. Index: sakura_core/util/file.h =================================================================== --- sakura_core/util/file.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/util/file.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -16,6 +16,10 @@ //※サクラ依存 FILE *_tfopen_absexe(LPCTSTR fname, LPCTSTR mode); // 2003.06.23 Moca FILE *_tfopen_absini(LPCTSTR fname, LPCTSTR mode, BOOL bOrExedir = TRUE); // 2007.05.19 ryoji +void GetInidir( + LPTSTR pDir, //!< [out] INIファイルのあるディレクトリを返す場所.予め_MAX_PATHのバッファを用意しておくこと. + LPCTSTR szFile /*=NULL*/ //!< [in] ディレクトリ名に結合するファイル名. +); //パス文字列処理 SAKURA_CORE_API void CutLastYenFromDirectoryPath( TCHAR* ); /* フォルダの最後が半角かつ'\\'の場合は、取り除く "c:\\"等のルートは取り除かない*/ @@ -25,6 +29,8 @@ SAKURA_CORE_API BOOL CheckEXT( const TCHAR*, const TCHAR* ); /* 拡張子を調べる */ const TCHAR* GetFileTitlePointer(const TCHAR* tszPath); //!< ファイルフルパス内のファイル名を指すポインタを取得。2007.09.20 kobake 作成 bool _IS_REL_PATH(const TCHAR* path); //!< 相対パスか判定する。2003.06.23 Moca +//bool TranslateForbiddenFileCharacterToZenkaku( TCHAR (&dest)[_MAX_FNAME], const TCHAR* const src ); ///< ファイル名に使えない文字を全角に変換する。コントロールコードは消去する。 +bool TranslateForbiddenFileCharacterToZenkaku( wchar_t* const dst, const wchar_t* const src ); ///< ファイル名に使えない文字を全角に変換する。コントロールコードは消去する。 //ファイル時刻 class CFileTime{ Index: sakura_core/view/CCaret.cpp =================================================================== --- sakura_core/view/CCaret.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CCaret.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -10,7 +10,7 @@ #include "charset/CCodeFactory.h" #include "window/CEditWnd.h" #include -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" using namespace std; // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // Index: sakura_core/view/CEditView_Search.cpp =================================================================== --- sakura_core/view/CEditView_Search.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CEditView_Search.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,6 +1,7 @@ #include "stdafx.h" #include "CEditView.h" #include "parse/CWordParse.h" +#include "charset/charcode.h" const int STRNCMP_MAX = 100; /* MAXキーワード長:strnicmp文字列比較最大値(CEditView::KeySearchCore) */ // 2006.04.10 fon @@ -276,71 +277,87 @@ //2002.02.08 hor //正規表現で検索したときの速度改善のため、マッチ先頭位置を引数に追加 //Jun. 26, 2001 genta 正規表現ライブラリの差し替え -bool CEditView::IsSearchString( +/* + @retval 0 + (パターン検索時) 現在位置以降にマッチはない。 + (それ以外) 現在位置は検索文字列の始まりではない。 + @retval 1,2,3,... + (パターン検索時) 現在位置以降にマッチが見つかった。 + (単語検索時) 現在位置が検索文字列に含まれる何番目の単語の始まりであるか。 + (それ以外) 現在位置が検索文字列の始まり。 +*/ +int CEditView::IsSearchString( const CStringRef& cStr, - /* - const wchar_t* pszData, - CLogicInt nDataLen, - */ CLogicInt nPos, CLogicInt* pnSearchStart, CLogicInt* pnSearchEnd ) const { - CLogicInt nKeyLength; - - *pnSearchStart = nPos; // 2002.02.08 hor - - if( m_sCurSearchOption.bRegularExp ){ - /* 行頭ではない? */ - /* 行頭検索チェックは、CBregexpクラス内部で実施するので不要 2003.11.01 かろと */ - - /* 位置を0でMatchInfo呼び出すと、行頭文字検索時に、全て true となり、 - ** 画面全体が検索文字列扱いになる不具合修正 - ** 対策として、行頭を MacthInfoに教えないといけないので、文字列の長さ・位置情報を与える形に変更 - ** 2003.05.04 かろと - */ - if( m_CurRegexp.Match( cStr.GetPtr(), cStr.GetLength(), nPos ) ){ + if( m_sCurSearchOption.bRegularExp ) { // パターン検索 + if( m_CurRegexp.Match( cStr.GetPtr(), cStr.GetLength(), nPos ) ) { *pnSearchStart = m_CurRegexp.GetIndex(); // 2002.02.08 hor *pnSearchEnd = m_CurRegexp.GetLastIndex(); - return true; + return 1; // 現在位置 *以降* にマッチした。 } - else{ - return false; + return 0; // 現在位置 *以降* にマッチはなかった。 + } + else if( GetDllShareData().m_Common.m_sSearch.m_sSearchOption.bWordOnly ) { // 単語検索 + if( ! this->m_szCurSrchKey || ! this->m_szCurSrchKey[0] ) { + return 0; // 検索条件が未定義。 } - } - else{ - nKeyLength = CLogicInt(wcslen( m_szCurSrchKey )); /* 検索条件 */ + /* 現在位置の単語の範囲を調べる */ + CLogicInt posWordHead, posWordEnd; + if( ! CWordParse::WhereCurrentWord_2( cStr.GetPtr(), CLogicInt(cStr.GetLength()), nPos, &posWordHead, &posWordEnd, NULL, NULL ) ) { + return 0; // 現在位置に単語が見つからなかった。 + } + if( nPos != posWordHead ) { + return 0; // 現在位置は単語の始まりではなかった。 + } + const CLogicInt wordLength = posWordEnd - posWordHead; + const wchar_t *const pWordHead = cStr.GetPtr() + posWordHead; - // 2001/06/23 単語単位の検索のために追加 - if( GetDllShareData().m_Common.m_sSearch.m_sSearchOption.bWordOnly ){ /* 検索/置換 1==単語のみ検索 */ - /* 現在位置の単語の範囲を調べる */ - /* 現在位置の単語の範囲を調べる */ - CLogicInt nIdxFrom, nIdxTo; - if( !CWordParse::WhereCurrentWord_2( cStr.GetPtr(), CLogicInt(cStr.GetLength()), nPos, &nIdxFrom, &nIdxTo, NULL, NULL ) ){ - return false; + // 比較関数 + int (*const fcmp)( const wchar_t*, const wchar_t*, size_t ) = m_sCurSearchOption.bLoHiCase ? wcsncmp : wcsnicmp; + + // 検索語を単語に分割しながら現在位置の単語と照合する。 + int wordIndex = 0; + const wchar_t* const searchKeyEnd = m_szCurSrchKey + wcslen( m_szCurSrchKey ); + for( const wchar_t* p = m_szCurSrchKey; p < searchKeyEnd; ) { + CLogicInt begin, end; // 検索語に含まれる単語?の位置。WhereCurrentWord_2()の仕様では空白文字列も単語に含まれる。 + if( CWordParse::WhereCurrentWord_2( p, CLogicInt(searchKeyEnd - p), 0, &begin, &end, NULL, NULL ) + && begin == 0 && begin < end + ) { + if( ! WCODE::IsWordDelimiter( *p ) ) { + ++wordIndex; + // p...(p + end) が検索語に含まれる wordIndex番目の単語。(wordIndexの最初は 1) + if( wordLength == end && 0 == fcmp( p, pWordHead, wordLength ) ) { + *pnSearchStart = posWordHead; + *pnSearchEnd = posWordEnd; + return wordIndex; + } + } + p += end; + } else { + p += CNativeW::GetSizeOfChar( p, searchKeyEnd - p, 0 ); } - if( nPos != nIdxFrom || nKeyLength != nIdxTo - nIdxFrom ){ - return false; - } } + return 0; // 現在位置の単語と検索文字列に含まれる単語は一致しなかった。 + } + else { + const CLogicInt nKeyLength = static_cast( wcslen( m_szCurSrchKey ) ); - //検索条件が未定義 または 検索条件の長さより調べるデータが短いときはヒットしない - if( 0 == nKeyLength || nKeyLength > cStr.GetLength() - nPos ){ - return false; + if( 0 == nKeyLength || nKeyLength > cStr.GetLength() - nPos ) { + return 0; // 検索条件が未定義。または検索条件の長さより調べるデータが短かった。 } - //英大文字小文字の区別をするかどうか - if( m_sCurSearchOption.bLoHiCase ){ /* 1==英大文字小文字の区別 */ - if( 0 == auto_memcmp( &cStr.GetPtr()[nPos], m_szCurSrchKey, nKeyLength ) ){ - *pnSearchEnd = nPos + nKeyLength; - return true; - } - }else{ - if( 0 == auto_memicmp( &cStr.GetPtr()[nPos], m_szCurSrchKey, nKeyLength ) ){ - *pnSearchEnd = nPos + nKeyLength; - return true; - } + + const int ret = m_sCurSearchOption.bLoHiCase ? // 英大文字小文字の区別をするかどうか + auto_memcmp( cStr.GetPtr() + nPos, m_szCurSrchKey, nKeyLength ): + auto_memicmp( cStr.GetPtr() + nPos, m_szCurSrchKey, nKeyLength ); + if( 0 == ret ) { + *pnSearchStart = nPos; + *pnSearchEnd = nPos + nKeyLength; + return 1; // 現在位置の文字列と検索文字列が一致した。 } + return 0; // 一致しなかった。 } - return false; } Index: sakura_core/view/CEditView_Paint_Bracket.cpp =================================================================== --- sakura_core/view/CEditView_Paint_Bracket.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CEditView_Paint_Bracket.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,7 +1,7 @@ #include "stdafx.h" #include "CEditView_Paint.h" #include "types/CTypeSupport.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // // 括弧 // Index: sakura_core/view/CViewSelect.cpp =================================================================== --- sakura_core/view/CViewSelect.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CViewSelect.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -204,17 +204,22 @@ m_sSelectOld.GetFrom(), // 範囲選択開始 m_sSelectOld.GetTo() // 範囲選択終了 ); - rcOld.left = t_max(rcOld.left , pView->GetTextArea().GetViewLeftCol() ); - rcOld.right = t_max(rcOld.right , pView->GetTextArea().GetViewLeftCol() ); - rcOld.right = t_min(rcOld.right , pView->GetTextArea().GetRightCol() + 1 ); - rcOld.top = t_max(rcOld.top , pView->GetTextArea().GetViewTopLine() ); - rcOld.bottom = t_min(rcOld.bottom, pView->GetTextArea().GetBottomLine() ); + rcOld.left = t_max(rcOld.left , pView->GetTextArea().GetViewLeftCol() ); + rcOld.right = t_max(rcOld.right , pView->GetTextArea().GetViewLeftCol() ); + rcOld.right = t_min(rcOld.right , pView->GetTextArea().GetRightCol() + 1); + rcOld.top = t_max(rcOld.top , pView->GetTextArea().GetViewTopLine() ); + rcOld.bottom = t_min(rcOld.bottom, pView->GetTextArea().GetBottomLine() ); RECT rcOld2; rcOld2.left = (pView->GetTextArea().GetAreaLeft() - (Int)pView->GetTextArea().GetViewLeftCol() * nCharWidth) + (Int)rcOld.left * nCharWidth; rcOld2.right = (pView->GetTextArea().GetAreaLeft() - (Int)pView->GetTextArea().GetViewLeftCol() * nCharWidth) + (Int)rcOld.right * nCharWidth; rcOld2.top = (Int)( rcOld.top - pView->GetTextArea().GetViewTopLine() ) * nCharHeight + pView->GetTextArea().GetAreaTop(); rcOld2.bottom = (Int)( rcOld.bottom + 1 - pView->GetTextArea().GetViewTopLine() ) * nCharHeight + pView->GetTextArea().GetAreaTop(); + if( m_sSelectOld.GetFrom() != m_sSelectOld.GetTo() ) { + rcOld2.right += 1; // ちょっとだけ見せていた。 + rcOld2.left -= 1; // ちょっとだけ見せていた。 + } + HRGN hrgnOld = ::CreateRectRgnIndirect( &rcOld2 ); // 2点を対角とする矩形を求める @@ -235,6 +240,8 @@ rcNew2.right = (pView->GetTextArea().GetAreaLeft() - (Int)pView->GetTextArea().GetViewLeftCol() * nCharWidth) + (Int)rcNew.right * nCharWidth; rcNew2.top = (Int)(rcNew.top - pView->GetTextArea().GetViewTopLine()) * nCharHeight + pView->GetTextArea().GetAreaTop(); rcNew2.bottom = (Int)(rcNew.bottom + 1 - pView->GetTextArea().GetViewTopLine()) * nCharHeight + pView->GetTextArea().GetAreaTop(); + rcNew2.right += 1; // ちょっとだけ見せる。 + rcNew2.left -= 1; // ちょっとだけ見せる。 HRGN hrgnNew = ::CreateRectRgnIndirect( &rcNew2 ); @@ -423,7 +430,7 @@ t_swap(nSelectFrom, nSelectTo); } } - + // 2006.03.28 Moca ウィンドウ幅が大きいと正しく反転しない問題を修正 if( nSelectFrom < pView->GetTextArea().GetViewLeftCol() ){ nSelectFrom = pView->GetTextArea().GetViewLeftCol(); Index: sakura_core/view/CEditView_Paint.cpp =================================================================== --- sakura_core/view/CEditView_Paint.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CEditView_Paint.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,15 +1,15 @@ #include "stdafx.h" -#include "CEditView_Paint.h" -#include "view/CEditView.h" +#include #include -#include "types/CTypeSupport.h" #include "doc/CLayout.h" -#include "parse/CWordParse.h" +#include "view/CEditView.h" #include "util/string_ex2.h" -#include "view/colors/CColorStrategy.h" -#include //auto_ptr -#include "view/colors/CColor_Found.h" +#include "parse/CWordParse.h" +#include "types/CTypeSupport.h" +#include "view/colors/EColorIndexType.h" +#include "view/colors/ColorMLStrategy.h" #include "view/figures/CFigureStrategy.h" +#include "CEditView_Paint.h" void _DispWrap(CGraphics& gr, DispPos* pDispPos, const CEditView* pcView); @@ -125,119 +125,49 @@ 1000〜COLORIDX_LASTまでは正規表現で使用する。 */ EColorIndexType CEditView::GetColorIndex( - const CLayout* pcLayout, - int nIndex + const CLayout* const pcLayout, + const int nIndex ) { - EColorIndexType eRet = COLORIDX_TEXT; - - if(!pcLayout){ + if( ! pcLayout ){ return COLORIDX_TEXT; } - // May 9, 2000 genta - STypeConfig *TypeDataPtr = &(m_pcEditDoc->m_cDocType.GetDocumentAttribute()); + STypeConfig *const TypeDataPtr = &(m_pcEditDoc->m_cDocType.GetDocumentAttribute()); + const CLogicInt lineNum = pcLayout->GetLogicLineNo(); + const CLogicInt pos = pcLayout->GetLogicOffset() + __min(nIndex, pcLayout->GetLengthWithEOL() - 1); - /* 論理行データの取得 */ - DispPos _sPos(0,0); - SColorStrategyInfo _sInfo; - SColorStrategyInfo* pInfo = &_sInfo; - pInfo->pcView = this; - pInfo->pDispPos=&_sPos; - { - // 2002/2/10 aroka CMemory変更 - pInfo->pLineOfLogic = pcLayout->GetDocLineRef()->GetPtr(); - - // 論理行の最初のレイアウト情報を取得 -> pcLayoutLineFirst - const CLayout* pcLayoutLineFirst = pcLayout; - while( 0 != pcLayoutLineFirst->GetLogicOffset() ){ - pcLayoutLineFirst = pcLayoutLineFirst->GetPrevLayout(); - - // 論理行の先頭まで戻らないと確実には正確な色は得られない - // (正規表現キーワードにマッチした長い強調表示がその位置のレイアウト行頭をまたいでいる場合など) - //if( pcLayout->GetLogicOffset() - pcLayoutLineFirst->GetLogicOffset() > 260 ) - // break; + ColorMLStrategy::Result highlight; + // 検索語のハイライトを優先。 + if( this->m_bCurSrchKeyMark ) { + this->colorStrategySearchWord.HighlightLine( this->m_pcEditDoc, lineNum, &highlight ); + EColorIndexType color = highlight.colorInfo.at( pos ); + if( color != COLORIDX_DEFAULT && TypeDataPtr->m_ColorInfoArr[ color ].m_bDisp ) { + return color; } - - // 2005.11.20 Moca 色が正しくないことがある問題に対処 - eRet = pcLayoutLineFirst->GetColorTypePrev(); /* 現在の色を指定 */ // 02/12/18 ai - pInfo->nPosInLogic = pcLayoutLineFirst->GetLogicOffset(); - - //CColorStrategyPool初期化 - CColorStrategyPool* pool = CColorStrategyPool::Instance(); - pool->NotifyOnStartScanLogic(); - - - // 2009.02.07 ryoji この関数では pInfo->DoChangeColor() で色を調べるだけなので以下の処理は不要 - // - ////############超仮。本当はVisitorを使うべき - //class TmpVisitor{ - //public: - // static int CalcLayoutIndex(const CLayout* pcLayout) - // { - // int n = -1; - // while(pcLayout){ - // pcLayout = pcLayout->GetPrevLayout(); //prev or null - // n++; - // } - // return n; - // } - //}; - //pInfo->pDispPos->SetLayoutLineRef(CLayoutInt(TmpVisitor::CalcLayoutIndex(pcLayout))); } - - //@@@ 2001.11.17 add start MIK - if( TypeDataPtr->m_bUseRegexKeyword ) - { - m_cRegexKeyword->RegexKeyLineStart(); - } - //@@@ 2001.11.17 add end MIK - - //文字列参照 - const CDocLine* pcDocLine = pcLayout->GetDocLineRef(); - CStringRef cLineStr(pcDocLine->GetPtr(),pcDocLine->GetLengthWithEOL()); - - //color strategy - CColorStrategyPool* pool = CColorStrategyPool::Instance(); - pInfo->pStrategy = pool->GetStrategyByColor(eRet); - if(pInfo->pStrategy)pInfo->pStrategy->InitStrategyStatus(); - - int nPosTo = pcLayout->GetLogicOffset() + __min(nIndex, pcLayout->GetLengthWithEOL() - 1); - while(pInfo->nPosInLogic <= nPosTo){ - //色切替 - pInfo->DoChangeColor(cLineStr); - - //1文字進む - pInfo->nPosInLogic += CNativeW::GetSizeOfChar( - cLineStr.GetPtr(), - cLineStr.GetLength(), - pInfo->nPosInLogic - ); - } - eRet = pInfo->GetCurrentColor(); - - return eRet; + // その他の色分け結果。 + this->m_pcEditDoc->HighlightInfo( lineNum, &highlight ); + return highlight.colorInfo.at( pos ); } /* 現在の色を指定 */ void CEditView::SetCurrentColor( CGraphics& gr, EColorIndexType eColorIndex ) { - //インデックス決定 - int nColorIdx = ToColorInfoArrIndex(eColorIndex); + // インデックス決定 + const EColorIndexType nColorIdx = ActualColor(eColorIndex); //実際に色を設定 - if( -1 != nColorIdx ){ - const ColorInfo& info = m_pcEditDoc->m_cDocType.GetDocumentAttribute().m_ColorInfoArr[nColorIdx]; - gr.SetForegroundColor(info.m_colTEXT); - gr.SetBackgroundColor(info.m_colBACK); - gr.SetMyFont( - GetFontset().ChooseFontHandle( - info.m_bFatFont, - info.m_bUnderLine - ) - ); - } + const ColorInfo& info = m_pcEditDoc->m_cDocType.GetDocumentAttribute().m_ColorInfoArr[nColorIdx]; + gr.SetForegroundColor(info.m_colTEXT); + gr.SetBackgroundColor(info.m_colBACK); + gr.SetMyFont( + GetFontset().ChooseFontHandle( + info.m_bFatFont, + info.m_bUnderLine + ) + ); } @@ -331,6 +261,12 @@ } //@@@ 2001.11.17 add end MIK + // ドキュメントの変更と検索条件の変更に対応するためハイライトのキャッシュをリセット。 + // この位置に置くのはおおざっぱだけど、たいしたコストじゃないので。 + if( this->pColorML_Found ) { + this->pColorML_Found->SearchConditionChanged(); + } + // メモリDCを利用した再描画の場合は描画先のDCを切り替える HDC hdcOld; // 2007.09.09 Moca bUseMemoryDCを有効化。 @@ -434,11 +370,15 @@ sPos.ResetDrawCol(); //1行描画 + CLayoutInt originalLineTo = nLayoutLineTo; bool bDispResult = DrawLogicLine( gr, &sPos, - nLayoutLineTo + &nLayoutLineTo ); + if( originalLineTo < nLayoutLineTo ) { + pPs->rcPaint.bottom += nLineHeight * static_cast( nLayoutLineTo - originalLineTo ); + } if(bDispResult){ pPs->rcPaint.bottom += nLineHeight; // EOF再描画対応 @@ -559,13 +499,12 @@ bool CEditView::DrawLogicLine( HDC _hdc, //!< [in] 作画対象 DispPos* _pDispPos, //!< [in/out] 描画する箇所、描画元ソース - CLayoutInt nLineTo //!< [in] 作画終了するレイアウト行番号 + CLayoutInt* pnLineTo //!< [in/out] 作画終了するレイアウト行番号 ) { // MY_RUNNINGTIMER( cRunningTimer, "CEditView::DrawLogicLine" ); bool bDispEOF = false; - SColorStrategyInfo _sInfo; - SColorStrategyInfo* pInfo = &_sInfo; + SColorStrategyInfo _sInfo, *pInfo = &_sInfo; pInfo->gr.Init(_hdc); pInfo->pDispPos = _pDispPos; pInfo->pcView = this; @@ -574,82 +513,77 @@ // return true; // } - //CColorStrategyPool初期化 - CColorStrategyPool* pool = CColorStrategyPool::Instance(); - pool->NotifyOnStartScanLogic(); - //DispPosを保存しておく pInfo->sDispPosBegin = *pInfo->pDispPos; // Aug. 14, 2005 genta 折り返し幅をLayoutMgrから取得するように const CLayoutInt nWrapKeta = m_pcEditDoc->m_cLayoutMgr.GetMaxLineKetas(); - //サイズ STypeConfig* TypeDataPtr = &m_pcEditDoc->m_cDocType.GetDocumentAttribute(); int nLineHeight = GetTextMetrics().GetHankakuDy(); //行の縦幅? int nCharDx = GetTextMetrics().GetHankakuDx(); //半角 //処理する文字位置 - pInfo->nPosInLogic = CLogicInt(0); //☆開始 + pInfo->nLogicPos = CLogicInt(0); //☆開始 // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // // 論理行データの取得 -> pLine, pLineLen // // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - // 前行の最終設定色 - { - const CLayout* pcLayout = pInfo->pDispPos->GetLayoutRef(); - //EColorIndexType eType = pcLayout? pcLayout->GetColorTypePrev(): COLORIDX_TEXT; - EColorIndexType eType = GetColorIndex(pcLayout, 0); - CColorStrategyPool* pool = CColorStrategyPool::Instance(); - pInfo->pStrategy = pool->GetStrategyByColor(eType); - //ここではGetColorIndex()からの継続処理にするためInitStrategyStatus()を行わない - //if(pInfo->pStrategy)pInfo->pStrategy->InitStrategyStatus(); - pInfo->ChangeColor(eType); - } //開始ロジック位置を算出 { const CLayout* pcLayout = pInfo->pDispPos->GetLayoutRef(); - pInfo->nPosInLogic = pcLayout?pcLayout->GetLogicOffset():CLogicInt(0); + pInfo->nLogicPos = pcLayout?pcLayout->GetLogicOffset():CLogicInt(0); } //サポート CTypeSupport cTextType(this,COLORIDX_TEXT); - CTypeSupport cSearchType(this,COLORIDX_SEARCH); - //正規表現キーワードを使うか //@@@ 2001.11.17 add MIK - if( TypeDataPtr->m_bUseRegexKeyword ){ - m_cRegexKeyword->RegexKeyLineStart(); + // 描画すべき論理行 + const CLogicInt lineToDraw = pInfo->pDispPos->GetLayoutRef()->GetLogicLineNo(); + // 論理行を色分け + if( -1 != lineToDraw ) { + if( this->m_bCurSrchKeyMark ) { + this->colorStrategySearchWord.HighlightLine( this->m_pcEditDoc, lineToDraw, &(pInfo->highlightSearchWord) ); + } + this->m_pcEditDoc->HighlightInfo( lineToDraw, &(pInfo->highlight) ); } + CLogicInt currentLine = lineToDraw; while(1){ - //対象行が描画範囲外だったら終了 + // 対象行が描画範囲外だったら終了 if( GetTextArea().GetBottomLine() < pInfo->pDispPos->GetLayoutLineRef() ){ - pInfo->pDispPos->SetLayoutLineRef(nLineTo + CLayoutInt(1)); + pInfo->pDispPos->SetLayoutLineRef(*pnLineTo + CLayoutInt(1)); break; } - if( nLineTo < pInfo->pDispPos->GetLayoutLineRef() ){ + // *pnLineToを超えたら抜ける。ただし、次の行の色分けが変わっている場合は + // (描画範囲内に収まっている限り) *pnLineToを増やしてまた DrawLogicLine()に戻ってくる。 + if( *pnLineTo < pInfo->pDispPos->GetLayoutLineRef() ) { + if( pInfo->highlight.nextLineHighlightChanged ) { + ++*pnLineTo; + } break; } + currentLine = pInfo->pDispPos->GetLayoutRef()->GetLogicLineNo(); + + // ロジック行を描画し終わったら抜ける + if( lineToDraw != currentLine ) { + break; + } + //レイアウト行を1行描画 bDispEOF = DrawLayoutLine(pInfo); //行を進める - CLogicInt nOldLogicLineNo = pInfo->pDispPos->GetLayoutRef()->GetLogicLineNo(); pInfo->pDispPos->ForwardDrawLine(1); //描画Y座標++ pInfo->pDispPos->ForwardLayoutLineRef(1); //レイアウト行++ - // ロジック行を描画し終わったら抜ける - if(pInfo->pDispPos->GetLayoutRef()->GetLogicLineNo()!=nOldLogicLineNo){ + // EOFなら終了 + if( currentLine < 0 ) { break; } - - // nLineToを超えたら抜ける - if(pInfo->pDispPos->GetLayoutLineRef() >= nLineTo + CLayoutInt(1)){ - break; - } } return bDispEOF; @@ -663,48 +597,29 @@ { bool bDispEOF = false; CTypeSupport cTextType(this,COLORIDX_TEXT); - CTypeSupport cSearchType(this,COLORIDX_SEARCH); const CLayout* pcLayout = pInfo->pDispPos->GetLayoutRef(); //m_pcEditDoc->m_cLayoutMgr.SearchLineByLayoutY( pInfo->pDispPos->GetLayoutLineRef() ); + const CDocLine* pcDocLine = pcLayout ? pcLayout->GetDocLineRef() : NULL; + pInfo->nLogicLineNum = pcLayout ? pcLayout->GetLogicLineNo() : -1; - // レイアウト情報 - if( pcLayout ){ - pInfo->pLineOfLogic = pcLayout->GetDocLineRef()->GetPtr(); - } - else{ - pInfo->pLineOfLogic = NULL; - } + //// 描画範囲外の場合は色切替だけで抜ける + //if(pInfo->pDispPos->GetDrawPos().y < pInfo->pcView->GetTextArea().GetAreaTop()){ + // if(pcLayout){ + // while(pInfo->nPosInLogic < pcLayout->GetLogicOffset() + pcLayout->GetLengthWithEOL()){ + // //色切替 + // pInfo->DoChangeColor(); - //文字列参照 - const CDocLine* pcDocLine = pInfo->GetDocLine(); - CStringRef cLineStr = pcDocLine->GetStringRefWithEOL(); + // //1文字進む + // pInfo->nPosInLogic += CNativeW::GetSizeOfChar( + // pcDocLine->GetPtr(), + // pcDocLine->GetLengthWithEOL(), + // pInfo->nPosInLogic + // ); + // } + // } + // return false; + //} - //color strategy - if(pcLayout && pcLayout->GetLogicOffset()==0){ - CColorStrategyPool* pool = CColorStrategyPool::Instance(); - pInfo->pStrategy = pool->GetStrategyByColor(pcLayout->GetColorTypePrev()); - if(pInfo->pStrategy)pInfo->pStrategy->InitStrategyStatus(); - pInfo->ChangeColor(pcLayout->GetColorTypePrev()); - } - - // 描画範囲外の場合は色切替だけで抜ける - if(pInfo->pDispPos->GetDrawPos().y < pInfo->pcView->GetTextArea().GetAreaTop()){ - if(pcLayout){ - while(pInfo->nPosInLogic < pcLayout->GetLogicOffset() + pcLayout->GetLengthWithEOL()){ - //色切替 - pInfo->DoChangeColor(cLineStr); - - //1文字進む - pInfo->nPosInLogic += CNativeW::GetSizeOfChar( - cLineStr.GetPtr(), - cLineStr.GetLength(), - pInfo->nPosInLogic - ); - } - } - return false; - } - // コンフィグ int nLineHeight = GetTextMetrics().GetHankakuDy(); //行の縦幅? STypeConfig* TypeDataPtr = &m_pcEditDoc->m_cDocType.GetDocumentAttribute(); @@ -744,21 +659,23 @@ // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // //行終端または折り返しに達するまでループ if(pcLayout){ - while(pInfo->nPosInLogic < pcLayout->GetLogicOffset() + pcLayout->GetLengthWithEOL()){ + while(pInfo->nLogicPos < pcLayout->GetLogicOffset() + pcLayout->GetLengthWithEOL()){ //色切替 - pInfo->DoChangeColor(cLineStr); + EColorIndexType color = this->m_bCurSrchKeyMark ? pInfo->highlightSearchWord.colorInfo.at( pInfo->nLogicPos ) : COLORIDX_DEFAULT; + color = color != COLORIDX_DEFAULT && TypeDataPtr->m_ColorInfoArr[color].m_bDisp ? color : pInfo->highlight.colorInfo.at( pInfo->nLogicPos ); + this->SetCurrentColor( pInfo->gr, color ); //1文字情報取得 $$高速化可能 - CFigure& cFigure = CFigureManager::Instance()->GetFigure(&cLineStr.GetPtr()[pInfo->GetPosInLogic()]); + CFigure& cFigure = CFigureManager::Instance()->GetFigure( pcDocLine->GetPtr() + pInfo->nLogicPos ); //1文字描画 - CLogicInt nPosOld = pInfo->nPosInLogic; + CLogicInt nPosOld = pInfo->nLogicPos; cFigure.DrawImp(pInfo); - if(pInfo->nPosInLogic == nPosOld){ - pInfo->nPosInLogic += CNativeW::GetSizeOfChar( - cLineStr.GetPtr(), - cLineStr.GetLength(), - pInfo->nPosInLogic + if(pInfo->nLogicPos == nPosOld){ + pInfo->nLogicPos += CNativeW::GetSizeOfChar( + pcDocLine->GetPtr(), + pcDocLine->GetLengthWithEOL(), + pInfo->nLogicPos ); } } @@ -920,17 +837,20 @@ rcClip.top = ptXY.y; rcClip.bottom = ptXY.y + nLineHeight; + if( GetSelectionInfo().IsBoxSelecting() && ! GetSelectionInfo().m_sSelect.IsOne() ) { + rcClip.right += 1; // ちょっとだけ見せる。 + rcClip.left -= 1; // ちょっとだけ見せる。 + } // 2005/04/02 かろと 0文字マッチだと反転幅が0となり反転されないので、1/3文字幅だけ反転させる // 2005/06/26 zenryaku 選択解除でキャレットの残骸が残る問題を修正 // 2005/09/29 ryoji スクロール時にキャレットのようなゴミが表示される問題を修正 - if (GetSelectionInfo().IsTextSelected() && rcClip.right == rcClip.left && - GetSelectionInfo().m_sSelect.IsLineOne() && - GetSelectionInfo().m_sSelect.GetFrom().x >= GetTextArea().GetViewLeftCol()) - { - HWND hWnd = ::GetForegroundWindow(); - if( hWnd && (hWnd == m_pcEditWnd->m_cDlgFind.GetHwnd() || hWnd == m_pcEditWnd->m_cDlgReplace.GetHwnd()) ){ - rcClip.right = rcClip.left + (nCharWidth/3 == 0 ? 1 : nCharWidth/3); - } + else if (GetSelectionInfo().IsTextSelected() && rcClip.right == rcClip.left && + GetSelectionInfo().m_sSelect.GetFrom().x >= GetTextArea().GetViewLeftCol() + ) { +// HWND hWnd = ::GetForegroundWindow(); +// if( hWnd && (hWnd == m_pcEditWnd->m_cDlgFind.GetHwnd() || hWnd == m_pcEditWnd->m_cDlgReplace.GetHwnd()) ){ + rcClip.right = rcClip.left + 2; +// } } if( rcClip.right == rcClip.left ){ return; //0文字マッチによる反転幅拡張なし @@ -1089,3 +1009,36 @@ } } } + + +/* + struct SColorStrategyInfo実装 + CLayoutと EColorIndexTypeに依存する部分だけ、CEditView.hでなく、ここで。 +*/ +CLayoutInt SColorStrategyInfo::GetLayoutPos() const +{ + return CLayoutInt( nLogicPos - pDispPos->GetLayoutRef()->GetLogicOffset() ); +} +const CDocLine* SColorStrategyInfo::GetDocLine() const +{ + return pDispPos->GetLayoutRef()->GetDocLineRef(); +} +const CLayout* SColorStrategyInfo::GetLayout() const +{ + return pDispPos->GetLayoutRef(); +} +EColorIndexType SColorStrategyInfo::GetCurrentColor() const +{ + if( this->pcView && this->pcView->m_bCurSrchKeyMark ) { + if( 0 <= this->GetLogicPos() && this->GetLogicPos() < this->highlightSearchWord.colorInfo.size() ) { + EColorIndexType color = this->highlightSearchWord.colorInfo.at( this->GetLogicPos() ); + if( color != COLORIDX_DEFAULT ){ + return ActualColor( color ); + } + } + } + if( 0 <= this->GetLogicPos() && this->GetLogicPos() < this->highlight.colorInfo.size() ) { + return ActualColor( this->highlight.colorInfo.at( this->GetLogicPos() ) ); + } + return COLORIDX_TEXT; +} Index: sakura_core/view/CTextArea.cpp =================================================================== --- sakura_core/view/CTextArea.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CTextArea.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -4,7 +4,7 @@ #include "CViewFont.h" #include "view/CEditView.h" #include "doc/CEditDoc.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" CTextArea::CTextArea(CEditView* pEditView) : m_pEditView(pEditView) Index: sakura_core/view/figures/CFigure_Eol.cpp =================================================================== --- sakura_core/view/figures/CFigure_Eol.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/figures/CFigure_Eol.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -51,7 +51,7 @@ if(cEol.GetLen()){ m_cEol = cEol; __super::DrawImp(pInfo); - pInfo->nPosInLogic+=cEol.GetLen(); + pInfo->nLogicPos+=cEol.GetLen(); } return true; Index: sakura_core/view/figures/CFigureStrategy.cpp =================================================================== --- sakura_core/view/figures/CFigureStrategy.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/figures/CFigureStrategy.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -15,19 +15,19 @@ public: bool DrawImp(SColorStrategyInfo* pInfo) { - int nIdx = pInfo->GetPosInLogic(); + int nIdx = pInfo->GetLogicPos(); int nLength = CNativeW::GetSizeOfChar( // サロゲートペア対策 2008.10.12 ryoji - pInfo->pLineOfLogic, + pInfo->GetLogicLinePtr(), pInfo->GetDocLine()->GetLengthWithoutEOL(), nIdx ); pInfo->pcView->GetTextDrawer().DispText( pInfo->gr, pInfo->pDispPos, - &pInfo->pLineOfLogic[nIdx], + &pInfo->GetLogicLinePtr()[nIdx], nLength ); - pInfo->nPosInLogic += nLength; + pInfo->nLogicPos += nLength; return true; } bool Match(const wchar_t* pText) const @@ -108,10 +108,10 @@ pInfo->gr.PopMyFont(); } - pInfo->nPosInLogic += CNativeW::GetSizeOfChar( // 行末以外はここでスキャン位置を1字進める - pInfo->pLineOfLogic, + pInfo->nLogicPos += CNativeW::GetSizeOfChar( // 行末以外はここでスキャン位置を1字進める + pInfo->GetLogicLinePtr(), pInfo->GetDocLine()->GetLengthWithoutEOL(), - pInfo->GetPosInLogic() + pInfo->GetLogicPos() ); return true; } Index: sakura_core/view/figures/CFigureStrategy.h =================================================================== --- sakura_core/view/figures/CFigureStrategy.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/figures/CFigureStrategy.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,9 +1,8 @@ #pragma once -#include "view/colors/CColorStrategy.h" //SColorStrategyInfo #include "util/design_template.h" #include - +#include "view/colors/EColorIndexType.h" struct SColorStrategyInfo; //$$レイアウト構築フロー(DoLayout)も CFigure で行うと整理しやすい Index: sakura_core/view/DispPos.h =================================================================== --- sakura_core/view/DispPos.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/DispPos.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,4 +1,6 @@ #pragma once +#include "doc/CLayoutMgr.h" +#include "doc/CEditDoc.h" struct DispPos{ public: Index: sakura_core/view/CEditView.h =================================================================== --- sakura_core/view/CEditView.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CEditView.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -26,9 +26,10 @@ #include +#include #include // LPDATAOBJECT #include "env/CShareData.h" -#include "CTipWnd.h" +#include "window/CTipWnd.h" #include "CDicMgr.h" #include "CHokanMgr.h" // Jun. 26, 2001 genta 正規表現ライブラリの差し替え @@ -48,6 +49,9 @@ #include "CEditView_Paint.h" #include "mfclike/CMyWnd.h" #include "doc/CDocListener.h" +#include "view/DispPos.h" +#include "view/colors/ColorMLStrategy.h" +#include "view/colors/CColorML_Found.h" class CDropTarget; /// 2002/2/3 aroka ヘッダ軽量化 class CMemory;/// @@ -86,7 +90,6 @@ /// @date 2006.05.19 genta const int CMD_FROM_MOUSE = 2; -class CEditView; struct SColorStrategyInfo; /*----------------------------------------------------------------------- @@ -214,7 +217,7 @@ bool DrawLogicLine( HDC hdc, //!< [in] 作画対象 DispPos* pDispPos, //!< [in/out] 描画する箇所、描画元ソース - CLayoutInt nLineTo //!< [in] 作画終了するレイアウト行番号 + CLayoutInt* pnLineTo //!< [in/out] 作画終了するレイアウト行番号 ); //! レイアウト行を1行描画 @@ -419,7 +422,7 @@ }; BOOL KeyWordHelpSearchDict( LID_SKH nID, POINT* po, RECT* rc ); // 2006.04.10 fon - bool IsSearchString( const CStringRef& cStr, CLogicInt, CLogicInt*, CLogicInt* ) const; /* 現在位置が検索文字列に該当するか */ //2002.02.08 hor 引数追加 + int IsSearchString( const CStringRef& cStr, CLogicInt, CLogicInt*, CLogicInt* ) const; /* 現在位置が検索文字列に該当するか */ //2002.02.08 hor 引数追加 void GetCurrentTextForSearch( CNativeW& ); /* 現在カーソル位置単語または選択範囲より検索等のキーを取得 */ void GetCurrentTextForSearchDlg( CNativeW& ); /* 現在カーソル位置単語または選択範囲より検索等のキーを取得(ダイアログ用) 2006.08.23 ryoji */ @@ -594,6 +597,8 @@ int m_nOldUnderLineY; // 前回作画したカーソルアンダーラインの位置 0未満=非表示 int m_nOldCursorLineX; /* 前回作画したカーソル位置縦線の位置 */ // 2007.09.09 Moca bool m_bUnderLineON; + SimpleColorStrategy colorStrategySearchWord; + CColorML_Found* pColorML_Found; public: //画面バッファ @@ -626,8 +631,14 @@ bool m_bCurSrchKeyMark; /* 検索文字列のマーク */ wchar_t m_szCurSrchKey[_MAX_PATH]; /* 検索文字列 */ SSearchOption m_sCurSearchOption; // 検索/置換 オプション + CLogicPoint m_ptSrchStartPos_PHY; // 検索/置換開始時のカーソル位置 (改行単位行先頭からのバイト数(0開始), 改行単位行の行番号(0開始)) BOOL m_bSearch; /* 検索/置換開始位置を登録するか */ // 02/06/26 ai + + struct SearchInfo { + CLogicPoint pos; ///< 検索語の開始位置。方向に関係なく検索語の頭の位置。 + } lastSearchInfo; ///< 正しいハイライト範囲を得るために、行の途中から開始された検索の情報を保存する。 + ESearchDirection m_nISearchDirection; int m_nISearchMode; bool m_bISearchWrap; @@ -678,10 +689,47 @@ }; +/// 描画時にバトンのように受け渡される協働作業用データ置き場 +struct SColorStrategyInfo +{ + SColorStrategyInfo() + : sDispPosBegin(0,0) + {} -/////////////////////////////////////////////////////////////////////// -#endif /* _CEDITVIEW_H_ */ + //参照 + CEditView* pcView; + CGraphics gr; //(SColorInfoでは未使用) + //スキャン位置 + CLogicInt nLogicLineNum; + CLogicInt nLogicPos; + //描画位置 + DispPos* pDispPos; + DispPos sDispPosBegin; + // スキャン位置や描画位置に基づく情報へのアクセサ + CLogicInt GetLogicLineNum() const { return nLogicLineNum; } + CLogicInt GetLogicPos() const { return nLogicPos; } + LPCWSTR GetLogicLinePtr() const + { + if( this->nLogicLineNum < 0 ) { + return NULL; // EOF + } + return this->pcView->GetDocument()->m_cDocLineMgr.GetLine( this->nLogicLineNum )->GetPtr(); + }; + CLayoutInt GetLayoutPos() const; + const CDocLine* GetDocLine() const; + const CLayout* GetLayout() const; + // 色分け。.nLineInLogic行目の色分け情報を納めておくこと(約束)。 + // .nLineInLogicでなく .pInfo->pDispPos->GetLayoutRef()->GetLogicLineNo() ? 使い分けがわからん。 + ColorMLStrategy::Result highlight; + SimpleColorStrategy::Result highlightSearchWord; + + EColorIndexType GetCurrentColor() const; +}; + + +/////////////////////////////////////////////////////////////////////// +#endif /* _CEDITVIEW_H_ */ Index: sakura_core/view/CRuler.cpp =================================================================== --- sakura_core/view/CRuler.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CRuler.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -4,7 +4,7 @@ #include "view/CEditView.h" #include "doc/CEditDoc.h" #include "types/CTypeSupport.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" CRuler::CRuler(const CEditView* pEditView, const CEditDoc* pEditDoc) : m_pEditView(pEditView) Index: sakura_core/view/CEditView_Scroll.cpp =================================================================== --- sakura_core/view/CEditView_Scroll.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CEditView_Scroll.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -574,13 +574,13 @@ CLayoutInt CEditView::ViewColNumToWrapColNum( CLayoutInt nViewColNum ) const { // ぶら下げ余白を差し引く - int nWidth = (Int)(nViewColNum - GetWrapOverhang()); + CLayoutInt nWidth = (Int)(nViewColNum - GetWrapOverhang()); // MINLINEKETAS未満の時はMINLINEKETASで折り返しとする if( nWidth < MINLINEKETAS ) nWidth = MINLINEKETAS; // 折り返し幅の最小桁数に設定 - return CLayoutInt( nWidth ); + return nWidth; } /*! Index: sakura_core/view/colors/CColor_Quote.cpp =================================================================== --- sakura_core/view/colors/CColor_Quote.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_Quote.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,36 +0,0 @@ -#include "stdafx.h" -#include "CColor_Quote.h" - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// クォーテーション // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -bool CColor_Quote::BeginColor(const CStringRef& cStr, int nPos) -{ - if(!cStr.IsValid())return false; - - if( cStr.At(nPos) == m_cQuote ){ - const CEditDoc* pcDoc = CEditDoc::GetInstance(0); - const STypeConfig* TypeDataPtr = &pcDoc->m_cDocType.GetDocumentAttribute(); - if( TypeDataPtr->m_ColorInfoArr[this->GetStrategyColor()].m_bDisp ){ /* クォーテーション文字列を表示する */ - /* クォーテーション文字列の終端があるか */ - this->m_nCOMMENTEND = pcDoc->m_cLayoutMgr.Match_Quote( m_cQuote, nPos + 1, cStr ); - return true; - } - } - return false; -} - -bool CColor_Quote::EndColor(const CStringRef& cStr, int nPos) -{ - if( 0 == this->m_nCOMMENTEND ){ - /* クォーテーション文字列の終端があるか */ - const CEditDoc* pcDoc = CEditDoc::GetInstance(0); - this->m_nCOMMENTEND = pcDoc->m_cLayoutMgr.Match_Quote( m_cQuote, nPos, cStr ); - } - else if( nPos == this->m_nCOMMENTEND ){ - return true; - } - - return false; -} Index: sakura_core/view/colors/CColor_KeywordSet.cpp =================================================================== --- sakura_core/view/colors/CColor_KeywordSet.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_KeywordSet.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,78 +0,0 @@ -#include "stdafx.h" -#include "CColor_KeywordSet.h" -#include "parse/CWordParse.h" -#include "util/string_ex2.h" -#include "doc/CLayout.h" -#include "types/CTypeSupport.h" - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// キーワードセット // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -CColor_KeywordSet::CColor_KeywordSet() -: m_nKeywordIndex(0) -, m_nCOMMENTEND(0) -{ -} - - -// 2005.01.13 MIK 強調キーワード数追加に伴う配列化 -bool CColor_KeywordSet::BeginColor(const CStringRef& cStr, int nPos) -{ - if(!cStr.IsValid())return false; - - const CEditDoc* pcDoc = CEditDoc::GetInstance(0); - const STypeConfig* TypeDataPtr = &pcDoc->m_cDocType.GetDocumentAttribute(); - - /* - Summary: - 現在位置からキーワードを抜き出し、そのキーワードが登録単語ならば、色を変える - */ - if( TypeDataPtr->m_ColorInfoArr[COLORIDX_KEYWORD1].m_bDisp && /* 強調キーワードを表示する */ // 2002/03/13 novice - _IsPosKeywordHead(cStr,nPos) && IS_KEYWORD_CHAR(cStr.At(nPos)) - ){ - // キーワードの開始 -> iKeyBegin - int iKeyBegin = nPos; - - // キーワードの終端 -> iKeyEnd - int iKeyEnd; - for( iKeyEnd = iKeyBegin + 1; iKeyEnd <= cStr.GetLength() - 1; ++iKeyEnd ){ - if( !IS_KEYWORD_CHAR( cStr.At(iKeyEnd) ) ){ - break; - } - } - - // キーワードの長さ -> nKeyLen - int nKeyLen = iKeyEnd - iKeyBegin; - - // キーワードが色変え対象であるか調査 - for( int i = 0; i < MAX_KEYWORDSET_PER_TYPE; i++ ) - { - if( TypeDataPtr->m_nKeyWordSetIdx[i] != -1 && // キーワードセット - TypeDataPtr->m_ColorInfoArr[COLORIDX_KEYWORD1 + i].m_bDisp) //MIK - { //MIK - /* n番目のセットから指定キーワードをサーチ 無いときは-1を返す */ //MIK - int nIdx = GetDllShareData().m_Common.m_sSpecialKeyword.m_CKeyWordSetMgr.SearchKeyWord2( //MIK 2000.12.01 binary search - TypeDataPtr->m_nKeyWordSetIdx[i], //MIK - &cStr.GetPtr()[iKeyBegin], //MIK - nKeyLen //MIK - ); //MIK - if( nIdx != -1 ){ //MIK - this->m_nCOMMENTEND = iKeyEnd; //MIK - m_nKeywordIndex = i; - return true; - } //MIK - } - } - } - return false; -} - -bool CColor_KeywordSet::EndColor(const CStringRef& cStr, int nPos) -{ - if( nPos == this->m_nCOMMENTEND ){ - return true; - } - return false; -} - Index: sakura_core/view/colors/CColor_Comment.cpp =================================================================== --- sakura_core/view/colors/CColor_Comment.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_Comment.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,85 +0,0 @@ -#include "stdafx.h" -#include "CColor_Comment.h" -#include "doc/CLayout.h" - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// 行コメント // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -bool CColor_LineComment::BeginColor(const CStringRef& cStr, int nPos) -{ - if(!cStr.IsValid())return false; - - const CEditDoc* pcDoc = CEditDoc::GetInstance(0); - const STypeConfig* TypeDataPtr = &pcDoc->m_cDocType.GetDocumentAttribute(); - - // 行コメント - if( TypeDataPtr->m_ColorInfoArr[COLORIDX_COMMENT].m_bDisp && - TypeDataPtr->m_cLineComment.Match( nPos, cStr ) //@@@ 2002.09.22 YAZAKI - ){ - return true; - } - return false; -} - -bool CColor_LineComment::EndColor(const CStringRef& cStr, int nPos) -{ - //文字列終端 - if( nPos >= cStr.GetLength() ){ - return true; - } - - //改行 - if( WCODE::IsLineDelimiter(cStr.At(nPos)) ){ - return true; - } - - return false; -} - - - - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// ブロックコメント1 // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -bool CColor_BlockComment::BeginColor(const CStringRef& cStr, int nPos) -{ - if(!cStr.IsValid())return false; - - const CEditDoc* pcDoc = CEditDoc::GetInstance(0); - const STypeConfig* TypeDataPtr = &pcDoc->m_cDocType.GetDocumentAttribute(); - - // ブロックコメント - if( TypeDataPtr->m_ColorInfoArr[COLORIDX_COMMENT].m_bDisp && - TypeDataPtr->m_cBlockComments[m_nType].Match_CommentFrom( nPos, cStr ) //@@@ 2002.09.22 YAZAKI - ){ - /* この物理行にブロックコメントの終端があるか */ //@@@ 2002.09.22 YAZAKI - this->m_nCOMMENTEND = TypeDataPtr->m_cBlockComments[m_nType].Match_CommentTo( - nPos + TypeDataPtr->m_cBlockComments[m_nType].getBlockFromLen(), - cStr - ); - - return true; - } - return false; -} - -bool CColor_BlockComment::EndColor(const CStringRef& cStr, int nPos) -{ - if( 0 == this->m_nCOMMENTEND ){ - /* この物理行にブロックコメントの終端があるか */ - const CEditDoc* pcDoc = CEditDoc::GetInstance(0); - const STypeConfig* TypeDataPtr = &pcDoc->m_cDocType.GetDocumentAttribute(); - this->m_nCOMMENTEND = TypeDataPtr->m_cBlockComments[m_nType].Match_CommentTo( - nPos, - cStr - ); - } - else if( nPos == this->m_nCOMMENTEND ){ - return true; - } - return false; -} - Index: sakura_core/view/colors/CColor_Numeric.cpp =================================================================== --- sakura_core/view/colors/CColor_Numeric.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_Numeric.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,589 +0,0 @@ -#include "stdafx.h" -#include "CColor_Numeric.h" -#include "parse/CWordParse.h" -#include "util/string_ex2.h" -#include "doc/CLayout.h" -#include "types/CTypeSupport.h" - -static int IsNumber( const CStringRef& cStr, int offset );/* 数値ならその長さを返す */ //@@@ 2001.02.17 by MIK - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// 半角数値 // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -bool CColor_Numeric::BeginColor(const CStringRef& cStr, int nPos) -{ - if(!cStr.IsValid())return false; - - const CEditDoc* pcDoc = CEditDoc::GetInstance(0); - const STypeConfig* TypeDataPtr = &pcDoc->m_cDocType.GetDocumentAttribute(); - int nnn; - - if( _IsPosKeywordHead(cStr,nPos) && TypeDataPtr->m_ColorInfoArr[COLORIDX_DIGIT].m_bDisp - && (nnn = IsNumber(cStr, nPos)) > 0 ) /* 半角数字を表示する */ - { - /* キーワード文字列の終端をセットする */ - this->m_nCOMMENTEND = nPos + nnn; - return true; /* 半角数値である */ // 2002/03/13 novice - } - return false; -} - - -bool CColor_Numeric::EndColor(const CStringRef& cStr, int nPos) -{ - if( nPos == this->m_nCOMMENTEND ){ - return true; - } - return false; -} - - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// 実装補助 // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -//@@@ 2001.11.07 Start by MIK -//#ifdef COMPILE_COLOR_DIGIT -/* - * 数値なら長さを返す。 - * 10進数の整数または小数。16進数(正数)。 - * 文字列 数値(色分け) - * --------------------- - * 123 123 - * 0123 0123 - * 0xfedc 0xfedc - * -123 -123 - * &H9a &H9a (ただしソース中の#ifを有効にしたとき) - * -0x89a 0x89a - * 0.5 0.5 - * 0.56.1 0.56 , 1 (ただしソース中の#ifを有効にしたら"0.56.1"になる) - * .5 5 (ただしソース中の#ifを有効にしたら".5"になる) - * -.5 5 (ただしソース中の#ifを有効にしたら"-.5"になる) - * 123. 123 - * 0x567.8 0x567 , 8 - */ -/* - * 半角数値 - * 1, 1.2, 1.2.3, .1, 0xabc, 1L, 1F, 1.2f, 0x1L, 0x2F, -.1, -1, 1e2, 1.2e+3, 1.2e-3, -1e0 - * 10進数, 16進数, LF接尾語, 浮動小数点数, 負符号 - * IPアドレスのドット連結(本当は数値じゃないんだよね) - */ -static int IsNumber(const CStringRef& cStr,/*const wchar_t *buf,*/ int offset/*, int length*/) -{ - register const wchar_t* p; - register const wchar_t* q; - register int i = 0; - register int d = 0; - register int f = 0; - - p = cStr.GetPtr() + offset; - q = cStr.GetPtr() + cStr.GetLength(); - - if( *p == L'0' ) /* 10進数,Cの16進数 */ - { - p++; i++; - if( ( p < q ) && ( *p == L'x' ) ) /* Cの16進数 */ - { - p++; i++; - while( p < q ) - { - if( ( *p >= L'0' && *p <= L'9' ) - || ( *p >= L'A' && *p <= L'F' ) - || ( *p >= L'a' && *p <= L'f' ) ) - { - p++; i++; - } - else - { - break; - } - } - /* "0x" なら "0" だけが数値 */ - if( i == 2 ) return 1; - - /* 接尾語 */ - if( p < q ) - { - if( *p == L'L' || *p == L'l' || *p == L'F' || *p == L'f' ) - { - p++; i++; - } - } - return i; - } - else if( *p >= L'0' && *p <= L'9' ) - { - p++; i++; - while( p < q ) - { - if( *p < L'0' || *p > L'9' ) - { - if( *p == L'.' ) - { - if( f == 1 ) break; /* 指数部に入っている */ - d++; - if( d > 1 ) - { - if( *(p - 1) == L'.' ) break; /* "." が連続なら中断 */ - } - } - else if( *p == L'E' || *p == L'e' ) - { - if( f == 1 ) break; /* 指数部に入っている */ - if( p + 2 < q ) - { - if( ( *(p + 1) == L'+' || *(p + 1) == L'-' ) - && ( *(p + 2) >= L'0' && *(p + 2) <= L'9' ) ) - { - p++; i++; - p++; i++; - f = 1; - } - else if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) - { - p++; i++; - f = 1; - } - else - { - break; - } - } - else if( p + 1 < q ) - { - if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) - { - p++; i++; - f = 1; - } - else - { - break; - } - } - else - { - break; - } - } - else - { - break; - } - } - p++; i++; - } - if( *(p - 1) == L'.' ) return i - 1; /* 最後が "." なら含めない */ - /* 接尾語 */ - if( p < q ) - { - if( (( d == 0 ) && ( *p == L'L' || *p == L'l' )) - || *p == L'F' || *p == L'f' ) - { - p++; i++; - } - } - return i; - } - else if( *p == L'.' ) - { - while( p < q ) - { - if( *p < L'0' || *p > L'9' ) - { - if( *p == L'.' ) - { - if( f == 1 ) break; /* 指数部に入っている */ - d++; - if( d > 1 ) - { - if( *(p - 1) == L'.' ) break; /* "." が連続なら中断 */ - } - } - else if( *p == L'E' || *p == L'e' ) - { - if( f == 1 ) break; /* 指数部に入っている */ - if( p + 2 < q ) - { - if( ( *(p + 1) == L'+' || *(p + 1) == L'-' ) - && ( *(p + 2) >= L'0' && *(p + 2) <= L'9' ) ) - { - p++; i++; - p++; i++; - f = 1; - } - else if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) - { - p++; i++; - f = 1; - } - else - { - break; - } - } - else if( p + 1 < q ) - { - if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) - { - p++; i++; - f = 1; - } - else - { - break; - } - } - else - { - break; - } - } - else - { - break; - } - } - p++; i++; - } - if( *(p - 1) == L'.' ) return i - 1; /* 最後が "." なら含めない */ - /* 接尾語 */ - if( p < q ) - { - if( *p == L'F' || *p == L'f' ) - { - p++; i++; - } - } - return i; - } - else if( *p == L'E' || *p == L'e' ) - { - p++; i++; - while( p < q ) - { - if( *p < L'0' || *p > L'9' ) - { - if( ( *p == L'+' || *p == L'-' ) && ( *(p - 1) == L'E' || *(p - 1) == L'e' ) ) - { - if( p + 1 < q ) - { - if( *(p + 1) < L'0' || *(p + 1) > L'9' ) - { - /* "0E+", "0E-" */ - break; - } - } - else - { - /* "0E-", "0E+" */ - break; - } - } - else - { - break; - } - } - p++; i++; - } - if( i == 2 ) return 1; /* "0E", 0e" なら "0" が数値 */ - /* 接尾語 */ - if( p < q ) - { - if( (( d == 0 ) && ( *p == L'L' || *p == L'l' )) - || *p == L'F' || *p == L'f' ) - { - p++; i++; - } - } - return i; - } - else - { - /* "0" だけが数値 */ - /*if( *p == L'.' ) return i - 1;*/ /* 最後が "." なら含めない */ - if( p < q ) - { - if( (( d == 0 ) && ( *p == L'L' || *p == L'l' )) - || *p == L'F' || *p == L'f' ) - { - p++; i++; - } - } - return i; - } - } - - else if( *p >= L'1' && *p <= L'9' ) /* 10進数 */ - { - p++; i++; - while( p < q ) - { - if( *p < L'0' || *p > L'9' ) - { - if( *p == L'.' ) - { - if( f == 1 ) break; /* 指数部に入っている */ - d++; - if( d > 1 ) - { - if( *(p - 1) == L'.' ) break; /* "." が連続なら中断 */ - } - } - else if( *p == L'E' || *p == L'e' ) - { - if( f == 1 ) break; /* 指数部に入っている */ - if( p + 2 < q ) - { - if( ( *(p + 1) == L'+' || *(p + 1) == L'-' ) - && ( *(p + 2) >= L'0' && *(p + 2) <= L'9' ) ) - { - p++; i++; - p++; i++; - f = 1; - } - else if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) - { - p++; i++; - f = 1; - } - else - { - break; - } - } - else if( p + 1 < q ) - { - if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) - { - p++; i++; - f = 1; - } - else - { - break; - } - } - else - { - break; - } - } - else - { - break; - } - } - p++; i++; - } - if( *(p - 1) == L'.' ) return i - 1; /* 最後が "." なら含めない */ - /* 接尾語 */ - if( p < q ) - { - if( (( d == 0 ) && ( *p == L'L' || *p == L'l' )) - || *p == L'F' || *p == L'f' ) - { - p++; i++; - } - } - return i; - } - - else if( *p == L'-' ) /* マイナス */ - { - p++; i++; - while( p < q ) - { - if( *p < L'0' || *p > L'9' ) - { - if( *p == L'.' ) - { - if( f == 1 ) break; /* 指数部に入っている */ - d++; - if( d > 1 ) - { - if( *(p - 1) == L'.' ) break; /* "." が連続なら中断 */ - } - } - else if( *p == L'E' || *p == L'e' ) - { - if( f == 1 ) break; /* 指数部に入っている */ - if( p + 2 < q ) - { - if( ( *(p + 1) == L'+' || *(p + 1) == L'-' ) - && ( *(p + 2) >= L'0' && *(p + 2) <= L'9' ) ) - { - p++; i++; - p++; i++; - f = 1; - } - else if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) - { - p++; i++; - f = 1; - } - else - { - break; - } - } - else if( p + 1 < q ) - { - if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) - { - p++; i++; - f = 1; - } - else - { - break; - } - } - else - { - break; - } - } - else - { - break; - } - } - p++; i++; - } - /* "-", "-." だけなら数値でない */ - //@@@ 2001.11.09 start MIK - //if( i <= 2 ) return 0; - //if( *(p - 1) == L'.' ) return i - 1; /* 最後が "." なら含めない */ - if( i == 1 ) return 0; - if( *(p - 1) == L'.' ) - { - i--; - if( i == 1 ) return 0; - return i; - } //@@@ 2001.11.09 end MIK - /* 接尾語 */ - if( p < q ) - { - if( (( d == 0 ) && ( *p == L'L' || *p == L'l' )) - || *p == L'F' || *p == L'f' ) - { - p++; i++; - } - } - return i; - } - - else if( *p == L'.' ) /* 小数点 */ - { - d++; - p++; i++; - while( p < q ) - { - if( *p < L'0' || *p > L'9' ) - { - if( *p == L'.' ) - { - if( f == 1 ) break; /* 指数部に入っている */ - d++; - if( d > 1 ) - { - if( *(p - 1) == L'.' ) break; /* "." が連続なら中断 */ - } - } - else if( *p == L'E' || *p == L'e' ) - { - if( f == 1 ) break; /* 指数部に入っている */ - if( p + 2 < q ) - { - if( ( *(p + 1) == L'+' || *(p + 1) == L'-' ) - && ( *(p + 2) >= L'0' && *(p + 2) <= L'9' ) ) - { - p++; i++; - p++; i++; - f = 1; - } - else if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) - { - p++; i++; - f = 1; - } - else - { - break; - } - } - else if( p + 1 < q ) - { - if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) - { - p++; i++; - f = 1; - } - else - { - break; - } - } - else - { - break; - } - } - else - { - break; - } - } - p++; i++; - } - /* "." だけなら数値でない */ - if( i == 1 ) return 0; - if( *(p - 1) == L'.' ) return i - 1; /* 最後が "." なら含めない */ - /* 接尾語 */ - if( p < q ) - { - if( *p == L'F' || *p == L'f' ) - { - p++; i++; - } - } - return i; - } - -#if 0 - else if( *p == L'&' ) /* VBの16進数 */ - { - p++; i++; - if( ( p < q ) && ( *p == L'H' ) ) - { - p++; i++; - while( p < q ) - { - if( ( *p >= L'0' && *p <= L'9' ) - || ( *p >= L'A' && *p <= L'F' ) - || ( *p >= L'a' && *p <= L'f' ) ) - { - p++; i++; - } - else - { - break; - } - } - /* "&H" だけなら数値でない */ - if( i == 2 ) i = 0; - return i; - } - - /* "&" だけなら数値でない */ - return 0; - } -#endif - - /* 数値ではない */ - return 0; -} -//@@@ 2001.11.07 End by MIK Index: sakura_core/view/colors/CColor_Quote.h =================================================================== --- sakura_core/view/colors/CColor_Quote.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_Quote.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,30 +0,0 @@ -#pragma once - -#include "view/colors/CColorStrategy.h" - - - -class CColor_Quote : public CColorStrategy{ -public: - CColor_Quote(wchar_t cQuote) : m_cQuote(cQuote), m_nCOMMENTEND(0) { } - virtual EColorIndexType GetStrategyColor() const = 0; - virtual void InitStrategyStatus(){ m_nCOMMENTEND = 0; } - virtual bool BeginColor(const CStringRef& cStr, int nPos); - virtual bool EndColor(const CStringRef& cStr, int nPos); -private: - wchar_t m_cQuote; - int m_nCOMMENTEND; -}; - - -class CColor_SingleQuote : public CColor_Quote{ -public: - CColor_SingleQuote() : CColor_Quote(L'\'') { } - virtual EColorIndexType GetStrategyColor() const{ return COLORIDX_SSTRING; } -}; - -class CColor_DoubleQuote : public CColor_Quote{ -public: - CColor_DoubleQuote() : CColor_Quote(L'"') { } - virtual EColorIndexType GetStrategyColor() const{ return COLORIDX_WSTRING; } -}; Index: sakura_core/view/colors/CColor_Url.cpp =================================================================== --- sakura_core/view/colors/CColor_Url.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_Url.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,36 +0,0 @@ -#include "stdafx.h" -#include "CColor_Url.h" -#include "parse/CWordParse.h" -#include "doc/CLayout.h" -#include "types/CTypeSupport.h" - - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// URL // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -bool CColor_Url::BeginColor(const CStringRef& cStr, int nPos) -{ - if(!cStr.IsValid())return false; - - const CEditDoc* pcDoc = CEditDoc::GetInstance(0); - const STypeConfig* TypeDataPtr = &pcDoc->m_cDocType.GetDocumentAttribute(); - int nUrlLen; - - if( _IsPosKeywordHead(cStr,nPos) && TypeDataPtr->m_ColorInfoArr[COLORIDX_URL].m_bDisp /* URLを表示する */ - && IsURL( cStr.GetPtr() + nPos, cStr.GetLength() - nPos, &nUrlLen ) /* 指定アドレスがURLの先頭ならばTRUEとその長さを返す */ - ){ - this->m_nCOMMENTEND = nPos + nUrlLen; - return true; - } - return false; -} - -bool CColor_Url::EndColor(const CStringRef& cStr, int nPos) -{ - if( nPos == this->m_nCOMMENTEND ){ - return true; - } - return false; -} - Index: sakura_core/view/colors/CColorStrategy.cpp =================================================================== --- sakura_core/view/colors/CColorStrategy.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColorStrategy.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,252 +0,0 @@ -#include "stdafx.h" -#include "view/colors/CColorStrategy.h" -#include "CColor_Comment.h" -#include "CColor_Quote.h" -#include "CColor_RegexKeyword.h" -#include "CColor_Found.h" -#include "CColor_Url.h" -#include "CColor_Numeric.h" -#include "CColor_KeywordSet.h" -#include "CColor_Found.h" -#include "doc/CLayout.h" - - - - -bool _IsPosKeywordHead(const CStringRef& cStr, int nPos) -{ - return (nPos==0 || !IS_KEYWORD_CHAR(cStr.At(nPos-1))); -} - - -CLogicInt SColorStrategyInfo::GetPosInLayout() const -{ - return nPosInLogic - pDispPos->GetLayoutRef()->GetLogicOffset(); -} - -const CDocLine* SColorStrategyInfo::GetDocLine() const -{ - return pDispPos->GetLayoutRef()->GetDocLineRef(); -} - -const CLayout* SColorStrategyInfo::GetLayout() const -{ - return pDispPos->GetLayoutRef(); -} - -void SColorStrategyInfo::DoChangeColor(const CStringRef& cLineStr) -{ - CColorStrategyPool* pool = CColorStrategyPool::Instance(); - pool->SetCurrentView(this->pcView); - CColorStrategy* pcFound = pool->GetFoundStrategy(); - - //検索色終了 - if(this->pStrategyFound){ - if(this->pStrategyFound->EndColor(cLineStr,this->GetPosInLogic())){ - this->pStrategyFound = NULL; - this->ChangeColor(this->GetCurrentColor()); - } - } - - //検索色開始 - if(!this->pStrategyFound){ - if(pcFound->BeginColor(cLineStr,this->GetPosInLogic())){ - this->pStrategyFound = pcFound; - this->ChangeColor(this->GetCurrentColor()); - } - } - - //色終了 - if(this->pStrategy){ - if(this->pStrategy->EndColor(cLineStr,this->GetPosInLogic())){ - this->pStrategy = NULL; - this->ChangeColor(this->GetCurrentColor()); - } - } - - //色開始 - if(!this->pStrategy){ - for(int i=0;iGetStrategyCount();i++){ - if(pool->GetStrategy(i)->BeginColor(cLineStr,this->GetPosInLogic())){ - this->pStrategy = pool->GetStrategy(i); - this->ChangeColor(this->GetCurrentColor()); - break; - } - } - } -} - -EColorIndexType SColorStrategyInfo::GetCurrentColor() const -{ - if(pStrategyFound){ - return pStrategyFound->GetStrategyColor(); - } - else{ - return pStrategy->GetStrategyColorSafe(); - } -} - - - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// プール // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -CColorStrategyPool::CColorStrategyPool() -{ - m_pcView = CEditWnd::Instance()->m_pcEditViewArr[0]; - m_pcFoundStrategy = new CColor_Found; -// m_vStrategies.push_back(new CColor_Found); // マッチ文字列 - m_vStrategies.push_back(new CColor_RegexKeyword); // 正規表現キーワード - m_vStrategies.push_back(new CColor_LineComment); // 行コメント - m_vStrategies.push_back(new CColor_BlockComment(0)); // ブロックコメント - m_vStrategies.push_back(new CColor_BlockComment(1)); // ブロックコメント2 - m_vStrategies.push_back(new CColor_SingleQuote); // シングルクォーテーション文字列 - m_vStrategies.push_back(new CColor_DoubleQuote); // ダブルクォーテーション文字列 - m_vStrategies.push_back(new CColor_Url); // URL - m_vStrategies.push_back(new CColor_Numeric); // 半角数字 - m_vStrategies.push_back(new CColor_KeywordSet); // キーワードセット - - // CheckColorMODE 用 - m_pcLineComment = (CColor_LineComment*)GetStrategyByColor(COLORIDX_COMMENT); // 行コメント - m_pcBlockComment1 = (CColor_BlockComment*)GetStrategyByColor(COLORIDX_BLOCK1); // ブロックコメント - m_pcBlockComment2 = (CColor_BlockComment*)GetStrategyByColor(COLORIDX_BLOCK2); // ブロックコメント2 - m_pcSingleQuote = (CColor_SingleQuote*)GetStrategyByColor(COLORIDX_SSTRING); // シングルクォーテーション文字列 - m_pcDoubleQuote = (CColor_DoubleQuote*)GetStrategyByColor(COLORIDX_WSTRING); // ダブルクォーテーション文字列 -} - -CColorStrategyPool::~CColorStrategyPool() -{ - SAFE_DELETE(m_pcFoundStrategy); - for(int i=0;i<(int)m_vStrategies.size();i++){ - delete m_vStrategies[i]; - } - m_vStrategies.clear(); -} - -CColorStrategy* CColorStrategyPool::GetStrategyByColor(EColorIndexType eColor) const -{ - if(m_pcFoundStrategy->GetStrategyColor()==eColor){ - return m_pcFoundStrategy; - } - for(int i=0;i<(int)m_vStrategies.size();i++){ - if(m_vStrategies[i]->GetStrategyColor()==eColor){ - return m_vStrategies[i]; - } - } - return NULL; -} - -// 2005.11.20 Mocaコメントの色分けがON/OFF関係なく行われていたバグを修正 -bool CColorStrategyPool::CheckColorMODE( - CColorStrategy** ppcColorStrategy, //!< [in/out] - int nPos, - const CStringRef& cLineStr -) -{ - //色終了 - if(*ppcColorStrategy){ - if((*ppcColorStrategy)->EndColor(cLineStr,nPos)){ - *ppcColorStrategy = NULL; - return true; - } - } - - //色開始 - if(!*ppcColorStrategy){ - // CheckColorMODE はレイアウト処理全体のボトルネックになるくらい頻繁に呼び出される - // 基本クラスからの動的仮想関数呼び出しを使用すると無視できないほどのオーバヘッドになる模様 - // ここはエレガントさよりも性能優先で個々の派生クラスから BeginColor() を呼び出す - if(m_pcLineComment->BeginColor(cLineStr,nPos)){ *ppcColorStrategy = m_pcLineComment; return false; } - if(m_pcBlockComment1->BeginColor(cLineStr,nPos)){ *ppcColorStrategy = m_pcBlockComment1; return false; } - if(m_pcBlockComment2->BeginColor(cLineStr,nPos)){ *ppcColorStrategy = m_pcBlockComment2; return false; } - if(m_pcSingleQuote->BeginColor(cLineStr,nPos)){ *ppcColorStrategy = m_pcSingleQuote; return false; } - if(m_pcDoubleQuote->BeginColor(cLineStr,nPos)){ *ppcColorStrategy = m_pcDoubleQuote; return false; } - } - - return false; -} - - - -/*! - iniの色設定を番号でなく文字列で書き出す。(added by Stonee, 2001/01/12, 2001/01/15) - 配列の順番は共有メモリ中のデータの順番と一致している。 - - @note 数値による内部的対応はglobal.hで行っているので参照のこと。(Mar. 7, 2001 jepro) - CShareDataからglobalに移動 -*/ -const SColorAttributeData g_ColorAttributeArr[] = -{ - {_T("TXT"), COLOR_ATTRIB_FORCE_DISP | COLOR_ATTRIB_NO_EFFECTS}, - {_T("RUL"), COLOR_ATTRIB_NO_EFFECTS}, - {_T("CAR"), COLOR_ATTRIB_FORCE_DISP | COLOR_ATTRIB_NO_BACK | COLOR_ATTRIB_NO_EFFECTS}, // キャレット // 2006.12.07 ryoji - {_T("IME"), COLOR_ATTRIB_NO_BACK | COLOR_ATTRIB_NO_EFFECTS}, // IMEキャレット // 2006.12.07 ryoji - {_T("UND"), COLOR_ATTRIB_NO_BACK | COLOR_ATTRIB_NO_EFFECTS}, - {_T("CVL"), COLOR_ATTRIB_NO_BACK | ( COLOR_ATTRIB_NO_EFFECTS & ~COLOR_ATTRIB_NO_BOLD )}, // 2007.09.09 Moca カーソル位置縦線 - {_T("LNO"), 0}, - {_T("MOD"), 0}, - {_T("TAB"), 0}, - {_T("SPC"), 0}, //2002.04.28 Add By KK - {_T("ZEN"), 0}, - {_T("CTL"), 0}, - {_T("EOL"), 0}, - {_T("RAP"), 0}, - {_T("VER"), 0}, // 2005.11.08 Moca 指定桁縦線 - {_T("EOF"), 0}, - {_T("NUM"), 0}, //@@@ 2001.02.17 by MIK 半角数値の強調 - {_T("FND"), 0}, - {_T("KW1"), 0}, - {_T("KW2"), 0}, - {_T("KW3"), 0}, //@@@ 2003.01.13 by MIK 強調キーワード3-10 - {_T("KW4"), 0}, - {_T("KW5"), 0}, - {_T("KW6"), 0}, - {_T("KW7"), 0}, - {_T("KW8"), 0}, - {_T("KW9"), 0}, - {_T("KWA"), 0}, - {_T("CMT"), 0}, - {_T("SQT"), 0}, - {_T("WQT"), 0}, - {_T("URL"), 0}, - {_T("RK1"), 0}, //@@@ 2001.11.17 add MIK - {_T("RK2"), 0}, //@@@ 2001.11.17 add MIK - {_T("RK3"), 0}, //@@@ 2001.11.17 add MIK - {_T("RK4"), 0}, //@@@ 2001.11.17 add MIK - {_T("RK5"), 0}, //@@@ 2001.11.17 add MIK - {_T("RK6"), 0}, //@@@ 2001.11.17 add MIK - {_T("RK7"), 0}, //@@@ 2001.11.17 add MIK - {_T("RK8"), 0}, //@@@ 2001.11.17 add MIK - {_T("RK9"), 0}, //@@@ 2001.11.17 add MIK - {_T("RKA"), 0}, //@@@ 2001.11.17 add MIK - {_T("DFA"), 0}, //DIFF追加 //@@@ 2002.06.01 MIK - {_T("DFC"), 0}, //DIFF変更 //@@@ 2002.06.01 MIK - {_T("DFD"), 0}, //DIFF削除 //@@@ 2002.06.01 MIK - {_T("BRC"), 0}, //対括弧 // 02/09/18 ai Add - {_T("MRK"), 0}, //ブックマーク // 02/10/16 ai Add - {_T("LAST"), 0} // Not Used -}; - - - -/* - * カラー名からインデックス番号に変換する - */ -SAKURA_CORE_API int GetColorIndexByName( const TCHAR *name ) -{ - int i; - for( i = 0; i < COLORIDX_LAST; i++ ) - { - if( _tcscmp( name, g_ColorAttributeArr[i].szName ) == 0 ) return i; - } - return -1; -} - -/* - * インデックス番号からカラー名に変換する - */ -SAKURA_CORE_API const TCHAR* GetColorNameByIndex( int index ) -{ - return g_ColorAttributeArr[index].szName; -} Index: sakura_core/view/colors/CColor_KeywordSet.h =================================================================== --- sakura_core/view/colors/CColor_KeywordSet.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_KeywordSet.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,15 +0,0 @@ -#pragma once - -#include "view/colors/CColorStrategy.h" - -class CColor_KeywordSet : public CColorStrategy{ -public: - CColor_KeywordSet(); - virtual EColorIndexType GetStrategyColor() const{ return (EColorIndexType)(COLORIDX_KEYWORD1 + m_nKeywordIndex); } - virtual void InitStrategyStatus(){ m_nCOMMENTEND = 0; } - virtual bool BeginColor(const CStringRef& cStr, int nPos); - virtual bool EndColor(const CStringRef& cStr, int nPos); -private: - int m_nKeywordIndex; - int m_nCOMMENTEND; -}; Index: sakura_core/view/colors/CColor_Comment.h =================================================================== --- sakura_core/view/colors/CColor_Comment.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_Comment.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,35 +0,0 @@ -#pragma once - -#include "view/colors/CColorStrategy.h" - - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// 行コメント // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -class CColor_LineComment : public CColorStrategy{ -public: - virtual EColorIndexType GetStrategyColor() const{ return COLORIDX_COMMENT; } - virtual void InitStrategyStatus(){} - virtual bool BeginColor(const CStringRef& cStr, int nPos); - virtual bool EndColor(const CStringRef& cStr, int nPos); -}; - - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// ブロックコメント1 // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -class CColor_BlockComment : public CColorStrategy{ -public: - CColor_BlockComment(int nType) : m_nType(nType), m_nCOMMENTEND(0) { } - virtual EColorIndexType GetStrategyColor() const{ return (EColorIndexType)(COLORIDX_BLOCK1 + m_nType); } - virtual void InitStrategyStatus(){ m_nCOMMENTEND = 0; } - virtual bool BeginColor(const CStringRef& cStr, int nPos); - virtual bool EndColor(const CStringRef& cStr, int nPos); -private: - int m_nType; //0 or 1 (コメント種) - int m_nCOMMENTEND; -}; - - Index: sakura_core/view/colors/CColor_Numeric.h =================================================================== --- sakura_core/view/colors/CColor_Numeric.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_Numeric.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,14 +0,0 @@ -#pragma once - -#include "view/colors/CColorStrategy.h" - -class CColor_Numeric : public CColorStrategy{ -public: - CColor_Numeric() : m_nCOMMENTEND(0) { } - virtual EColorIndexType GetStrategyColor() const{ return COLORIDX_DIGIT; } - virtual void InitStrategyStatus(){ m_nCOMMENTEND = 0; } - virtual bool BeginColor(const CStringRef& cStr, int nPos); - virtual bool EndColor(const CStringRef& cStr, int nPos); -private: - int m_nCOMMENTEND; -}; Index: sakura_core/view/colors/CColor_Url.h =================================================================== --- sakura_core/view/colors/CColor_Url.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_Url.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,14 +0,0 @@ -#pragma once - -#include "view/colors/CColorStrategy.h" - -class CColor_Url : public CColorStrategy{ -public: - CColor_Url() : m_nCOMMENTEND(0) { } - virtual EColorIndexType GetStrategyColor() const{ return COLORIDX_URL; } - virtual void InitStrategyStatus(){ m_nCOMMENTEND = 0; } - virtual bool BeginColor(const CStringRef& cStr, int nPos); - virtual bool EndColor(const CStringRef& cStr, int nPos); -private: - int m_nCOMMENTEND; -}; Index: sakura_core/view/colors/CColorStrategy.h =================================================================== --- sakura_core/view/colors/CColorStrategy.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColorStrategy.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,230 +0,0 @@ -#pragma once - -bool _IsPosKeywordHead(const CStringRef& cStr, int nPos); - -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // -// 色定数 // -// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - -// Stonee 注: 2000/01/12 -// ここを変更したときは、global.cpp のg_ColorAttributeArrの定義も変更して下さい。 -// From Here Sept. 18, 2000 JEPRO 順番を大幅に入れ替えた -// 2007.09.09 Moca 中間の定義はお任せに変更 -SAKURA_CORE_API enum EColorIndexType { - COLORIDX_TEXT = 0, // テキスト - COLORIDX_RULER, // ルーラー - COLORIDX_CARET, // キャレット // 2006.12.07 ryoji - COLORIDX_CARET_IME, // IMEキャレット // 2006.12.07 ryoji - COLORIDX_UNDERLINE, // カーソル行アンダーライン - COLORIDX_CURSORVLINE, // カーソル位置縦線 // 2006.05.13 Moca - COLORIDX_GYOU, // 行番号 - COLORIDX_GYOU_MOD, // 行番号(変更行) - COLORIDX_TAB, // TAB記号 - COLORIDX_SPACE, // 半角空白 //2002.04.28 Add by KK 以降全て+1 - COLORIDX_ZENSPACE, // 日本語空白 - COLORIDX_CTRLCODE, // コントロールコード - COLORIDX_EOL, // 改行記号 - COLORIDX_WRAP, // 折り返し記号 - COLORIDX_VERTLINE, // 指定桁縦線 // 2005.11.08 Moca - COLORIDX_EOF, // EOF記号 - COLORIDX_DIGIT, // 半角数値 //@@@ 2001.02.17 by MIK //色設定Ver.3からユーザファイルに対しては文字列で処理しているのでリナンバリングしてもよい. Mar. 7, 2001 JEPRO noted - COLORIDX_SEARCH, // 検索文字列 - COLORIDX_KEYWORD1, // 強調キーワード1 // 2002/03/13 novice - COLORIDX_KEYWORD2, // 強調キーワード2 // 2002/03/13 novice //MIK ADDED - COLORIDX_KEYWORD3, // 強調キーワード3 // 2005.01.13 MIK 3-10 added - COLORIDX_KEYWORD4, // 強調キーワード4 - COLORIDX_KEYWORD5, // 強調キーワード5 - COLORIDX_KEYWORD6, // 強調キーワード6 - COLORIDX_KEYWORD7, // 強調キーワード7 - COLORIDX_KEYWORD8, // 強調キーワード8 - COLORIDX_KEYWORD9, // 強調キーワード9 - COLORIDX_KEYWORD10, // 強調キーワード10 - COLORIDX_COMMENT, // 行コメント //Dec. 4, 2000 shifted by MIK - COLORIDX_SSTRING, // シングルクォーテーション文字列 //Dec. 4, 2000 shifted by MIK - COLORIDX_WSTRING, // ダブルクォーテーション文字列 //Dec. 4, 2000 shifted by MIK - COLORIDX_URL, // URL //Dec. 4, 2000 shifted by MIK - COLORIDX_REGEX1, // 正規表現キーワード1 //@@@ 2001.11.17 add MIK - COLORIDX_REGEX2, // 正規表現キーワード2 //@@@ 2001.11.17 add MIK - COLORIDX_REGEX3, // 正規表現キーワード3 //@@@ 2001.11.17 add MIK - COLORIDX_REGEX4, // 正規表現キーワード4 //@@@ 2001.11.17 add MIK - COLORIDX_REGEX5, // 正規表現キーワード5 //@@@ 2001.11.17 add MIK - COLORIDX_REGEX6, // 正規表現キーワード6 //@@@ 2001.11.17 add MIK - COLORIDX_REGEX7, // 正規表現キーワード7 //@@@ 2001.11.17 add MIK - COLORIDX_REGEX8, // 正規表現キーワード8 //@@@ 2001.11.17 add MIK - COLORIDX_REGEX9, // 正規表現キーワード9 //@@@ 2001.11.17 add MIK - COLORIDX_REGEX10, // 正規表現キーワード10 //@@@ 2001.11.17 add MIK - COLORIDX_DIFF_APPEND, // DIFF追加 //@@@ 2002.06.01 MIK - COLORIDX_DIFF_CHANGE, // DIFF追加 //@@@ 2002.06.01 MIK - COLORIDX_DIFF_DELETE, // DIFF追加 //@@@ 2002.06.01 MIK - COLORIDX_BRACKET_PAIR, // 対括弧 // 02/09/18 ai Add - COLORIDX_MARK, // ブックマーク // 02/10/16 ai Add - - //カラーの最後 - COLORIDX_LAST, - - //カラー表示制御用 - COLORIDX_BLOCK1, // ブロックコメント1(文字色と背景色は行コメントと同じ) - COLORIDX_BLOCK2, // ブロックコメント2(文字色と背景色は行コメントと同じ) - - //1000- : カラー表示制御用(正規表現キーワード) - COLORIDX_REGEX_FIRST = 1000, - COLORIDX_REGEX_LAST = COLORIDX_REGEX_FIRST + COLORIDX_LAST - 1, - - // -- -- 別名 -- -- // - COLORIDX_DEFAULT = COLORIDX_TEXT, -}; -// To Here Sept. 18, 2000 - -//正規表現キーワードのEColorIndexType値を作る関数 -inline EColorIndexType ToColorIndexType_RegularExpression(const int& nRegexColorIndex) -{ - return (EColorIndexType)(COLORIDX_REGEX_FIRST + nRegexColorIndex); -} - -//正規表現キーワードのEColorIndexType値かどうか -inline bool IsRegularExpression(const EColorIndexType& eColorIndex) -{ - return (eColorIndex >= COLORIDX_REGEX_FIRST && eColorIndex <= COLORIDX_REGEX_LAST); -} - -//正規表現キーワードのEColorIndexType値を色番号に戻す関数 -inline int ToColorInfoArrIndex_RegularExpression(const EColorIndexType& eRegexColorIndex) -{ - return eRegexColorIndex - COLORIDX_REGEX_FIRST; -} - -//EColorIndexType値を色番号に変換する関数 -inline int ToColorInfoArrIndex(const EColorIndexType& eColorIndex) -{ - if(eColorIndex>=0 && eColorIndex //auto_ptr - -struct SColorStrategyInfo{ - SColorStrategyInfo() : sDispPosBegin(0,0), pStrategy(NULL), pStrategyFound(NULL) {} - - //参照 - CEditView* pcView; - CGraphics gr; //(SColorInfoでは未使用) - - //スキャン位置 - LPCWSTR pLineOfLogic; - CLogicInt nPosInLogic; - - //描画位置 - DispPos* pDispPos; - DispPos sDispPosBegin; - - //色変え - CColorStrategy* pStrategy; - CColorStrategy* pStrategyFound; - - //! 色の切り替え - void ChangeColor(EColorIndexType eNewColor) - { - this->pcView->SetCurrentColor( this->gr, eNewColor ); - } - - void DoChangeColor(const CStringRef& cLineStr); - EColorIndexType GetCurrentColor() const; - - //! 現在のスキャン位置 - CLogicInt GetPosInLogic() const - { - return nPosInLogic; - } - CLogicInt GetPosInLayout() const; - const CDocLine* GetDocLine() const; - const CLayout* GetLayout() const; -}; - -class CColorStrategy{ -public: - virtual ~CColorStrategy(){} - //! 色定義 - virtual EColorIndexType GetStrategyColor() const = 0; - //! 色切り替え開始を検出したら、その直前までの描画を行い、さらに色設定を行う。 - virtual void InitStrategyStatus() = 0; - virtual bool BeginColor(const CStringRef& cStr, int nPos){ return false; } - virtual bool EndColor(const CStringRef& cStr, int nPos){ return true; } - //イベント - virtual void OnStartScanLogic(){} - - //#######ラップ - EColorIndexType GetStrategyColorSafe() const{ if(this)return GetStrategyColor(); else return COLORIDX_TEXT; } -}; - -#include "util/design_template.h" -#include -class CColor_LineComment; -class CColor_BlockComment; -class CColor_BlockComment; -class CColor_SingleQuote; -class CColor_DoubleQuote; - -class CColorStrategyPool : public TSingleton{ -public: - //コンストラクタ・デストラクタ - CColorStrategyPool(); - virtual ~CColorStrategyPool(); - - //取得 - CColorStrategy* GetStrategy(int nIndex) const{ return m_vStrategies[nIndex]; } - int GetStrategyCount() const{ return (int)m_vStrategies.size(); } - CColorStrategy* GetStrategyByColor(EColorIndexType eColor) const; - - //特定取得 - CColorStrategy* GetFoundStrategy() const{ return m_pcFoundStrategy; } - - //イベント - void NotifyOnStartScanLogic() - { - m_pcFoundStrategy->OnStartScanLogic(); - for(int i=0;iOnStartScanLogic(); - } - } - - /* - || 色分け - */ - //@@@ 2002.09.22 YAZAKI - // 2005.11.21 Moca 引用符の色分け情報を引数から除去 - bool CheckColorMODE( CColorStrategy** ppcColorStrategy, int nPos, const CStringRef& cLineStr ); - - //ビューの設定・取得 - CEditView* GetCurrentView(void) const{ return m_pcView; } - void SetCurrentView(CEditView* pcView) { m_pcView = pcView; } - -private: - std::vector m_vStrategies; - CColorStrategy* m_pcFoundStrategy; - - CColor_LineComment* m_pcLineComment; - CColor_BlockComment* m_pcBlockComment1; - CColor_BlockComment* m_pcBlockComment2; - CColor_SingleQuote* m_pcSingleQuote; - CColor_DoubleQuote* m_pcDoubleQuote; - - CEditView* m_pcView; -}; Index: sakura_core/view/colors/CColor_Found.cpp =================================================================== --- sakura_core/view/colors/CColor_Found.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_Found.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,57 +0,0 @@ -#include "stdafx.h" -#include "CColor_Found.h" -#include "types/CTypeSupport.h" - - -void CColor_Found::OnStartScanLogic() -{ - m_bSearchFlg = true; - m_nSearchStart = CLogicInt(-1); - m_nSearchEnd = CLogicInt(-1); -} - -bool CColor_Found::BeginColor(const CStringRef& cStr, int nPos) -{ - if(!cStr.IsValid())return false; - - const CEditDoc* pcDoc = CEditDoc::GetInstance(0); - const STypeConfig* TypeDataPtr = &pcDoc->m_cDocType.GetDocumentAttribute(); - - const CEditView* pcView = CColorStrategyPool::Instance()->GetCurrentView(); - if( !pcView->m_bCurSrchKeyMark || !CTypeSupport(pcView,COLORIDX_SEARCH).IsDisp() ){ - return false; - } - - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - // 検索ヒットフラグ設定 -> bSearchStringMode // - // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // - // 2002.02.08 hor 正規表現の検索文字列マークを少し高速化 - if(!pcView->m_sCurSearchOption.bRegularExp || (m_bSearchFlg && m_nSearchStart < nPos)){ - m_bSearchFlg = pcView->IsSearchString( - cStr, - CLogicInt(nPos), - &m_nSearchStart, - &m_nSearchEnd - ); - } - //マッチ文字列検出 - if( m_bSearchFlg && m_nSearchStart==nPos){ - return true; - } - return false; -} - -bool CColor_Found::EndColor(const CStringRef& cStr, int nPos) -{ - const CEditDoc* pcDoc = CEditDoc::GetInstance(0); - const STypeConfig* TypeDataPtr = &pcDoc->m_cDocType.GetDocumentAttribute(); - - //マッチ文字列終了検出 - if( m_nSearchEnd <= nPos ){ //+ == では行頭文字の場合、m_nSearchEndも0であるために文字色の解除ができないバグを修正 2003.05.03 かろと - // -- -- マッチ文字列を描画 -- -- // - - return true; - } - - return false; -} Index: sakura_core/view/colors/CColor_RegexKeyword.cpp =================================================================== --- sakura_core/view/colors/CColor_RegexKeyword.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_RegexKeyword.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,35 +0,0 @@ -#include "stdafx.h" -#include "CColor_RegexKeyword.h" - - -bool CColor_RegexKeyword::BeginColor(const CStringRef& cStr, int nPos) -{ - if(!cStr.IsValid())return false; - - const CEditDoc* pcDoc = CEditDoc::GetInstance(0); - const STypeConfig* TypeDataPtr = &pcDoc->m_cDocType.GetDocumentAttribute(); - int nMatchLen; - int nMatchColor; - - const CEditView* pcView = CColorStrategyPool::Instance()->GetCurrentView(); - - //正規表現キーワード - if( TypeDataPtr->m_bUseRegexKeyword - && pcView->m_cRegexKeyword->RegexIsKeyword( cStr, nPos, &nMatchLen, &nMatchColor ) - ){ - this->m_nCOMMENTEND = nPos + nMatchLen; /* キーワード文字列の終端をセットする */ - this->m_nCOMMENTMODE = ToColorIndexType_RegularExpression(nMatchColor); - return true; - } - return false; -} - - -bool CColor_RegexKeyword::EndColor(const CStringRef& cStr, int nPos) -{ - if( nPos == this->m_nCOMMENTEND ){ - return true; - } - return false; -} - Index: sakura_core/view/colors/CColor_Found.h =================================================================== --- sakura_core/view/colors/CColor_Found.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_Found.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,19 +0,0 @@ -#pragma once - -#include "view/colors/CColorStrategy.h" - -class CColor_Found : public CColorStrategy{ -public: - virtual EColorIndexType GetStrategyColor() const{ return COLORIDX_SEARCH; } - //色替え - virtual void InitStrategyStatus(){ } //############要検証 - virtual bool BeginColor(const CStringRef& cStr, int nPos); - virtual bool EndColor(const CStringRef& cStr, int nPos); - //イベント - virtual void OnStartScanLogic(); - -private: - bool m_bSearchFlg; - CLogicInt m_nSearchStart; - CLogicInt m_nSearchEnd; -}; Index: sakura_core/view/colors/CColor_RegexKeyword.h =================================================================== --- sakura_core/view/colors/CColor_RegexKeyword.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/colors/CColor_RegexKeyword.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -1,17 +0,0 @@ -#pragma once - -#include "view/colors/CColorStrategy.h" - - - -class CColor_RegexKeyword : public CColorStrategy{ -public: - CColor_RegexKeyword() : m_nCOMMENTEND(0), m_nCOMMENTMODE(EColorIndexType(COLORIDX_REGEX_FIRST + COLORIDX_DEFAULT)) { } - virtual EColorIndexType GetStrategyColor() const{ return m_nCOMMENTMODE; } - virtual void InitStrategyStatus(){ m_nCOMMENTEND = 0; m_nCOMMENTMODE = EColorIndexType(COLORIDX_REGEX_FIRST + COLORIDX_DEFAULT); } - virtual bool BeginColor(const CStringRef& cStr, int nPos); - virtual bool EndColor(const CStringRef& cStr, int nPos); -private: - int m_nCOMMENTEND; - EColorIndexType m_nCOMMENTMODE; -}; Index: sakura_core/view/colors/CColorML_KeywordSet.h =================================================================== --- sakura_core/view/colors/CColorML_KeywordSet.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_KeywordSet.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,19 @@ +#pragma once +#include "view/colors/ColorMLStrategy.h" + + +class CColorML_KeywordSet +: public CColorML_Base +{ +public: + CColorML_KeywordSet( const EColorIndexType color, const int keywordSet ) + : color( color ), keywordSet( keywordSet ) + {} + + virtual const CLogicInt IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + virtual const CLogicInt IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + +private: + const EColorIndexType color; + const int keywordSet; +}; Index: sakura_core/view/colors/ColorMLStrategy.h =================================================================== --- sakura_core/view/colors/ColorMLStrategy.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/ColorMLStrategy.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,127 @@ +#pragma once +#include +#include +#include "DivArray.h" +#include "basis/SakuraBasis.h" // CLogicInt +class CEditDoc; +enum EColorIndexType; + + +/** 個々の色分け戦略のベースクラス。 + 正規表現キーワードやダブルクォーテーション文字列、数値などの色分けを担当するものが + これを継承して、ColorMLStrategyに対し、共通のインターフェイスを提供する。 +*/ +class CColorML_Base +{ +public: + virtual ~CColorML_Base() {} + + /** 戻り値で色分け対象の始まりを示す。 + 色分け対象が '''nPosWithinLineから'''始まっていれば、outColorにその色をセットし、その色が継続する文字数を返す。負数は行末までを意味する。 + */ + virtual const CLogicInt IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) = 0; + + /** 戻り値で色分け対象の終わりを示す。 + 先立つ IsStartOfKeyword()呼び出しが非0 を返した後に、非0 を返すまで何度も呼ばれることになる。 + 引数と戻り値の意味は IsStartOfKeyword()と基本的に同じであるが、nPosWithinLineはキーワードがその位置から始まっていることを要求しない。 + IsStartOfKeyword()で見つけた色分け対象の、終端を示す役目を持つ。色の変わり目を示すこともできる。 + N行目の行末までを色分け対象にした場合、次に呼ばれるのは IsInsideKeyword( ..., nLineNumber = N+1, nPosWithinLine = 0, ... )である。 + */ + virtual const CLogicInt IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) = 0; + + /** ドキュメントの内容に変更があったという通知。 + 保持するキャッシュの破棄や更新などに役立てる。 + */ + virtual void LineChanged( const CEditDoc* const pDoc, const CLogicInt nLineNumber ) {} + virtual void LinesChangedAfter( const CEditDoc* const pDoc, const CLogicInt nLineNumber ) {} +}; + + +/** 行キャッシュなどを持たない色分け戦略のとりまとめ。所属する色分けユニットが行単位で動き、行を超えて + 情報を持つ必要がないときはこちらを使う。検索語ハイライトのために用意した。 +*/ +class SimpleColorStrategy +{ +public: + struct Result; + + SimpleColorStrategy( const CEditDoc* const pDoc ); + ~SimpleColorStrategy(); + + /** 色分け戦略を登録する。 + 優先度の高い順に Pushすること。複数の色分け戦略が同じ文字を色分け開始文字に選んだときの結果に影響する。 + */ + void PushStrategyUnit( std::auto_ptr strategyUnit ) + { + this->strategies.push_back( strategyUnit.release() ); + } + + /** 行あたりの色分け結果を返す。 + */ + void HighlightLine( const CEditDoc* const pDoc, const CLogicInt nLineNumber, Result* const outResult ); + +protected: + const CEditDoc* const pDoc; ///< この色分けストラテジのオーナードキュメント + std::vector strategies; ///< 検索語ハイライトなどの色分けルール。 +}; + + +/** 色分け戦略のとりまとめ。ドキュメントに対し独立した色分け権限を持つ。 + 例えば、正規表現キーワードやダブルクォーテーション文字列、数値などの色分けは協調して働く必要があるので、 + 同じ ColorMLStrategyに属す必要がある。検索語のハイライトはそれらとは独立して働くので、別の ColorMLStrategyに所有させる。 + 複数の ColorMLStrategyに優先順位を付けて重ね合わせるのは別の仕事。 +*/ +class ColorMLStrategy +: private SimpleColorStrategy +{ +public: + typedef SimpleColorStrategy::Result Result; + + ColorMLStrategy( const CEditDoc* const pDoc ); + ~ColorMLStrategy(); + + /** 色分け戦略を登録する。 + 優先度の高い順に Pushすること。複数の色分け戦略が同じ文字を色分け開始文字に選んだときの結果に影響する。 + */ + void PushStrategyUnit( std::auto_ptr strategyUnit ) + { + return SimpleColorStrategy::PushStrategyUnit( strategyUnit ); + } + + /** 行あたりの色分け結果を返す。 + ドキュメントの変更を逐一 NotifyLineChange()/NotifyLineChangeAfter()で通知していないと + 正しい結果が帰ってこない。 + */ + void HighlightLine( const CEditDoc* const pDoc, const CLogicInt nLineNumber, Result* const outResult ); + + /** ドキュメントの行文字列に変更があったときに、それを通知するために呼ぶ。 + コストの高い色分け戦略(ぶっちゃけ正規表現キーワード)は独自のキャッシュを保存していることがあり、 + その内容を更新(無効化)する必要があることを知らせてやらなければいけない。 + */ + void NotifyLineChange( const CLogicInt nLineNumber ); + + /** NotifyLineChangeの複数行版。 + 行の挿入や削除があり、それより後ろの行の内容と行番号が一斉にずれてしまったときに呼ぶ。 + */ + void NotifyLineChangeAfter( const CLogicInt nLineNumber ); + +private: + class HighlightEngine; + const std::auto_ptr engine; ///< 色分けの実行者。 +}; + + +/** ColorMLStrategy.HighlightLine()を呼んで得られる一行あたりの色分け結果。 +*/ +struct SimpleColorStrategy::Result +{ + typedef DivArray + LineColorInfo; + + LineColorInfo colorInfo; + bool nextLineHighlightChanged; + + Result() + : colorInfo(), nextLineHighlightChanged( false ) + {} +}; Index: sakura_core/view/colors/JSON_reader.h =================================================================== --- sakura_core/view/colors/JSON_reader.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/JSON_reader.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,54 @@ +#ifndef JSON_READER_H +#define JSON_READER_H +#include + +class JSON_reader +{ +public: + struct Token; + virtual ~JSON_reader() {} + bool parse(); /* start! */ + +protected: + /** parse()を中断させるために呼ぶ。 + これにより発生したエラーも error()メソッドに通知され、 + その後、parse()が失敗する(falseを返す)。 + */ + void raise( const wchar_t* const errMsg ); + +private: + /** parse()する対象文字列を供給する役割を持つ。 + parse()を呼んだ直後に一度、以後 beginと endが等しくなる度に何度も呼ばれるが、 + *beginや *endに無効なポインタ(0)を代入したり、falseを返すと対象文字列が終わったと見なされる。 + */ + virtual bool read( const wchar_t** const begin, const wchar_t** const end ) { return false; } + virtual void enterArray() {} + virtual void exitArray() {} + virtual void enterObject() {} + virtual void exitObject() {} + virtual void gotValue( const Token& token ) {} + virtual void error( const unsigned index, const wchar_t* const errMsg ) {} + + friend class JSON_reader_driver; +}; + +struct JSON_reader::Token +{ + enum TokenType + { + T_IDENT, /* オブジェクトのキー。*/ + T_STRING, /* オブジェクトのキーまたは値。配列の要素。(valueに引用符は含まれない) */ + T_RXPATTERN, /* 正規表現リテラルのパターン部分。(valueにスラッシュは含まれない。次に必ず T_RXFLAGが続く) */ + T_RXFLAG, /* 正規表現リテラルのフラグ部分。(valueにスラッシュは含まれない。空の場合もある。必ず T_RXPATTERNに続く) */ + T_NUMBER, /* オブジェクトの値。配列の要素。 */ + T_TRUE, /* true. (valueは必ず L"true") */ + T_FALSE, /* false. (valueは必ず L"false") */ + T_NULL, /* null. (valueは必ず L"null") */ + NR_TOKENS /* number of tokens. (使用されることはない) */ + } type; /* valueが表現するタイプ。 */ + std::wstring value; + + const wchar_t* to_str() const; +}; + +#endif JSON_CHECKER_H Index: sakura_core/view/colors/CColorML_Comment.h =================================================================== --- sakura_core/view/colors/CColorML_Comment.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_Comment.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,36 @@ +#pragma once +#include +#include "view/colors/ColorMLStrategy.h" + + +class CColorML_LineComment +: public CColorML_Base +{ +public: + CColorML_LineComment( const wchar_t* const szCommentChar, const CLogicInt column = -1 ) + : commentChar( szCommentChar ), column( column ) + {} + + virtual const CLogicInt IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + virtual const CLogicInt IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + +private: + const std::wstring commentChar; ///< 行コメント開始文字 + const CLogicInt column; ///< 桁指定。-1なら行のどの位置からでもコメントが開始できる。 +}; + + +class CColorML_BlockComment +: public CColorML_Base +{ +public: + CColorML_BlockComment( const wchar_t* const szCommentBegin, const wchar_t* const szCommentEnd ) + : commentBegin( szCommentBegin ), commentEnd( szCommentEnd ) + {} + + virtual const CLogicInt IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + virtual const CLogicInt IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + +private: + const std::wstring commentBegin, commentEnd; +}; Index: sakura_core/view/colors/CColorML_Numeric.h =================================================================== --- sakura_core/view/colors/CColorML_Numeric.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_Numeric.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,10 @@ +#pragma once +#include "view/colors/ColorMLStrategy.h" + +class CColorML_Numeric +: public CColorML_Base +{ +public: + virtual const CLogicInt IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + virtual const CLogicInt IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); +}; Index: sakura_core/view/colors/CColorML_Url.h =================================================================== --- sakura_core/view/colors/CColorML_Url.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_Url.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,11 @@ +#pragma once +#include "view/colors/ColorMLStrategy.h" + + +class CColorML_Url +: public CColorML_Base +{ +public: + virtual const CLogicInt IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + virtual const CLogicInt IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); +}; Index: sakura_core/view/colors/JSON_checker.h =================================================================== --- sakura_core/view/colors/JSON_checker.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/JSON_checker.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,117 @@ +#ifndef JSON_CHECKER_H +#define JSON_CHECKER_H +#include + +class JSON_checker +{ +public: + enum Mode + { + MODE_DONE, + MODE_ARRAY, + MODE_OBJECT, + MODE_KEY, + }; + + enum State + { + _E = -14, _D, _C, _B, _A, _9, _8, _7, _6, _5, _4, _3, _2, /* actions */ + __, /* transition error */ + GO, /* start */ + OK, /* ok */ + OB, /* object */ + KE, /* key */ + CO, /* colon */ + VA, /* value */ + AR, /* array */ + ST, /* "string" */ + SQ, /* 'string' */ + ID, /* ident */ + ES, /* escape */ + U1, /* \u */ + U2, /* \uX */ + U3, /* \uXX */ + U4, /* \uXXX */ + MI, /* minus */ + ZE, /* zero */ +#undef IN + IN, /* integer */ + FR, /* fraction */ + E1, /* e */ + E2, /* ex */ + E3, /* exp */ + T1, /* t */ + T2, /* tr */ + T3, /* tru */ + F1, /* f */ + F2, /* fa */ + F3, /* fal */ + F4, /* fals */ + N1, /* n */ + N2, /* nu */ + N3, /* nul */ + CM, /* slash */ + C1, /* // */ + C2, /* / * */ + C3, /* / ** */ + R0, /* regex? */ + RX, /* regex */ + RE, /* rx esc */ + RF, /* rx flag */ + NR_STATES + }; + + enum Error + { + E_NO_ERROR, + E_INVALID_CHAR, + E_UNEXPECTED_OBJECT_END, + E_UNEXPECTED_ARRAY_END, + E_UNEXPECTED_QUOTE, + E_UNEXPECTED_COMMA, + E_UNEXPECTED_COLON, + E_UNEXPECTED_CHAR, + E_TRANSITION_ERROR, + NR_ERRORS + }; + + typedef std::vector::size_type size_type; + + JSON_checker() + : modeStack( 1, MODE_DONE ), currentState( GO ), returnState( __ ), error( E_NO_ERROR ) + {} + void reset() + { + this->modeStack.resize( 1, MODE_DONE ); + this->currentState = GO; + this->returnState = __; + this->error = E_NO_ERROR; + } + bool nextChar( const wchar_t nextChar ); + bool done() const + { return this->currentState == OK && this->modeStack.back() == MODE_DONE; } + Mode mode() const + { return this->modeStack.back(); } + State state() const + { return this->currentState; } + size_type stackSize() const + { return this->modeStack.size(); } + Error error; + const wchar_t* errorMessage( const Error error ) const; + +private: + /* + Characters are mapped into these 31 character classes. This allows for + a significant reduction in the size of the state transition table. + */ + enum CharClass; + + CharClass classify( const wchar_t ch ) const; + bool moveNext( const CharClass charClass ); + + std::vector modeStack; + State currentState; + State returnState; +}; + +#endif JSON_CHECKER_H Index: sakura_core/view/colors/CColorML_Found.cpp =================================================================== --- sakura_core/view/colors/CColorML_Found.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_Found.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,89 @@ +#include "StdAfx.h" +#include +#include +#include "mem/CNativeW.h" +#include "view/CEditView.h" +#include "view/colors/EColorIndexType.h" +#include "view/colors/CColorML_Found.h" + +/// 語の末尾が searchEndを超えない最後の検索語を探して、見つかったかどうかと、見つかっていればその位置を返す。 +static bool FindPrevSearchString( const CEditView* const pView, const CStringRef& line, const CLogicInt lastIndex, CLogicInt* const outIndex, CLogicInt* const outLastIndex ); + +const CLogicInt CColorML_Found::IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + *outColor = this->colors.empty() ? COLORIDX_DEFAULT : this->colors.front(); + if( this->lineNum == nLineNumber && nPosWithinLine <= this->begin ) { // 以前とっておいた正規表現検索結果がまだ使えるなら…… + return nPosWithinLine == this->begin ? std::max( 1, this->end - this->begin ) : 0; + } + // 新たに検索する。 + this->lineNum = nLineNumber; + const CStringRef& line = pLine->GetStringRefWithEOL(); + if( this->pView->m_sCurSearchOption.bRegularExp ) { + int found = false; + const CEditView::SearchInfo& searchInfo = this->pView->lastSearchInfo; + // パターン検索では検索開始位置を無視できない。上検索では行末から、下検索では行頭から。 + // 検索が開始された行ではキャレットのある位置から検索を始めなければならない。 + const CLogicInt searchStart = searchInfo.pos.y == nLineNumber ? searchInfo.pos.x : searchInfo.pos.y < nLineNumber ? 0 : line.GetLength(); + if( searchStart <= nPosWithinLine ) { + // 行の最初から検索語を検索していって、語の始まりが nPosWithinLine以上になる最初の検索語を見つける。 + for( CLogicInt pos = searchStart; pos <= nPosWithinLine; pos = std::max( this->begin + 1, this->end ) ) { + found = this->pView->IsSearchString( line, pos, &(this->begin), &(this->end) ); + if( ! found || nPosWithinLine <= this->begin ) { + break; + } + } + } else { + // 行の最後(<ちょっと違う)から検索語を上検索していって、語の終わりが nPosWithinLine以上の最後の検索語を見つける。 + if( searchStart != line.GetLength() ) { + found = this->pView->IsSearchString( line, searchStart, &(this->begin), &(this->end) ); + } else { + found = FindPrevSearchString( this->pView, line, searchStart, &(this->begin), &(this->end) ); + } + if( found ) { + for( CLogicInt p = this->begin, q = this->begin, r = this->end; 0 <= p && (nPosWithinLine < r || nPosWithinLine == r && r == q); p = std::min( p - 1, q ) ) { + this->begin = q; this->end = r; + if( ! FindPrevSearchString( this->pView, line, p, &q, &r ) ) { + break; + } + } + } + } + if( ! found ) { + this->begin = this->end = std::numeric_limits::max(); // この行ではもう検索をトライしないように。 + } + } else { + const int found = this->pView->IsSearchString( line, nPosWithinLine, &(this->begin), &(this->end) ); + if( 0 < found ) { + // 単語検索では戻り値の foundは、検索語の中の何番目の単語が一致したかを示す、1から始まる数字。 + // COLORIDX_SEARCHから COLORIDX_SEARCHTAILまでの色を順番に割り当てる。 + *outColor = this->colors.empty() ? COLORIDX_DEFAULT : this->colors.at( (found - 1) % this->colors.size() ); + } else { + this->begin = this->end = -1; // 次の nPosWithinLineでリトライ。 + } + } + return nPosWithinLine == this->begin ? std::max( 1, this->end - this->begin ) : 0; +} + +const CLogicInt CColorML_Found::IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + return 0; +} + +bool FindPrevSearchString( const CEditView* const pView, const CStringRef& line, const CLogicInt searchEnd, CLogicInt* const outIndex, CLogicInt* const outLastIndex ) +{ + CLogicInt index = -1, lastIndex = -1; + for( CLogicInt p = 0, q, r; p <= std::min( CLogicInt(line.GetLength()), searchEnd ); p += std::max( CLogicInt(1), CNativeW::GetSizeOfChar( line.GetPtr(), line.GetLength(), p ) ) ) { + if( 0 == pView->IsSearchString( line, p, &q, &r ) ) { + break; + } + if( searchEnd < r ) { + break; + } + index = q; lastIndex = r; + } + if( 0 <= index ) { + *outIndex = index; *outLastIndex = lastIndex; + return true; + } + return false; +} Index: sakura_core/view/colors/CColorML_RegexKeyword.cpp =================================================================== --- sakura_core/view/colors/CColorML_RegexKeyword.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_RegexKeyword.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,51 @@ +#include "StdAfx.h" +#include "view/colors/RKW2.h" +#include "view/colors/EColorIndexType.h" +#include "view/colors/CColorML_RegexKeyword.h" +static bool IsRegexKeywordColor( EColorIndexType color ); + +const CLogicInt CColorML_RegexKeyword::IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + static int rkw2_internal_state = 0; + const RKW2* const pRKW2 = RKW2Holder::GetRKW2( pDoc->m_cDocType.GetDocumentType() ); + if( ! pRKW2 ) { + return 0; + } + EColorIndexType color; + const CLogicInt colorLen = pRKW2->IsStartOfKeyword( pDoc, nLineNumber, pLine, nPosWithinLine, this->hint.get(), &color ); + if( 0 < colorLen ) { + *reinterpret_cast( userData ) = pRKW2->InternalStateID( this->hint.get() ); // ColorMLStrategyに対し、正規表現キーワードの内部状態が変わったこと、そのために色分けを更新しなければいけないことを通知する。 + const STypeConfig& doctype = pDoc->m_cDocType.GetDocumentAttribute(); + if( IsRegexKeywordColor( color ) && ! doctype.m_ColorInfoArr[color].m_bDisp ) { + color = COLORIDX_TEXT; + } + *outColor = color; + return colorLen; + } + return 0; +} + +const CLogicInt CColorML_RegexKeyword::IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + const RKW2* const pRKW2 = RKW2Holder::GetRKW2( pDoc->m_cDocType.GetDocumentType() ); + if( ! pRKW2 ) { + return 0; + } + EColorIndexType color; + const CLogicInt colorLen = pRKW2->IsInsideKeyword( pDoc, nLineNumber, pLine, nPosWithinLine, this->hint.get(), &color ); + if( 0 < colorLen ) { + const STypeConfig& doctype = pDoc->m_cDocType.GetDocumentAttribute(); + if( IsRegexKeywordColor( color ) && ! doctype.m_ColorInfoArr[color].m_bDisp ) { + color = COLORIDX_TEXT; + } + *outColor = color; + return colorLen; // まだだ。まだ終わらんよ。 + } + return 0; +} + + +static inline bool IsRegexKeywordColor( const EColorIndexType color ) +{ + return COLORIDX_REGEX1 <= color && color < COLORIDX_LAST; +} Index: sakura_core/view/colors/CColorML_Found.h =================================================================== --- sakura_core/view/colors/CColorML_Found.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_Found.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,30 @@ +#pragma once +#include +#include +#include "view/colors/ColorMLStrategy.h" +class CEditView; + + +class CColorML_Found +: public CColorML_Base +{ +public: + CColorML_Found::CColorML_Found( const CEditView* const pView ) + : pView( pView ), lineNum( -1 ), begin( -1 ), end( -1 ), colors( 1, COLORIDX_SEARCH ) + {} + + virtual const CLogicInt IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + virtual const CLogicInt IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + + void SearchConditionChanged() + { this->lineNum = -1; } + void SetColors( const std::vector& colors ) + { this->colors = colors; } + +private: + const CEditView* const pView; ///< オーナービュー。検索語ハイライトはビューに属している。 + CLogicInt lineNum; ///< begin、endがどの行内の位置を表しているか。 + CLogicInt begin; ///< ハイライト対象の開始位置。これは常に前回の IsStartOfKeyword()呼び出しの nPosWithinLine以上の値をとる。 + CLogicInt end; ///< ハイライト対象の終了位置。(最後の文字の次を指す) + std::vector colors; +}; Index: sakura_core/view/colors/EColorIndexType.cpp =================================================================== --- sakura_core/view/colors/EColorIndexType.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/EColorIndexType.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,256 @@ +#include "StdAfx.h" +#include "view/colors/EColorIndexType.h" + +const unsigned COLOR_ATTRIB_FORCE_DISP = 0x00000001; +const unsigned COLOR_ATTRIB_NO_TEXT = 0x00000010; // 予約値 +const unsigned COLOR_ATTRIB_NO_BACK = 0x00000020; +const unsigned COLOR_ATTRIB_NO_BOLD = 0x00000100; +const unsigned COLOR_ATTRIB_NO_UNDERLINE = 0x00000200; +const unsigned COLOR_ATTRIB_NO_ITALIC = 0x00000400; // 予約値 +const unsigned COLOR_ATTRIB_NO_EFFECTS = 0x00000F00; + +const COLORREF DEFAULT_TEXT_COLOUR = RGB( 0, 0, 0); +const COLORREF DEFAULT_BACK_COLOUR = RGB( 255, 251, 240); + +const SColorAttributeData g_ColorAttributeArr[ COLORIDX_LAST + 1 ] = +{ +// ini用の短い色名, グローバルな表示属性 + {_T("TXT"), COLOR_ATTRIB_FORCE_DISP | COLOR_ATTRIB_NO_EFFECTS, +// 項目名, 表示, 太字, 下線, 文字色, 背景色, + _T("テキスト"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("RUL"), COLOR_ATTRIB_NO_EFFECTS, + _T("ルーラー"), FALSE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, RGB( 239, 239, 239 ) + }, + {_T("CAR"), COLOR_ATTRIB_FORCE_DISP | COLOR_ATTRIB_NO_BACK | COLOR_ATTRIB_NO_EFFECTS, + _T("カーソル"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("IME"), COLOR_ATTRIB_NO_BACK | COLOR_ATTRIB_NO_EFFECTS, + _T("カーソル(IME ON)"), TRUE, FALSE, FALSE, RGB( 255, 0, 0 ), DEFAULT_BACK_COLOUR + }, + {_T("UND"), COLOR_ATTRIB_NO_BACK | COLOR_ATTRIB_NO_EFFECTS, + _T("カーソル行アンダーライン"), FALSE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("CVL"), COLOR_ATTRIB_NO_BACK | ( COLOR_ATTRIB_NO_EFFECTS & ~COLOR_ATTRIB_NO_BOLD ), + _T("カーソル位置縦線"), FALSE, FALSE, FALSE, RGB( 128, 128, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("VER"), 0, + _T("指定桁縦線"), TRUE, FALSE, FALSE, RGB( 192, 192, 192 ), DEFAULT_BACK_COLOUR + }, + {_T("LNO"), 0, + _T("行番号"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), RGB( 239, 239, 239 ) + }, + {_T("MOD"), 0, + _T("行番号(変更行)"), TRUE, TRUE, FALSE, RGB( 0, 0, 255 ), RGB( 239, 239, 239 ) + }, + {_T("TAB"), 0, + _T("TAB記号"), FALSE, FALSE, FALSE, RGB( 128, 128, 128 ), DEFAULT_BACK_COLOUR //Jan. 19, 2001 JEPRO RGB(192,192,192)より濃いグレーに変更 + }, + {_T("SPC"), 0, + _T("半角空白"), FALSE, FALSE, FALSE, RGB( 192, 192, 192 ), DEFAULT_BACK_COLOUR //2002.04.28 Add by KK + }, + {_T("ZEN"), 0, + _T("日本語空白"), TRUE, FALSE, FALSE, RGB( 192, 192, 192 ), DEFAULT_BACK_COLOUR + }, + {_T("CTL"), 0, + _T("コントロールコード"), TRUE, FALSE, FALSE, RGB( 255, 255, 0 ), DEFAULT_BACK_COLOUR + }, + {_T("RAP"), 0, + _T("折り返し記号"), TRUE, FALSE, FALSE, RGB( 255, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("EOL"), 0, + _T("改行記号"), FALSE, FALSE, FALSE, RGB( 0, 128, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("EOF"), 0, + _T("EOF記号"), FALSE, FALSE, FALSE, RGB( 0, 255, 255 ), DEFAULT_TEXT_COLOUR + }, + {_T("NUM"), 0, //@@@ 2001.02.17 by MIK 半角数値の強調 + _T("半角数値"), TRUE, FALSE, FALSE, RGB( 235, 0, 0 ), DEFAULT_BACK_COLOUR //@@@ 2001.02.17 by MIK //Mar. 7, 2001 JEPRO RGB(0,0,255)を変更 Mar.10, 2001 標準は色なしに + }, + {_T("URL"), 0, + _T("URL"), TRUE, FALSE, TRUE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("CMT"), 0, + _T("コメント"), TRUE, FALSE, FALSE, RGB( 0, 128, 0 ), DEFAULT_BACK_COLOUR + }, + {_T("SQT"), 0, + _T("シングルクォーテーション文字列"), FALSE, FALSE, FALSE, RGB( 64, 128, 128 ), DEFAULT_BACK_COLOUR + }, + {_T("WQT"), 0, + _T("ダブルクォーテーション文字列"), FALSE, FALSE, FALSE, RGB( 128, 0, 64 ), DEFAULT_BACK_COLOUR + }, + {_T("MRK"), 0, + _T("ブックマーク"), TRUE , FALSE, FALSE, DEFAULT_BACK_COLOUR, RGB( 0, 128, 192 ) + }, + {_T("BRC"), 0, + _T("対括弧の強調表示"), FALSE, TRUE, FALSE, RGB( 128, 0, 0 ), DEFAULT_BACK_COLOUR + }, + {_T("DFA"), 0, + _T("DIFF差分表示(追加)"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("DFC"), 0, + _T("DIFF差分表示(変更)"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("DFD"), 0, + _T("DIFF差分表示(削除)"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("FND"), 0, + _T("検索文字列"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, RGB( 255, 255, 0 ) + }, + {_T("FN2"), 0, + _T("検索文字列2"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, RGB( 160, 255, 255 ) + }, + {_T("FN3"), 0, + _T("検索文字列3"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, RGB( 153, 255, 153 ) + }, + {_T("FN4"), 0, + _T("検索文字列4"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, RGB( 255, 153, 153 ) + }, + {_T("FN5"), 0, + _T("検索文字列5"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, RGB( 255, 102, 255 ) + }, + {_T("KW1"), 0, + _T("強調キーワード1"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("KW2"), 0, + _T("強調キーワード2"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), DEFAULT_BACK_COLOUR //Dec. 4, 2000 MIK added //Jan. 19, 2001 JEPRO キーワード1とは違う色に変更 + }, + {_T("KW3"), 0, + _T("強調キーワード3"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), DEFAULT_BACK_COLOUR //Dec. 4, 2000 MIK added //Jan. 19, 2001 JEPRO キーワード1とは違う色に変更 + }, + {_T("KW4"), 0, + _T("強調キーワード4"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), DEFAULT_BACK_COLOUR + }, + {_T("KW5"), 0, + _T("強調キーワード5"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), DEFAULT_BACK_COLOUR + }, + {_T("KW6"), 0, + _T("強調キーワード6"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), DEFAULT_BACK_COLOUR + }, + {_T("KW7"), 0, + _T("強調キーワード7"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), DEFAULT_BACK_COLOUR + }, + {_T("KW8"), 0, + _T("強調キーワード8"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), DEFAULT_BACK_COLOUR + }, + {_T("KW9"), 0, + _T("強調キーワード9"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), DEFAULT_BACK_COLOUR + }, + {_T("KWA"), 0, + _T("強調キーワード10"), TRUE, FALSE, FALSE, RGB( 255, 128, 0 ), DEFAULT_BACK_COLOUR + }, + {_T("RK1"), 0, + _T("正規表現キーワード1"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("RK2"), 0, + _T("正規表現キーワード2"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("RK3"), 0, + _T("正規表現キーワード3"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("RK4"), 0, + _T("正規表現キーワード4"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("RK5"), 0, + _T("正規表現キーワード5"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("RK6"), 0, + _T("正規表現キーワード6"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("RK7"), 0, + _T("正規表現キーワード7"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("RK8"), 0, + _T("正規表現キーワード8"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("RK9"), 0, + _T("正規表現キーワード9"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("RKA"), 0, + _T("正規表現キーワード10"), TRUE, FALSE, FALSE, RGB( 0, 0, 255 ), DEFAULT_BACK_COLOUR + }, + {_T("RKB"), 0, + _T("正規表現キーワード(予約語)"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("RKC"), 0, + _T("正規表現キーワード(型)"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("RKD"), 0, + _T("正規表現キーワード(変数)"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("RKE"), 0, + _T("正規表現キーワード(定数)"), TRUE, TRUE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("RKF"), 0, + _T("正規表現キーワード(代入)"), TRUE, TRUE, FALSE, RGB( 0xDC,0x14,0x3C), DEFAULT_BACK_COLOUR + }, + {_T("RKG"), 0, + _T("正規表現キーワード(演算子)"), TRUE, TRUE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("RKH"), 0, + _T("正規表現キーワード(関数)"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("RKI"), 0, + _T("正規表現キーワード(オブジェクト)"),TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("RKJ"), 0, + _T("正規表現キーワード(構造単位)"), TRUE, TRUE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("RKK"), 0, + _T("正規表現キーワード(正規表現パターン)"),TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("RKL"), 0, + _T("正規表現キーワード(日付)"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("RKL"), 0, + _T("正規表現キーワード(時刻)"), TRUE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + }, + {_T("LAST"), 0, + _T("Not Used"), FALSE, FALSE, FALSE, DEFAULT_TEXT_COLOUR, DEFAULT_BACK_COLOUR + } +}; + +SAKURA_CORE_API EColorIndexType GetColorIndexFromShortName( const TCHAR* const szShortName ) +{ + for( int i = 0; i < COLORIDX_LAST; i++ ) { + if( 0 == _tcscmp( szShortName, g_ColorAttributeArr[i].szShortName ) ) { + return EColorIndexType( i ); + } + } + return COLORIDX_DEFAULT; +} + +EColorIndexType GetColorIndexFromLongName( const TCHAR* const szLongName ) +{ + for( int i = 0; i < COLORIDX_LAST; ++i ) { + if( 0 == _tcscmp( szLongName, g_ColorAttributeArr[i].szLongName ) ) { + return EColorIndexType( i ); + } + } + return COLORIDX_DEFAULT; +} + +SAKURA_CORE_API const TCHAR* GetShortNameFromColorIndex( const EColorIndexType color ) +{ + if( 0 <= color && color < COLORIDX_LAST ) { + return g_ColorAttributeArr[color].szShortName; + } + return _T(""); +} + + +void GetDefaultColorInfo( ColorInfo* const pColorInfo, EColorIndexType color ) +{ + if( color < 0 || COLORIDX_LAST <= color ) { + color = COLORIDX_TEXT; + } + *static_cast(pColorInfo) = g_ColorAttributeArr[color].sColorInfo; + _tcsncpy( pColorInfo->m_szName, g_ColorAttributeArr[color].szLongName, _countof(pColorInfo->m_szName) - 1 ); + pColorInfo->m_szName[ _countof(pColorInfo->m_szName) - 1 ] = _T('\0'); + pColorInfo->m_nColorIdx = color; +} + +int GetDefaultColorInfoCount() +{ + return _countof(g_ColorAttributeArr) - 1; // LAST(not used)の分を省いた。 +} Index: sakura_core/view/colors/CColorML_RegexKeyword.h =================================================================== --- sakura_core/view/colors/CColorML_RegexKeyword.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_RegexKeyword.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,33 @@ +#pragma once +#include "view/colors/RKW2.h" +#include "view/colors/ColorMLStrategy.h" + + +class CColorML_RegexKeyword +: public CColorML_Base +{ +public: + virtual const CLogicInt IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + virtual const CLogicInt IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + + // 通知の受け取り + virtual void LineChanged( const CEditDoc* const pDoc, const CLogicInt nLineNumber ); + virtual void LinesChangedAfter( const CEditDoc* const pDoc, const CLogicInt nLineNumber ); + + CColorML_RegexKeyword() + : hint( RKW2::CreateHint() ) + {} + +private: + std::auto_ptr hint; +}; + +inline void CColorML_RegexKeyword::LineChanged( const CEditDoc* const pDoc, const CLogicInt nLineNumber ) +{ + this->hint->InvalidateLineCache( nLineNumber ); +} + +inline void CColorML_RegexKeyword::LinesChangedAfter( const CEditDoc* const pDoc, const CLogicInt nLineNumber ) +{ + this->hint->InvalidateLineCacheAfter( nLineNumber ); +} Index: sakura_core/view/colors/EColorIndexType.h =================================================================== --- sakura_core/view/colors/EColorIndexType.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/EColorIndexType.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,137 @@ +#pragma once +#include + +// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // +// 色定数 // +// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // + +SAKURA_CORE_API enum EColorIndexType { + COLORIDX_DEFAULT = -1, // 未定義状態。無効な色。 + + COLORIDX_TEXT = 0, // テキスト + COLORIDX_RULER, // ルーラー + COLORIDX_CARET, // キャレット // 2006.12.07 ryoji + COLORIDX_CARET_IME, // IMEキャレット // 2006.12.07 ryoji + COLORIDX_UNDERLINE, // カーソル行アンダーライン + COLORIDX_CURSORVLINE, // カーソル位置縦線 // 2006.05.13 Moca + COLORIDX_VERTLINE, // 指定桁縦線 // 2005.11.08 Moca + COLORIDX_GYOU, // 行番号 + COLORIDX_GYOU_MOD, // 行番号(変更行) + COLORIDX_TAB, // TAB記号 + COLORIDX_SPACE, // 半角空白 //2002.04.28 Add by KK 以降全て+1 + COLORIDX_ZENSPACE, // 日本語空白 + COLORIDX_CTRLCODE, // コントロールコード + COLORIDX_WRAP, // 折り返し記号 + COLORIDX_EOL, // 改行記号 + COLORIDX_EOF, // EOF記号 + COLORIDX_DIGIT, // 半角数値 //@@@ 2001.02.17 by MIK //色設定Ver.3からユーザファイルに対しては文字列で処理しているのでリナンバリングしてもよい. Mar. 7, 2001 JEPRO noted + COLORIDX_URL, // URL //Dec. 4, 2000 shifted by MIK + COLORIDX_COMMENT, // 行コメント //Dec. 4, 2000 shifted by MIK + COLORIDX_SSTRING, // シングルクォーテーション文字列 //Dec. 4, 2000 shifted by MIK + COLORIDX_WSTRING, // ダブルクォーテーション文字列 //Dec. 4, 2000 shifted by MIK + COLORIDX_MARK, // ブックマーク // 02/10/16 ai Add + COLORIDX_BRACKET_PAIR, // 対括弧 // 02/09/18 ai Add + COLORIDX_DIFF_APPEND, // DIFF追加 //@@@ 2002.06.01 MIK + COLORIDX_DIFF_CHANGE, // DIFF追加 //@@@ 2002.06.01 MIK + COLORIDX_DIFF_DELETE, // DIFF追加 //@@@ 2002.06.01 MIK + COLORIDX_SEARCH, // 検索文字列 + COLORIDX_SEARCH2, // 検索文字列 + COLORIDX_SEARCH3, // 検索文字列 + COLORIDX_SEARCH4, // 検索文字列 + COLORIDX_SEARCH5, // 検索文字列 + COLORIDX_KEYWORD1, // 強調キーワード1 // 2002/03/13 novice + COLORIDX_KEYWORD2, // 強調キーワード2 // 2002/03/13 novice //MIK ADDED + COLORIDX_KEYWORD3, // 強調キーワード3 // 2005.01.13 MIK 3-10 added + COLORIDX_KEYWORD4, // 強調キーワード4 + COLORIDX_KEYWORD5, // 強調キーワード5 + COLORIDX_KEYWORD6, // 強調キーワード6 + COLORIDX_KEYWORD7, // 強調キーワード7 + COLORIDX_KEYWORD8, // 強調キーワード8 + COLORIDX_KEYWORD9, // 強調キーワード9 + COLORIDX_KEYWORD10, // 強調キーワード10 + COLORIDX_REGEX1, // 正規表現キーワード1 //@@@ 2001.11.17 add MIK + COLORIDX_REGEX2, // 正規表現キーワード2 //@@@ 2001.11.17 add MIK + COLORIDX_REGEX3, // 正規表現キーワード3 //@@@ 2001.11.17 add MIK + COLORIDX_REGEX4, // 正規表現キーワード4 //@@@ 2001.11.17 add MIK + COLORIDX_REGEX5, // 正規表現キーワード5 //@@@ 2001.11.17 add MIK + COLORIDX_REGEX6, // 正規表現キーワード6 //@@@ 2001.11.17 add MIK + COLORIDX_REGEX7, // 正規表現キーワード7 //@@@ 2001.11.17 add MIK + COLORIDX_REGEX8, // 正規表現キーワード8 //@@@ 2001.11.17 add MIK + COLORIDX_REGEX9, // 正規表現キーワード9 //@@@ 2001.11.17 add MIK + COLORIDX_REGEX10, // 正規表現キーワード10 //@@@ 2001.11.17 add MIK + COLORIDX_REGEX_KEYWORD, // 正規表現キーワード(予約語) + COLORIDX_REGEX_TYPE, // 正規表現キーワード(型) + COLORIDX_REGEX_VARIABLE,// 正規表現キーワード(変数) + COLORIDX_REGEX_CONSTANT,// 正規表現キーワード(定数) + COLORIDX_REGEX_ASSIGN, // 正規表現キーワード(代入) + COLORIDX_REGEX_OPERATOR,// 正規表現キーワード(演算子) + COLORIDX_REGEX_FUNCTION,// 正規表現キーワード(関数) + COLORIDX_REGEX_OBJECT, // 正規表現キーワード(オブジェクト) + COLORIDX_REGEX_BLOCK, // 正規表現キーワード(構造単位) + COLORIDX_REGEX_RXPATTERN,// 正規表現キーワード(正規表現パターン) + COLORIDX_REGEX_DATE, // 正規表現キーワード(日付) + COLORIDX_REGEX_TIME, // 正規表現キーワード(時刻) + + // カラーの最後。ここまでの色が共有メモリの m_Types[MAX_TYPES].m_ColorInfoArr[COLORIDX_LAST]に登録され、実際の表示に利用される。 + COLORIDX_LAST, + + // ここから ColorStrategy用の疑似カラー + CTRLCOLOR_REGEX_UNMATCHED, // 正規表現キーワードの内部処理用 + CTRLCOLOR_REGEX_NOTSPECIFIED, // 正規表現キーワードの内部処理用(色指定無し=直前の色を引き継ぐ) + + // エイリアス + COLORIDX_SEARCHTAIL = COLORIDX_SEARCH5, +}; + +/// 必ず、色設定配列のインデックスとして有効な色( COLORIDX_TEXTから COLORIDX_LAST-1 まで)を返します。 +inline EColorIndexType ActualColor( const EColorIndexType& color ) +{ + if( 0 <= color && color < COLORIDX_LAST ) { + return color; + } + return COLORIDX_TEXT; +} + +//! テキストの色や装飾 +struct TextDecoration +{ + bool m_bDisp; //!< 表示 + bool m_bFatFont; //!< 太字 + bool m_bUnderLine; //!< 下線 + COLORREF m_colTEXT; //!< 文字色 + COLORREF m_colBACK; //!< 背景色 +}; + +/// SColorAttrubuteData.fAttribute用のビットフラグ。 +/// 各文字種のグローバルな属性を指示する。 +extern const unsigned COLOR_ATTRIB_FORCE_DISP; +//extern const unsigned COLOR_ATTRIB_NO_TEXT; // 予約値 +extern const unsigned COLOR_ATTRIB_NO_BACK; +extern const unsigned COLOR_ATTRIB_NO_BOLD; +extern const unsigned COLOR_ATTRIB_NO_UNDERLINE; +//extern const unsigned COLOR_ATTRIB_NO_ITALIC; // 予約値 +extern const unsigned COLOR_ATTRIB_NO_EFFECTS; + +SAKURA_CORE_API extern const struct SColorAttributeData +{ + const TCHAR* szShortName; ///< ini保存用の短い色名。 + unsigned int fAttribute; ///< 文字種ごとのグローバルな表示設定。 + const TCHAR* szLongName; //!< 色の日本語名(表示用)。 + TextDecoration sColorInfo; //!< タイプ別の色設定のデフォルト。 +} +g_ColorAttributeArr[ COLORIDX_LAST + 1 ]; + +SAKURA_CORE_API EColorIndexType GetColorIndexFromShortName( const TCHAR* const szShortName ); +EColorIndexType GetColorIndexFromLongName( const TCHAR* const szLongName ); +SAKURA_CORE_API const TCHAR* GetShortNameFromColorIndex( const EColorIndexType color ); + + +/// タイプ別色設定のデフォルトを受け取るための構造体 +struct ColorInfo +: public TextDecoration +{ + EColorIndexType m_nColorIdx; //!< インデックス + TCHAR m_szName[64]; //!< 名前 +}; +void GetDefaultColorInfo(ColorInfo* const pColorInfo, const EColorIndexType color ); +int GetDefaultColorInfoCount(); Index: sakura_core/view/colors/RKW2.cpp =================================================================== --- sakura_core/view/colors/RKW2.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/RKW2.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,1044 @@ +#include "StdAfx.h" +#include +#include +#include +#include // _wtoi() +#include +#include +#include "util/file.h" // GetInidir(), TranslateForbiddenFileCharacterToZenkaku() +#include "types/CType.h" +#include "CBregexpDll2.h" +#include "io/CFileLoad.h" +#include "config/maxdata.h" +#include "view/colors/DivArray.h" +#include "view/colors/JSON_reader.h" +#include "view/colors/EColorIndexType.h" +#include "view/colors/RKW2.h" + +/** 正規表現ライブラリのインスタンス。Singleton. 共有します。ファイルグローバルです。 +*/ +class RXDLL +: public CDllHandler +, public TSingleton +{ +}; + +/** Pattern.exec()の戻り値の型。対象文字列のどの範囲にマッチしたか、しなかったかを記憶する。 +*/ +struct MatchData +{ + /// マッチの範囲やキャプチャの範囲を表す。 + struct Range + { + CLogicInt index; + CLogicInt lastIndex; + + Range() + : index( Null.index ), lastIndex( Null.lastIndex ) + {} + Range( const CLogicInt index, const CLogicInt lastIndex ) + : index( index ), lastIndex( lastIndex ) + {} + + bool empty() const + { return this->index == this->lastIndex; } + + CLogicInt size() const + { return this->lastIndex - this->index; } + + bool null() const ///< マッチに失敗した状態。キャプチャがマッチに参加しなかった状態。 + { return this->index < 0 && this->lastIndex < 0; } + + private: + static const Range Null;; + friend MatchData; + }; + + std::vector match; + + MatchData() + : match( 0 ) + {} + MatchData( CLogicInt index, CLogicInt lastIndex ) + : match( 1, Range( index , lastIndex ) ) + {} + MatchData( const BREGEXP_W* const pCompileBlock, const wchar_t* const szTarget ); + + bool undefined() const ///< 初期状態。マッチ結果が格納されていない状態。 + { return this->match.empty(); } + + bool null() const ///< マッチに失敗した(見つからなかった)という結果を格納した状態。 + { return ! this->undefined() && this->match[0].null(); } + + unsigned size() const ///< キャプチャを含めた要素数。インデックス0がマッチ全体で、要素Nが N番目に出現したかっこの範囲。 + { return (this->undefined() || this->null()) ? 0 : this->match.size(); } + + const Range& operator[]( const unsigned index ) const ///< マッチ結果へのアクセサ。 + { return this->match[index]; } + + static const MatchData Null; +}; +const MatchData::Range MatchData::Range::Null( -1, -1 ); +const MatchData MatchData::Null( -1, -1 ); + + +/** SHJSの言語ファイルに見られるパターンを表す型。 + 正規表現パターン、遷移先、色を情報として持つ。 + SHJSのそれとはちょっと違い exec()メソッドを持ち、正規表現パターンそのものとしても振る舞う。 + これは横着だったかも知れない。違うものが混じり合った結果 mutableが必要になったといえる。 +*/ +struct Pattern +{ + std::wstring patternStr; + std::vector colors; + int nextState; + bool isState; + + Pattern() + : patternStr(), colors( 0 ), nextState( -1/*not specified*/ ), isState( false ), pBregexp_w( 0 ) + {} + Pattern( const std::wstring& patternStr, const EColorIndexType color, const int nextState = -1/*not specified*/, const bool isState = false ) + : patternStr( patternStr ), colors( 1, color ), nextState( nextState ), isState( isState ), pBregexp_w( 0 ) + {} + Pattern( const std::wstring& patternStr, const std::vector& colors, const int nextState = -1/*not specified*/, const bool isState = false ) + : patternStr( patternStr ), colors( colors ), nextState( nextState ), isState( isState ), pBregexp_w( 0 ) + {} + Pattern( const Pattern& other ) + : patternStr( other.patternStr ), colors( other.colors ), nextState( other.nextState ), isState( other.isState ), pBregexp_w( 0 ) + {} + ~Pattern(); + + MatchData exec( const CDocLine* const pLine, const CLogicInt nPosWithinLine ) const; + EColorIndexType color( const unsigned index ) const; ///< 範囲が無効な場合のデフォルト付きで N番目の色指定を取得する方法。 + + bool compile(); ///< 必ずしも必要でない。コンパイルエラーが知りたいときに。 + static wchar_t szLastErrMsg[80]; ///< DLLから受け取った、直前のコンパイルエラーメッセージ。大きさに関して、サンプルが 80だったり 256だったりで怪しすぎる。 + +private: + mutable BREGEXP_W* pBregexp_w; +}; +wchar_t Pattern::szLastErrMsg[] = L""; + +/** 行の変わり目における色分けエンジンの状態のキャッシュ。 + 短いコード片を対象とする SHJSには必要ないが、ファイルを対象とする + サクラエディタでは途中の行から色分けをやり直す能力が必要なので、そのために。 +*/ +struct StartingStateOfLine +{ + std::vector patternStack; + EColorIndexType currentStyle; + + StartingStateOfLine() + : patternStack( 0 ), currentStyle( CTRLCOLOR_REGEX_UNMATCHED ) + {} + StartingStateOfLine( const std::vector& patternStack, const EColorIndexType currentStyle ) + : patternStack( patternStack ), currentStyle( currentStyle ) + {} + + friend bool operator == ( const StartingStateOfLine& lhs, const StartingStateOfLine& rhs ); + friend bool operator != ( const StartingStateOfLine& lhs, const StartingStateOfLine& rhs ); +}; +inline bool operator == ( const StartingStateOfLine& lhs, const StartingStateOfLine& rhs ) +{ + return lhs.currentStyle == rhs.currentStyle && lhs.patternStack.size() == rhs.patternStack.size() + && std::equal( lhs.patternStack.begin(), lhs.patternStack.end(), rhs.patternStack.begin() ); +} +inline bool operator != ( const StartingStateOfLine& lhs, const StartingStateOfLine& rhs ) +{ + return ! ( lhs == rhs ); +} + +/** 行の変わり目における色分けエンジンの状態のキャッシュ、の配列。 + ファイルの先頭(0行)から色分けの済んだ行の分まで。 +*/ +typedef DivArray + StartingStates; + +/** 色の配列。何文字目が何色かがわかる。 +*/ +typedef DivArray + LineColor; + +/** ある行における色分けの途中経過を保持する。 + resultは色分けの済んだところまでの色配列。 + cacheには Stateごとの MatchDataのキャッシュが、何度も同じパターンマッチングを繰り返さないように保存されている。 + 色分けが完了していないあいだは、active()が trueを返す。active()が falseになったとき、次の行の色分けを開始する準備ができたといえる。 +*/ +struct LineMatch +{ + struct StateMatchCache + { + const int iState; + std::vector cache; + + StateMatchCache( const int iState ) + : iState( iState ), cache( 0 ) + {} + StateMatchCache() + : iState( -1 ), cache( 0 ) + { + // Stateに関連づけられていないキャッシュが存在してはいけない。でも std::listが要求するので……。 + } + }; + struct NonNullMatchDetector + { + bool operator()( const MatchData& match ) const { return ! match.null(); } + }; + struct CacheFinder + { + bool operator()( const StateMatchCache& stateMatch ) const { return stateMatch.iState == iState; } + + CacheFinder( const int iState ) + : iState( iState ) + {} + const int iState; + }; + + LineColor result; + std::vector patternStack; + std::list cache; + + LineMatch() + : result( 0, CTRLCOLOR_REGEX_UNMATCHED ), patternStack( 0 ), cache( 0 ) + {} + LineMatch( const StartingStateOfLine& startState ) + : result( 0 , startState.currentStyle ), patternStack( startState.patternStack ), cache( 0 ) + {} + + bool active() const; +}; + +/** パターン配列。 + LineMatchにしろ、これにしろ、structではなく classとして能動的に動いてもいいかもしれない。 +*/ +struct RKW2::State +{ + std::vector patterns; + + State() + : patterns( 0 ) + {} +}; + +/** Hintの詳細。 + Hintと HintImplを分けたのは実装の詳細を隠すため。 + Hintを RKW2に所有させず分けたのは、ファイルタイプに基づく色分け戦略(RKW2)と、そのドキュメントへの適用結果(Hint)が別物だから。 + Hintをドキュメントごとに使い分ければ、色分け戦略は使い回しできる。 +*/ +struct HintImpl +: public RKW2::Hint +{ + const CEditDoc* pDoc; // キャッシュの有効性チェック用。 + const std::vector* pStates; // キャッシュの有効性チェック用。RKW2が変化していたらヒントは全く無効。 + StartingStates nextStartingStates; + std::vector invalidLines; // 昇順ソート済み(約束!)。 + CLogicInt lineMatchLineNum; + LineMatch lineMatch; + int internalStateID; + + HintImpl::HintImpl() + : pDoc( 0 ), pStates( 0 ), nextStartingStates(), invalidLines( 0 ), lineMatchLineNum( -1 ), lineMatch() + {} + + virtual void InvalidateAllCache(); + virtual void InvalidateLineCache( const CLogicInt nLineNumber ); + virtual void InvalidateLineCacheAfter( const CLogicInt nLineNumber ); +}; + + +std::auto_ptr RKW2::CreateHint() +{ + return std::auto_ptr( new HintImpl() ); +} + + +static std::basic_string MakeRkw2Path( const STypeConfig& doctype ); +static std::auto_ptr > ReadRkw2( const std::basic_string path ); + +RKW2::RKW2( const STypeConfig& doctype ) +: states( ReadRkw2( MakeRkw2Path( doctype ) ).release() ) +{} + +RKW2::~RKW2() +{ + if( this->states ) { + delete this->states; + } +} + + +static bool IsHintValid( const HintImpl* const pHint, const std::vector* const pStates, const CEditDoc* const pDoc ); +static bool IsLineMatchAvailable( const HintImpl* const pHint, const CLogicInt nLineNumber ); +static void FetchLineMatch( HintImpl* const pHint, const CEditDoc* const pDoc, const CLogicInt nLineNumber ); +static CLogicInt AdvanceLineMatchPos( LineMatch* const pLineMatch, const std::vector* const pStates, const CDocLine* const pLine, const CLogicInt nPosWithinLine ); +static CLogicInt PeekColorFromLineMatch( const LineMatch* const pLineMatch, const CLogicInt nPosWithinLine, EColorIndexType* const outColor ); +static void LineHighlightDone( HintImpl* const pHint, const CLogicInt nLineNumber, const LineMatch& lineMatch ); + +CLogicInt RKW2::IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, Hint* const pHint_, EColorIndexType* const outColor ) const +{ +// HintImpl* const pHint = dynamic_cast(pHint_); + HintImpl* const pHint = static_cast(pHint_); // 悪魔の誘惑。 + + // AdvanceLineMatchPos()が statesが空のときを想定していないのでここで対処。マッチが存在しないのは火を見るより明らかなので。 + if( ! this->states || this->states->empty() ) { + return false; + } + // this->statesが変化したなど、ヒントが全く無効な場合がある。 + if( ! IsHintValid( pHint, this->states, pDoc ) ) { + pHint->InvalidateAllCache(); + pHint->pDoc = pDoc; + pHint->pStates = this->states; + } + if( ! IsLineMatchAvailable( pHint, nLineNumber ) ) { + FetchLineMatch( pHint, pDoc, nLineNumber ); + if( ! IsLineMatchAvailable( pHint, nLineNumber ) ) { + return false; // お手上げ。 + } + } + + // 同じ行に対して nPosWithinLineを進めながら何度も呼び出されるので、一行分のマッチング結果(途中経過)を保存している。 + // ほかの色分けストラテジと文字の奪い合いがあるので、行末まで一気に色分けを終えることはできない。 + // とりあえず今は、pDocの nLineNumber行目の nPosWithinLine桁目の文字(から始まるキーワード)に対する権利を持っている。 + CLogicInt nAdvancedPos = nPosWithinLine; + do { + nAdvancedPos = AdvanceLineMatchPos( &(pHint->lineMatch), this->states, pLine, nAdvancedPos ); + } while( pHint->lineMatch.active() && ( nAdvancedPos <= nPosWithinLine || nAdvancedPos == pLine->GetLengthWithEOL() ) ); + + if( ! pHint->lineMatch.active() ) { // この行で nPosWithinLineより後ろでマッチする可能性がもうなければ…… + LineHighlightDone( pHint, nLineNumber, pHint->lineMatch ); + } + + return PeekColorFromLineMatch( &(pHint->lineMatch), nPosWithinLine, outColor ); +} + +CLogicInt RKW2::IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, Hint* const pHint_, EColorIndexType* const outColor ) const +{ +// HintImpl* const pHint = dynamic_cast(pHint_); + HintImpl* const pHint = static_cast(pHint_); // 悪魔の誘惑。 + + if( ! IsHintValid( pHint, this->states, pDoc ) ) { + return false; // IsInsideKeyword()の使い方を間違えている。 + } + if( ! IsLineMatchAvailable( pHint, nLineNumber ) ) { + FetchLineMatch( pHint, pDoc, nLineNumber ); + if( ! IsLineMatchAvailable( pHint, nLineNumber ) ) { + return false; // お手上げ。 + } + } + + for( CLogicInt nAdvancedPos = pHint->lineMatch.result.size(); pHint->lineMatch.active() && ( nAdvancedPos <= nPosWithinLine || nAdvancedPos == pLine->GetLengthWithEOL() ); ) { + nAdvancedPos = AdvanceLineMatchPos( &(pHint->lineMatch), this->states, pLine, nAdvancedPos ); + } + + if( ! pHint->lineMatch.active() ) { // この行で nPosWithinLineより後ろでマッチする可能性がもうなければ…… + LineHighlightDone( pHint, nLineNumber, pHint->lineMatch ); + } + + return PeekColorFromLineMatch( &(pHint->lineMatch), nPosWithinLine, outColor ); +} + +int RKW2::InternalStateID( const Hint* const pHint_ ) const +{ +// const HintImpl* const pHint = dynamic_cast(pHint_); + const HintImpl* const pHint = static_cast(pHint_); // 悪魔の誘惑。 + return pHint->internalStateID; +} + +MatchData::MatchData( const BREGEXP_W* const pCompileBlock, const wchar_t* const szTarget ) +: match( 0 ) +{ + this->match.reserve( pCompileBlock->nparens + 1 ); + for( int i = 0; i < pCompileBlock->nparens + 1; ++i ) { + this->match.push_back( + ! pCompileBlock->startp[i] ? Range::Null : Range( + CLogicInt( pCompileBlock->startp[i] - szTarget ), + CLogicInt( pCompileBlock->endp[i] - szTarget ) + ) + ); + } +} + + +Pattern::~Pattern() +{ + if( this->pBregexp_w ) { + RXDLL* pDllHandler = RXDLL::Instance(); + if( pDllHandler ) { + RXDLL& pDll = *pDllHandler; + if( pDll->IsAvailable() ) { + pDll->BRegfree( this->pBregexp_w ); + this->pBregexp_w = 0; + } + } + } +} + +MatchData Pattern::exec( const CDocLine* const pLine, const CLogicInt nPosWithinLine ) const +{ + RXDLL* const pDllHandler = RXDLL::Instance(); + if( ! pDllHandler ) { + return MatchData::Null; + } + RXDLL& pDll = *pDllHandler; + if( ! pDll->IsAvailable() ) { + return MatchData::Null; + } + const wchar_t* const szLine = pLine->GetPtr(); // with EOL + const CLogicInt lineLength = pLine->GetLengthWithoutEOL(); // without EOL. /$/m が LF の直前にしかマッチしなかったりするらしいので改行文字はマッチ対象から外す。これは SHJSと同じ方針。 + int bmResult = 0; + Pattern::szLastErrMsg[0] = L'\0'; + if( lineLength < nPosWithinLine ) { + return MatchData::Null; // おかしいぞ。 + } else if( lineLength == nPosWithinLine ) { + // nPosWithinLineが lineLengthと等しいとき(行末に対する検索時)に特別扱いをしなければいけない。 + // それは、targetBeginと targetEndが等しいことが空文字列に対する検索を意味せず、必ず ""(length=1) + // に対する検索を行う必要があるのだが、szLine[lineLength]にはないものとして扱っている改行文字があるから。 + const wchar_t szDummy[] = { L'\0', L'\0', L'\0' }; + const wchar_t* const targetBegin = nPosWithinLine == 0 ? szDummy : szDummy + 1; + const wchar_t* const targetEnd = targetBegin + 1; + if( pDll->ExistBMatchEx() ) { + bmResult = pDll->BMatchEx( this->pBregexp_w ? NULL : this->patternStr.c_str(), szDummy, targetBegin, targetEnd, &(this->pBregexp_w), Pattern::szLastErrMsg ); + } else { + bmResult = pDll->BMatch( this->pBregexp_w ? NULL : this->patternStr.c_str(), targetBegin, targetEnd, &(this->pBregexp_w), Pattern::szLastErrMsg ); + } + if( 0 < bmResult ) { + return MatchData( lineLength , lineLength ); + } else if( bmResult < 0 ) { + // エラー。パターンが間違ってたとか? + } + return MatchData::Null; + } else { + if( pDll->ExistBMatchEx() ) { + bmResult = pDll->BMatchEx( this->pBregexp_w ? NULL : this->patternStr.c_str(), szLine, szLine + nPosWithinLine, szLine + lineLength, &(this->pBregexp_w), Pattern::szLastErrMsg ); + } else { + // BMatch()がなかったら死亡。 + // BMatch()があっても、文字列先頭/行頭アンカーが使用されていたら誤マッチする。 + bmResult = pDll->BMatch( this->pBregexp_w ? NULL : this->patternStr.c_str(), szLine + nPosWithinLine, szLine + lineLength, &(this->pBregexp_w), Pattern::szLastErrMsg ); + } + if( 0 < bmResult ) { + return MatchData( this->pBregexp_w, szLine );; + } else if( bmResult < 0 ) { + // エラー。パターンが間違ってたとか? + } + return MatchData::Null; + } +} + +EColorIndexType Pattern::color( const unsigned index ) const +{ + if( index < this->colors.size() ) { + return this->colors.at( index ); + } + return CTRLCOLOR_REGEX_NOTSPECIFIED; +} + +bool Pattern::compile() +{ + Pattern::szLastErrMsg[0] = L'\0'; + + RXDLL* const pDllHandler = RXDLL::Instance(); + if( ! pDllHandler ) { + return false; + } + RXDLL& pDll = *pDllHandler; + if( ! pDll->IsAvailable() ) { + return false; + } + const wchar_t szDummyTarget[] = L""; + return 0 <= pDll->BMatch( this->patternStr.c_str(), szDummyTarget, szDummyTarget + 1, &(this->pBregexp_w), Pattern::szLastErrMsg ); +} + + +bool LineMatch::active() const +{ + // 色分け( pLineMatch->result )が行末まで終わっているかどうかで判断してはいけない。正規表現の幅0 マッチ + // (改行・EOF直前にマッチする $ とか)で内部状態の変化があるかもしれない。それは次の行の色分け開始状態に影響する。 + // 初期状態の LineMatchは Inactiveだと判断されかねない。一度以上 AdvanceLineMatchPos()で使用してから使うこと。 + const int currentState = this->patternStack.empty() ? 0 : this->patternStack.back()->nextState; + const std::list::const_iterator itStateMatch = std::find_if( this->cache.begin(), this->cache.end(), CacheFinder( currentState ) ); + if( itStateMatch == this->cache.end() ) { + return true; + } + return itStateMatch->cache.end() != std::find_if( itStateMatch->cache.begin(), itStateMatch->cache.end(), NonNullMatchDetector() ); +} + + +inline void HintImpl::InvalidateAllCache() +{ + this->nextStartingStates.clear(); + this->invalidLines.clear(); + this->lineMatchLineNum = -1; +} + +void HintImpl::InvalidateLineCache( const CLogicInt nLineNumber ) +{ + this->lineMatchLineNum = -1; + if( nLineNumber < this->nextStartingStates.size() ) { + std::vector::const_iterator it = std::lower_bound( this->invalidLines.begin(), this->invalidLines.end(), nLineNumber ); + if( it == this->invalidLines.end() || *it != nLineNumber ) { // 重複していなければ…… + this->invalidLines.insert( it, nLineNumber ); + } + } +} + +inline void HintImpl::InvalidateLineCacheAfter( const CLogicInt nLineNumber ) +{ + this->nextStartingStates.resize( nLineNumber ); + this->lineMatchLineNum = -1; + while( ! this->invalidLines.empty() && nLineNumber <= this->invalidLines.back() ) { + this->invalidLines.pop_back(); + } +} + + +static std::basic_string MakeRkw2Path( const STypeConfig& doctype ) +{ + TCHAR szPath[_MAX_PATH]; + GetInidir( szPath, NULL ); + std::basic_string path( szPath ); + path.append( TEXT("\\rkw2\\") ); + TranslateForbiddenFileCharacterToZenkaku( szPath, doctype.m_szTypeName ); + path.append( szPath ).append( TEXT(".rkw2") ); + return path; +} + +static EColorIndexType ColorNametoColorIndexType( const std::wstring& colorName ); + +static std::auto_ptr > ReadRkw2( const std::basic_string path ) +{ + class Reader + : public JSON_reader + { + public: + class FileOpenError {}; + class FormatError {}; + + Reader( std::vector* const pStates ) + : pStates( pStates ), szPath( 0 ) , file(), line(), eol(), lineLen( 0 ), lineNum( 0 ), linePos( 0 ), depth( OUT_OF_STATES ), objkey(), state(), pattern() + {} + + void open( const TCHAR* const szPath ) + { + try { + this->file.FileOpen( szPath, CODE_AUTODETECT, 0/*no base64 decode*/ ); + } catch( CError_FileOpen ) { + throw FileOpenError(); + } + // 一応サイズ上限( 1MiB ) + if( 1 * 1024 * 1024 < this->file.GetFileSize() ) { + this->messageBox( L"rkw2ファイルサイズの上限:1MiBを超えています。" ); + throw FileOpenError(); + } + this->szPath = szPath; + } + + private: + std::vector* const pStates; + const TCHAR* szPath; + CFileLoad file; + CNativeW line; + CEol eol; + CLogicInt lineLen; + CLogicInt lineNum; + CLogicInt linePos; + enum Depth { OUT_OF_STATES, IN_STATES, IN_STATE, IN_PATTERN, IN_STYLE, OUT_OF_STATES_AND_STATES_HAS_BEEN_GOTTEN } depth; + std::wstring objkey; // if(! empty()){ next value is object value. } + RKW2::State state; + Pattern pattern; + + virtual bool read( const wchar_t** const begin, const wchar_t** const end ) + { + if( ! this->szPath ) { + return false; + } + this->lineNum += 1; + this->linePos += this->lineLen; + if( RESULT_FAILURE == this->file.ReadLine( &(this->line), &(this->eol) ) ) { + return false; // EOF or read error + } + this->lineLen = this->line.GetStringLength(); + *begin = this->line.GetStringPtr(); + *end = this->line.GetStringPtr() + this->lineLen; + return true; + } + virtual void enterArray() + { + if( this->depth == OUT_OF_STATES ) { + this->depth = IN_STATES; + return; + } + if( this->depth == IN_STATES ) { + this->depth = IN_STATE; + this->state.patterns.clear(); + return; + } + if( this->depth == IN_PATTERN && this->objkey == L"style" ) { + this->depth = IN_STYLE; + this->pattern.colors.clear(); + this->pattern.colors.push_back( CTRLCOLOR_REGEX_NOTSPECIFIED ); + return; + } + this->raise( L"予期せぬ配列。" ); // State配列と Pattern配列しか認めない。 + } + virtual void exitArray() + { + if( this->depth == IN_STATES ) { + // got states describing a language highlighting rule. + this->depth = OUT_OF_STATES_AND_STATES_HAS_BEEN_GOTTEN; + return; + } + if( this->depth == IN_STATE ) { + // got a state + this->pStates->push_back( this->state ); + this->depth = IN_STATES; + return; + } + if( this->depth == IN_STYLE && this->objkey == L"style" ) { + if( this->pattern.colors.empty() ) { + this->raise( L"空の色配列。" ); + } + this->objkey.clear(); + this->depth = IN_PATTERN; + return; + } + this->raise( L"起こるはずないエラー。" ); // enterArray()で弾いてるからここには来ない。 + } + virtual void enterObject() + { + if( this->depth == IN_STATE ) { + this->depth = IN_PATTERN; + this->pattern = Pattern(); + return; + } + this->raise( L"予期せぬオブジェクト。" ); + } + virtual void exitObject() + { + if( this->depth == IN_PATTERN ) { + // got a pattern + this->state.patterns.push_back( this->pattern ); + this->depth = IN_STATE; + return; + } + this->raise( L"起こるはずないエラー。" ); // enterObject()ではじいてるからここには来ない。 + } + virtual void gotValue( const Token& token ) + { + if( this->depth == IN_PATTERN ) { + if( this->objkey.empty() ) { + // got an object key + this->objkey = token.value; + return; + } + if( this->objkey == L"regex" && token.type == Token::T_RXPATTERN ) { + this->pattern.patternStr.clear(); + this->pattern.patternStr.append( 1, L'/' ).append( token.value ).append( 1, L'/' ); + return; // T_RXPATTERNは特別で、必ず T_RXFLAGが続く。合わせて一つの値。だから this->objkeyをクリアしない。 + } + // got an object value + if( this->objkey == L"regex" ) { + if( token.type == Token::T_RXFLAG ) { + this->pattern.patternStr.append( token.value ); + if( ! this->pattern.compile() ) { + this->raise( Pattern::szLastErrMsg ); + } + } + } else if( this->objkey == L"style" ) { + if( token.type == Token::T_STRING ) { + this->pattern.colors.push_back( ActualColor( ColorNametoColorIndexType( token.value ) ) ); + } else { + this->raise( L"無効な色指定。" ); + } + } else if( this->objkey == L"next" ) { + if( token.type == Token::T_NUMBER ) { + this->pattern.nextState = _wtoi( token.value.c_str() ); + } + } else if( this->objkey == L"exit" ) { + this->pattern.nextState = -2; + } else if( this->objkey == L"exitall" ) { + this->pattern.nextState = -3; + } else if( this->objkey == L"state" ) { + this->pattern.isState = true; + } + this->objkey.clear(); + return; + } else if( this->depth == IN_STYLE ) { + if( token.type == Token::T_STRING ) { + EColorIndexType color = ColorNametoColorIndexType( token.value ); + if( 0 <= color && color < COLORIDX_LAST ) { + this->pattern.colors.push_back( color ); + return; + } + } + this->pattern.colors.push_back( CTRLCOLOR_REGEX_NOTSPECIFIED ); + return; + } + this->raise( L"予期せぬ値。" ); + } + virtual void error( const unsigned index, const wchar_t* const szErrMsg ) + { + this->messageBox( szErrMsg, index - this->linePos ); + throw FormatError(); + } + + void messageBox( const wchar_t* const szErrMsg, const int stateIndex, const int patternIndex ) const + { + std::wostringstream ss; + ss << szErrMsg << std::endl << std::endl; + ss << this->szPath << L"(state" << stateIndex; + if( 0 <= patternIndex ) { + ss << L",pattern" << patternIndex; + } + ss << L')'; + ::MessageBoxW( CEditWnd::Instance()->GetHwnd(), ss.str().c_str(), L"Sakura Editor", MB_OK|MB_ICONEXCLAMATION); + } + void messageBox( const wchar_t* const szErrMsg, const CLogicInt pos = -1 ) const + { + std::wostringstream ss; + ss << szErrMsg << std::endl << std::endl; + ss << this->szPath; + if( 0 <= pos) { + ss << L"(line:" << this->lineNum << L", col:" << pos << L')'; + } + ::MessageBoxW( CEditWnd::Instance()->GetHwnd(), ss.str().c_str(), L"Sakura Editor", MB_OK|MB_ICONEXCLAMATION); + } + }; + std::auto_ptr< std::vector > states( new std::vector() ); + try { + Reader reader( states.get() ); + reader.open( path.c_str() ); + reader.parse(); + } catch( Reader::FileOpenError ) { + } catch( Reader::FormatError ) { + states->clear(); + } + return states; +} + +static EColorIndexType ColorNametoColorIndexType( const std::wstring& colorName ) +{ + if( colorName.length() == 3 ) { + // WQTや SQTなどの色指定。3文字とは決まってないけど、今はそうなってる。 + const EColorIndexType color = GetColorIndexFromShortName( colorName.c_str() ); + if( color != COLORIDX_DEFAULT ) { + return color; + } + } else if( colorName.substr( 0, 3 ) == L"sh_" ) { + // SHJSの色指定。 + const struct entry { + const wchar_t* const sh_color; + const EColorIndexType color; + } map[] = { + //.sh_keyword /* language keywords */ + //.sh_type /* basic types */ + //.sh_usertype /* user defined types */ + //.sh_string /* strings and chars */ + //.sh_regexp /* regular expressions */ + //.sh_specialchar /* e.g., \n, \t, \\ */ + //.sh_comment /* comments */ + //.sh_number /* literal numbers */ + //.sh_preproc /* e.g., #include, import */ + //.sh_symbol /* e.g., <, >, + */ + //.sh_function /* function calls and declarations */ + //.sh_cbracket /* block brackets (e.g., {, }) */ + //.sh_todo /* TODO and FIXME */ + { L"sh_normal", COLORIDX_TEXT }, + { L"sh_keyword",COLORIDX_REGEX_KEYWORD }, + { L"sh_type", COLORIDX_REGEX_TYPE }, + { L"sh_string", COLORIDX_WSTRING }, + { L"sh_regexp", COLORIDX_REGEX_RXPATTERN }, + { L"sh_comment",COLORIDX_COMMENT }, + { L"sh_number", COLORIDX_DIGIT }, + { L"sh_preproc",COLORIDX_REGEX_CONSTANT }, + { L"sh_symbol", COLORIDX_REGEX_OPERATOR }, + { L"sh_function",COLORIDX_REGEX_FUNCTION }, + { L"sh_cbracket",COLORIDX_REGEX_BLOCK }, + + /* Predefined variables and functions (for instance glsl) */ + //.sh_predef_var + //.sh_predef_func + + /* for OOP */ + //.sh_classname + { L"sh_classname", COLORIDX_REGEX_TYPE }, + + /* Internet related */ + //.sh_url + { L"sh_url", COLORIDX_URL }, + + /* for ChangeLog and Log files */ + //.sh_date + //.sh_time, .sh_file + //.sh_ip, .sh_name + { L"sh_date", COLORIDX_REGEX_DATE }, + { L"sh_time", COLORIDX_REGEX_TIME }, + { L"sh_file", COLORIDX_URL }, + { L"sh_ip", COLORIDX_URL }, + + /* for Prolog, Perl... */ + //.sh_variable + { L"sh_variable", COLORIDX_REGEX_VARIABLE }, + + /* for LaTeX */ + //.sh_italics + //.sh_bold + //.sh_underline + //.sh_fixed + //.sh_argument + //.sh_optionalargument + //.sh_math + //.sh_bibtex + + /* for diffs */ + //.sh_oldfile + //.sh_newfile + //.sh_difflines + { L"sh_oldfile", COLORIDX_URL }, + { L"sh_newfile", COLORIDX_URL }, + + /* for css */ + //.sh_selector + //.sh_property + //.sh_value + { L"sh_selector", COLORIDX_REGEX_VARIABLE }, + { L"sh_prperty", COLORIDX_REGEX_TYPE }, + { L"sh_value", COLORIDX_WSTRING }, + + /* other */ + //.sh_section + //.sh_paren + //.sh_attribute + { L"sh_section", COLORIDX_REGEX_BLOCK }, + { L"sh_attribute", COLORIDX_REGEX_VARIABLE }, + }; + for( int i = 0; i != _countof(map); ++i ) { + if( std::wstring::npos != colorName.find( map[i].sh_color ) ) { + return map[i].color; + } + } + } else { + // 強調キーワード1や正規表現キーワード1などの色指定。 + const EColorIndexType color = GetColorIndexFromLongName( colorName.c_str() ); + if( color != COLORIDX_DEFAULT ) { + return color; + } + } + return COLORIDX_DEFAULT; +} + +static inline bool IsHintValid( const HintImpl* const pHint, const std::vector* const pStates, const CEditDoc* const pDoc ) +{ + // ヒントとドキュメントは関連があるか? + // ヒントと正規表現キーワードセットは関連があり、正規表現キーワードの設定に変更はなかったか? + return pHint->pDoc == pDoc && pHint->pStates == pStates; +} + +static inline bool IsLineMatchAvailable( const HintImpl* const pHint, const CLogicInt nLineNumber ) +{ + return pHint->lineMatchLineNum == nLineNumber; +} + +static void FetchLineMatch( HintImpl* const pHint, const CEditDoc* const pDoc, const CLogicInt nLineNumber ) +{ + if( nLineNumber < pHint->nextStartingStates.size() ) { + //// 過去のキャッシュを精算する。 + // IsInsideKeyword()から呼ばれたときは精算したらダメっぽいのでコメントアウトして様子を見る。 + //pHint->nextStartingStates.resize( nLineNumber ); + } else if( pHint->nextStartingStates.size() < nLineNumber ) { + // 一行まるまる他の色分けストラテジに食べられていた場合、与えられる nLineNumberは非連続になる。 + // とりあえずデフォルトで埋める。 + pHint->nextStartingStates.resize( nLineNumber ); + } + // 精算する。 + if( ! pHint->invalidLines.empty() && pHint->invalidLines.front() < nLineNumber ) { + std::vector::const_iterator it = pHint->invalidLines.begin(); + while( it != pHint->invalidLines.end() && *it < nLineNumber ) { + ++it; + } + pHint->invalidLines.erase( pHint->invalidLines.begin(), it ); + } + pHint->InvalidateLineCache( nLineNumber ); + + pHint->lineMatch = LineMatch( nLineNumber == 0 ? StartingStateOfLine() : pHint->nextStartingStates.at( nLineNumber - 1 ) ); + pHint->lineMatchLineNum = nLineNumber; +} + +static void PushColorDiv( LineMatch* const pLineMatch, const CLogicInt to, const EColorIndexType& color ); + +static CLogicInt AdvanceLineMatchPos( LineMatch* const pLineMatch, const std::vector* const pStates, const CDocLine* const pLine, const CLogicInt nPosWithinLine ) +{ + int stateIndex = pLineMatch->patternStack.empty() ? 0 : pLineMatch->patternStack.back()->nextState; + const RKW2::State& state = pStates->at( stateIndex ); + + std::list::iterator itStateMatch = std::find_if( pLineMatch->cache.begin(), pLineMatch->cache.end(), LineMatch::CacheFinder( stateIndex ) ); + if( itStateMatch == pLineMatch->cache.end() ) { // この Stateに移動してくるのが初めて(あるいはこの行に来たのが初めて)であれば + LineMatch::StateMatchCache stateMatch( stateIndex ); + for( std::vector::size_type iPattern = 0; iPattern != state.patterns.size(); ++iPattern ) { + stateMatch.cache.push_back( state.patterns.at( iPattern ).exec( pLine, nPosWithinLine ) ); + } + itStateMatch = pLineMatch->cache.insert( pLineMatch->cache.begin(), stateMatch ); + } + + // nPosWithinLineより後ろかつ一番近くでマッチするパターンを探します。 + int iBestPattern = -1; + int bestMatchIndex = -1; // mcState[iBestPattern].indexへのショートカット変数。 + for( std::vector::size_type iPattern = 0; iPattern != state.patterns.size(); ++iPattern ) { + MatchData& match = itStateMatch->cache.at( iPattern ); + if( match.null() ) { + continue; + } + if( match[0].index < nPosWithinLine ) { + match = state.patterns.at( iPattern ).exec( pLine, nPosWithinLine ); + if( match.null() ) { + continue; + } + } + if( iBestPattern == -1 || match[0].index < bestMatchIndex ) { + iBestPattern = iPattern; + bestMatchIndex = match[0].index; + if( bestMatchIndex == nPosWithinLine ) { + break; + } + } + } + + if( iBestPattern == -1 ) { + PushColorDiv( pLineMatch, pLine->GetLengthWithEOL(), CTRLCOLOR_REGEX_NOTSPECIFIED ); + } else { + const Pattern& bestPattern = state.patterns.at( iBestPattern ); // ショートカット変数。 + const MatchData& bestMatch = itStateMatch->cache.at( iBestPattern ); // ショートカット変数。 + + PushColorDiv( pLineMatch, bestMatch[0].index, CTRLCOLOR_REGEX_NOTSPECIFIED ); + if( bestMatch[0].index == nPosWithinLine + || pLineMatch->result.back() != CTRLCOLOR_REGEX_UNMATCHED + ) { + if( bestMatch[0].empty() ) { + // マッチが幅ゼロ。文字は出力しない。無限ループを防ぐ。 + itStateMatch->cache.at( iBestPattern ) = bestPattern.exec( pLine, bestMatch[0].lastIndex + 1 ); + } else { + if( bestMatch.size() == 1 || bestPattern.colors.size() == 1 ) { // キャプチャが使われていなかったり、色指定が単独の文字列だったら…… + PushColorDiv( pLineMatch, bestMatch[0].lastIndex, bestPattern.color( 0 ) ); + } else { + // JavaScriptとは違い、キャプチャの位置を知ることができる。だから SHJSのように、 + // パターン中のキャプチャを /(A)(B)(C)(D)/ というように隣接して並べる必要がない。 + std::vector colorMap; + colorMap.assign( bestMatch[0].size() + 1, bestPattern.color( 0 ) ); + for( unsigned iCapture = 1; iCapture != bestMatch.size(); ++iCapture ) { + if( ! bestMatch[iCapture].null() ) { + std::fill( + colorMap.begin() + ( bestMatch[iCapture].index - bestMatch[0].index ), + colorMap.begin() + ( bestMatch[iCapture].lastIndex - bestMatch[0].index ), + bestPattern.color( iCapture ) + ); + } + } + // 色のまとまりごとに Push。 + colorMap.back() = CTRLCOLOR_REGEX_UNMATCHED; // ありえない色指定を。 + struct PushColorOnColorDiv + { + LineMatch* const pLineMatch; + CLogicInt to; // color色の範囲。末尾の次。 + EColorIndexType color; + + PushColorOnColorDiv( LineMatch* const pLineMatch, const CLogicInt& offset, const EColorIndexType& color ) + : pLineMatch( pLineMatch ), to( offset ), color( color ){} + + void operator()( const EColorIndexType& color ) + { + if( color != this->color ) { + PushColorDiv( this->pLineMatch, this->to, this->color ); + this->color = color; + } + this->to += 1; + } + }; + std::for_each( colorMap.begin(), colorMap.end(), PushColorOnColorDiv( pLineMatch, bestMatch[0].index, colorMap.front() ) ); + } + } + + switch( bestPattern.nextState ) { + case -1: + // do nothing + break; + case -2: // exit + if( ! pLineMatch->patternStack.empty() ) { + pLineMatch->patternStack.pop_back(); + } + break; + case -3: // exitall + pLineMatch->patternStack.clear(); + break; + default: // next state index + if( 0 <= bestPattern.nextState && bestPattern.nextState < static_cast( pStates->size() ) ) { // 不正チェック。pStates構築時に一回だけ行う方が良い。 + pLineMatch->patternStack.push_back( &bestPattern ); + } else { + // do nothing + } + } + } + } + + return pLineMatch->result.size(); +} + +static void PushColorDiv( LineMatch* const pLineMatch, const CLogicInt to, const EColorIndexType& color ) +{ + if( to == pLineMatch->result.size() ) { + return; + } else if( to < pLineMatch->result.size() ) { + // 不正な操作があったか、呼び出しシークェンスが狂っている。 + return; + } + EColorIndexType newColor = color; + if( newColor == CTRLCOLOR_REGEX_NOTSPECIFIED ) { // 色が未指定なら、パターンスタックから引きつぐ + if( pLineMatch->patternStack.empty() ) { + newColor = CTRLCOLOR_REGEX_UNMATCHED; + } else if( ! pLineMatch->patternStack.back()->isState ) { + newColor = pLineMatch->patternStack.back()->color( 0 ); + } + if( newColor == CTRLCOLOR_REGEX_NOTSPECIFIED ) { + newColor = pLineMatch->result.back(); + } + } + pLineMatch->result.resize( to, newColor ); +} + +static inline CLogicInt PeekColorFromLineMatch( const LineMatch* const pLineMatch, const CLogicInt nPosWithinLine, EColorIndexType* const outColor ) +{ + if( 0 <= nPosWithinLine && nPosWithinLine < pLineMatch->result.size() ) { + EColorIndexType color = pLineMatch->result.at( nPosWithinLine ); + if( 0 <= color && color < COLORIDX_LAST ) { + if( outColor ) { + *outColor = color; + } + return pLineMatch->result.range_including( nPosWithinLine ).end - nPosWithinLine; + } + } + return 0; // 返す色はない(=正規表現キーワードはマッチしていない)。 +} + +static void LineHighlightDone( HintImpl* const pHint, const CLogicInt nLineNumber, const LineMatch& lineMatch ) +{ + // nLineNumber行目の色分け開始状態の無効化を忘れずに解除。 + if( ! pHint->invalidLines.empty() ) { + std::vector::const_iterator it = std::lower_bound( pHint->invalidLines.begin(), pHint->invalidLines.end(), nLineNumber ); + if( it != pHint->invalidLines.end() && *it == nLineNumber ) { + pHint->invalidLines.erase( it ); + } + } + + const StartingStateOfLine nextStartState = StartingStateOfLine( lineMatch.patternStack, lineMatch.result.back() ); + if( pHint->nextStartingStates.size() == nLineNumber ) { + pHint->nextStartingStates.push_back( nextStartState ); + } else if( pHint->nextStartingStates.size() < nLineNumber ) { + throw L"前の行から連続しない startingStateに意味はない。"; + } else { + // nLineNumber行目の色分け開始状態の変化は既に色分けの済んでいる後ろの行に波及する。 + if( pHint->nextStartingStates.at( nLineNumber ) != nextStartState ) { + pHint->nextStartingStates.assignable_at( nLineNumber ) = nextStartState; + pHint->InvalidateLineCache( nLineNumber + 1 ); + } + } + + pHint->internalStateID = pHint->nextStartingStates.find_first_of( nextStartState ) * COLORIDX_LAST + nextStartState.currentStyle; +} Index: sakura_core/view/colors/DivArray.h =================================================================== --- sakura_core/view/colors/DivArray.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/DivArray.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,198 @@ +#pragma once +#include +#include +#include + +template +class DivArray +{ + struct Div + { + I to; + V value; + + Div() + : to( 0 ), value() + {} + Div( const I to, const V& value ) + : to( to ), value( value ) + {} + }; + struct DivOrder { bool operator()( const Div& lhs, const Div& rhs ) const { return lhs.to < rhs.to; } }; + + struct Range + { + I begin, end; + + Range() + : begin( 0 ), end( 0 ) + {} + Range( const I begin, const I end ) + : begin( begin ), end( end ) + {} + bool empty() const + { + return begin == end; + } + }; + + mutable std::vector
vec; // range_including()で vec.erace()を行いたいから。内部表現の整理のためにメンバ関数の const性を失いたくない。 + +public: + typedef Range range_type; + + DivArray() + : vec( 0 ) + {} + DivArray( const I to, const V& value ) + : vec( 1, Div( to, value ) ) + { + assert( 0 <= this->vec.front().to ); + } + Range range_including( const I index ) const; + const V& at( const I index ) const + { + const std::vector
::const_iterator it = std::upper_bound( this->vec.begin(), this->vec.end(), Div( index, V() ), DivOrder() ); + return it->value; + } + const V& back() const + { + return this->vec.back().value; + } + bool empty() const + { + return this->vec.empty(); + } + I size() const + { + if( this->vec.empty() ) { + return I( 0 ); + } + return I( this->vec.back().to ); + } + void push_back( const V& value ) + { + if( this->vec.empty() ) { + this->vec.push_back( Div( 1, value ) ); + } else if( this->vec.back().value == value ) { + this->vec.back().to += 1; + } else { + this->vec.push_back( Div( this->vec.back().to + 1, value ) ); + } + } + V& assignable_at( const I index ); + void clear() + { + this->vec.clear(); + } + void resize( const I newSize, const V& value = V() ); + + I find_first_of( const V& value ) const + { + CLogicInt prevTo = 0; + for(unsigned i = 0; i != this->vec.size(); prevTo = this->vec[i++].to) + { + if(this->vec[i].value == value) { + break; + } + + } + return prevTo; + } +}; + +template +typename DivArray::Range DivArray::range_including( const I index ) const +{ + // 同じ valueを持つ Divが前後に連続しているかもしれない。(非const参照を返す at()メンバ関数が一つの理由) + // それらを結合して内部配列を整理し、正しい範囲を求める。 + const std::vector
::const_iterator itCenter = std::upper_bound( this->vec.begin(), this->vec.end(), Div( index, V() ), DivOrder() ); + std::vector
::const_iterator itFirst = itCenter; + if( itFirst != this->vec.begin() ) { + while( itFirst != this->vec.begin() && itFirst->value == itCenter->value ) { // このループは最低一巡はする。 + --itFirst; + } + ++itFirst; // だからこのインクリメントで itCenterを超えることはない。 + } + std::vector
::const_iterator itLast = itCenter; + if( itLast != this->vec.end() ) { + while( itLast != this->vec.end() && itLast->value == itCenter->value ) { + ++itLast; + } + --itLast; + } + const std::vector
::const_iterator it = itFirst != itLast ? this->vec.erase( itFirst , itLast ) : itFirst; // 整理! + // itFirst, itCenter, itLast は無効化されてるかもしれないので、もう使わない。 + if( it == this->vec.end() ) { // 気のまわしすぎかも。std::out_of_range exceptionでもよい。 + return Range( index, index ); + } + if( it == this->vec.begin() ) { + return Range( 0, it->to ); + } + return Range( (it-1)->to, it->to ); +} + +template +V& DivArray::assignable_at( const I index ) +{ + std::vector
::iterator div = std::upper_bound( this->vec.begin(), this->vec.end(), Div( index, V() ), DivOrder() ); + const unsigned divWidth = div == this->vec.begin() ? div->to - 0 : div->to - (div-1)->to; + if( divWidth == 1 ) { + return div->value; + } else if( divWidth < 1 ) { + return div->value; // よくわからん状態だけど、一応。 + } else { + if( index + 1 == div->to ) { + // indexは divの範囲の末尾を指している。divを一つ縮めて後ろに幅1の、valueを変更されても構わない要素を挿入する。 + div->to -= 1; + return this->vec.insert( div + 1, Div( index + 1, div->value ) )->value; + } else if( index + divWidth == div->to ) { + // indexは divの範囲の先頭を指している。divの前に幅1の、valueを変更されても構わない要素を追加する。(divの幅は自動的に 1小さくなる) + return this->vec.insert( div, Div( index + 1, div->value ) )->value; + } else { + // indexは divの範囲の中間を指している。divを分割し、真ん中に幅1の、valueを変更されても構わない要素を追加する。 + div = this->vec.insert( div, Div( index + 1, div->value ) ); + div = this->vec.insert( div, Div( index, div->value ) ); + return (div + 1)->value; + } + } +} + +template +void DivArray::resize( const I newSize, const V& value ) +{ + if( newSize < 0 ) { + return; + } + if( newSize == 0 ) { + this->vec.clear(); + return; + } + // 以下、newSizeは 0より大きい。 + if( this->vec.empty() ) { + this->vec.push_back( Div( newSize, value ) ); + return; + } + // 以下、vecは空ではない。 + if( this->vec.back().to < newSize ) { + if( this->vec.back().value == value ) { + this->vec.back().to = newSize; + } else { + this->vec.push_back( Div( newSize, value ) ); + } + } else if( newSize < this->vec.back().to ) { + const std::vector
::iterator it = std::upper_bound( this->vec.begin(), this->vec.end(), Div( newSize, V() ), DivOrder() ); + if( it == this->vec.begin() ) { + it->to = newSize; + this->vec.erase( it + 1, this->vec.end() ); + } else if( (it-1)->to == newSize ) { + this->vec.erase( it, this->vec.end() ); + } else { + it->to = newSize; + this->vec.erase( it + 1, this->vec.end() ); + } + } else { // newSize == this->vec.size() + // することがない。 + } + return; +} Index: sakura_core/view/colors/CColorML_Quote.cpp =================================================================== --- sakura_core/view/colors/CColorML_Quote.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_Quote.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,73 @@ +#include "StdAfx.h" +#include "mem/CNativeW.h" +#include "view/colors/EColorIndexType.h" +#include "view/colors/CColorML_Quote.h" + +static CLogicInt SeekDelimiter( const CStringRef* const pLine, const CLogicInt startIndex, const wchar_t delim, const wchar_t escape = L'\0' ); + + +const CLogicInt CColorML_Quote::IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + CLogicInt& posEndOfQuote = *reinterpret_cast( userData ); + const CStringRef& line = pLine->GetStringRefWithEOL(); + if( this->delim == line.At( nPosWithinLine ) ) { + posEndOfQuote = -1; // IsInsideKeyword()へ終了位置が未定だというメッセージ。 + *outColor = this->color; + return 1; // デリミタ(文字列の開始文字)の長さ。 + } + return 0; +} + +const CLogicInt CColorML_Quote::IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + CLogicInt& posEndOfQuote = *reinterpret_cast( userData ); + if( nPosWithinLine == posEndOfQuote ) { + return 0; // 文字列終了。nPosWithinLine-1 が閉じ引用符だった。 + } + *outColor = this->color; + const CStringRef& line = pLine->GetStringRefWithEOL(); + const CLogicInt posDelim = SeekDelimiter( &line, nPosWithinLine, this->delim, this->escape ); + if( line.GetLength() <= posDelim ) { + return -1; // 次の行へ続く。 + } + // 終了位置が見つかった。次の IsInsideKeyword()で終了。 + posEndOfQuote = posDelim + 1; // 終了デリミタの次の文字の位置。 + return posDelim + 1 - nPosWithinLine; // デリミタを含めた残りの長さ。 +} + + +/** pLineの指定された位置(startIndex)からデリミタを検索し、その位置を返す。(位置は startIndexからの相対位置ではない) + 見つからなかったときの戻り値は、pLine->GetLength()以上の無効なインデックスである。 +*/ +static CLogicInt SeekDelimiter( const CStringRef* const pLine, const CLogicInt startIndex, const wchar_t delim, const wchar_t escape ) +{ + CLogicInt pos = startIndex; + for( ; pos < pLine->GetLength(); pos += CNativeW::GetSizeOfChar( pLine->GetPtr(), pLine->GetLength(), pos ) ) { + if( escape && escape == pLine->At( pos ) ) { + if( escape == delim ) { + // delimiterの連続なら飛ばし。 + if( pos + 1 < pLine->GetLength() && escape == pLine->At( pos + 1 ) ) { + pos += 1; + continue; + } + } else { + // エスケープされた文字。無条件で飛ばし。 + pos += 1; + continue; + } + } + if( delim == pLine->At( pos ) ) { + break; + } + } + return pos; +} + + +CColorML_WQuote::CColorML_WQuote( const wchar_t escape ) +: CColorML_Quote( COLORIDX_WSTRING, L'\"', escape ) +{} + +CColorML_SQuote::CColorML_SQuote( const wchar_t escape ) +: CColorML_Quote( COLORIDX_SSTRING, L'\'' , escape ) +{} Index: sakura_core/view/colors/ColorMLStrategy.cpp =================================================================== --- sakura_core/view/colors/ColorMLStrategy.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/ColorMLStrategy.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,225 @@ +#include "StdAfx.h" +#include +#include +#include "mem/CNativeW.h" +#include "view/colors/DivArray.h" +#include "view/colors/EColorIndexType.h" +#include "view/colors/ColorMLStrategy.h" + + +/** 色分けを行わない色分け戦略。 + 存在理由は StartingStrategy.indexのデフォルト。 + デフォルトが存在することでインデックスが常に有効な値になる。 +*/ +const class NullStrategy +: public CColorML_Base +{ +public: + virtual const CLogicInt IsStartOfKeyword( const CEditDoc* const, const CLogicInt, const CDocLine* const, const CLogicInt, EColorIndexType* const, void** ) + { return 0; } + virtual const CLogicInt IsInsideKeyword( const CEditDoc* const, const CLogicInt, const CDocLine* const, const CLogicInt, EColorIndexType* const, void** ) + { return 0; } +}; + + +/* + class SimpleColorStrategy +*/ + +SimpleColorStrategy::SimpleColorStrategy( const CEditDoc* const pDoc ) +: pDoc( pDoc ), strategies( 0 ) +{ + this->strategies.push_back( new NullStrategy() ); +} + +SimpleColorStrategy::~SimpleColorStrategy() +{ + while( this->strategies.empty() ) { + delete this->strategies.back(); + this->strategies.pop_back(); + } +} + +struct StartingStrategy +{ + unsigned index; + void* data; + + StartingStrategy() + : index( 0 ), data( 0 ) + {} + StartingStrategy( const int& strategyIndex, void* const data = NULL ) + : index( strategyIndex ), data( data ) + {} + bool operator==( const StartingStrategy& other ) const + { + return this->index == other.index && this->data == other.data; + } + bool operator!=( const StartingStrategy& other ) const + { + return ! (*this == other); + } +}; + +static StartingStrategy DoHighlightLine( const std::vector& strategies, const CEditDoc* const pDoc, const CLogicInt nLineNumber, const StartingStrategy& startingStrategy, SimpleColorStrategy::Result* const outResult = 0 ); + +void SimpleColorStrategy::HighlightLine( const CEditDoc* const pDoc, const CLogicInt nLineNumber, Result* const outResult ) +{ + if( ! outResult) { + return; + } + DoHighlightLine( this->strategies, pDoc, nLineNumber, StartingStrategy( 0 ), outResult ); +} + + +/* + class ColorMLStrategy +*/ + +class ColorMLStrategy::HighlightEngine +{ +public: + typedef DivArray + StartingStrategies; + + StartingStrategies startingStrategies; // emptyにしちゃダメ。0行目の startingStrategyは常に決まっているでしょう。 + std::vector invalidLines; // 昇順ソート済み(約束!)。 + + HighlightEngine() + : startingStrategies( 1, StartingStrategy() ), invalidLines( 0 ) + {} + + void HighlightLine( const std::vector& strategies, const CEditDoc* const pDoc, const CLogicInt nLineNumber, ColorMLStrategy::Result* const outResult ); + bool InvalidateLine( const CLogicInt nLineNumber ); +}; + +ColorMLStrategy::ColorMLStrategy( const CEditDoc* const pDoc ) +: SimpleColorStrategy( pDoc ), engine( new HighlightEngine() ) +{} +ColorMLStrategy::~ColorMLStrategy() +{} + +void ColorMLStrategy::NotifyLineChange( const CLogicInt nLineNumber ) +{ + this->engine->InvalidateLine( nLineNumber ); + // 構成メンバに通知 + for( std::vector::size_type i = 0; i != this->strategies.size(); ++i ) { + this->strategies.at( i )->LineChanged( this->pDoc, nLineNumber ); + } +} + +void ColorMLStrategy::NotifyLineChangeAfter( const CLogicInt nLineNumber ) +{ + this->engine->startingStrategies.resize( nLineNumber + 1 ); + // 構成メンバに通知 + for( unsigned i = 0; i != this->strategies.size(); ++i ) { + this->strategies.at( i )->LinesChangedAfter( this->pDoc, nLineNumber ); + } +} + +void ColorMLStrategy::HighlightLine( const CEditDoc* const pDoc, const CLogicInt nLineNumber, Result* const outResult ) +{ + this->engine->HighlightLine( this->strategies, pDoc, nLineNumber, outResult ); +} + + +/* + ファイルローカルな実装 +*/ + +static StartingStrategy DoHighlightLine( const std::vector& strategies, const CEditDoc* const pDoc, const CLogicInt nLineNumber, const StartingStrategy& startingStrategy, SimpleColorStrategy::Result* const outResult ) +{ + const CDocLine* const pLine = pDoc->m_cDocLineMgr.GetLine( nLineNumber ); + const CLogicInt len = pLine->GetLengthWithEOL(); + std::vector vStrategiesData( strategies.size(), 0 ); + unsigned iStrategy = startingStrategy.index; + vStrategiesData.at( iStrategy ) = startingStrategy.data; + void** strategiesData = &(vStrategiesData.front()); // vectorの要素に配列風にアクセスするためのショートカット変数。 + + EColorIndexType prevColor = COLORIDX_DEFAULT; + CLogicInt pos = 0; + while( pos < len ) { + EColorIndexType color; + CLogicInt colorLen = strategies[iStrategy]->IsInsideKeyword( pDoc, nLineNumber, pLine, pos, &color, strategiesData + iStrategy ); + if( colorLen == 0 ) { + for( iStrategy = 0; iStrategy != strategies.size(); ++iStrategy ) { + colorLen = strategies[iStrategy]->IsStartOfKeyword( pDoc, nLineNumber, pLine, pos, &color, strategiesData + iStrategy ); + if( colorLen != 0 ) { + break; + } + } + } + if( colorLen == 0 ) { + iStrategy = 0; + color = COLORIDX_DEFAULT; + } + // colorLenを一文字分のサイズ以上から、行末を超えない長さまでに制限する。 + colorLen = colorLen < 0 ? len - pos : std::min( len - pos, std::max( colorLen, CNativeW::GetSizeOfChar( pLine->GetPtr(), pLine->GetLengthWithEOL(), pos ) ) ); + if( color != prevColor ) { + if( outResult && pos != 0 ) { + outResult->colorInfo.resize( pos, prevColor ); + } + prevColor = color; + } + pos += colorLen; + } + if( outResult ) { + outResult->colorInfo.resize( pos, prevColor ); + } + return StartingStrategy( iStrategy, strategiesData[iStrategy] ); +} + +void ColorMLStrategy::HighlightEngine::HighlightLine( const std::vector& strategies, const CEditDoc* const pDoc, const CLogicInt nLineNumber, ColorMLStrategy::Result* const outResult ) +{ + // ハイライトしたい行より前の、無効化されて再度色分けの必要な行、 + // まだ色分けが完了していない行を先頭に近い行から順番に処理していく。 + for( ;; ) { + const CLogicInt invalidLine = ! this->invalidLines.empty() ? this->invalidLines.front() : static_cast( std::numeric_limits::max() ); + const CLogicInt notHighlightedLine = this->startingStrategies.size() - 1; + const CLogicInt lineToHighlight = std::min( nLineNumber, std::min( invalidLine, notHighlightedLine ) ); + if( lineToHighlight == invalidLine ) { + this->invalidLines.erase( this->invalidLines.begin() ); + } + if( lineToHighlight == nLineNumber ) { + break; + } + const StartingStrategy startingStrategy = this->startingStrategies.at( lineToHighlight ); + const StartingStrategy nextLineStrategy = DoHighlightLine( strategies, pDoc, lineToHighlight, startingStrategy, NULL ); + if( this->startingStrategies.size() - 1 == lineToHighlight ) { + this->startingStrategies.push_back( nextLineStrategy ); + } else if( this->startingStrategies.at( lineToHighlight + 1 ) != nextLineStrategy ) { + this->startingStrategies.assignable_at( lineToHighlight + 1 ) = nextLineStrategy; + this->InvalidateLine( lineToHighlight + 1 ); + } + } + + // 準備完了。いざ。 + if( outResult ) { + outResult->colorInfo.clear(); + outResult->nextLineHighlightChanged = false; + } + const StartingStrategy startingStrategy = this->startingStrategies.at( nLineNumber ); + const StartingStrategy nextLineStrategy = DoHighlightLine( strategies, pDoc, nLineNumber, startingStrategy, outResult ); + if( this->startingStrategies.size() - 1 == nLineNumber ) { + this->startingStrategies.push_back( nextLineStrategy ); + if( outResult ) { + outResult->nextLineHighlightChanged = true; + } + } else if( this->startingStrategies.at( nLineNumber + 1 ) != nextLineStrategy ) { + this->startingStrategies.assignable_at( nLineNumber + 1 ) = nextLineStrategy; + this->InvalidateLine( nLineNumber + 1 ); + if( outResult ) { + outResult->nextLineHighlightChanged = true; + } + } +} + +bool ColorMLStrategy::HighlightEngine::InvalidateLine( const CLogicInt nLineNumber ) +{ + std::vector::const_iterator it = std::lower_bound( this->invalidLines.begin(), this->invalidLines.end(), nLineNumber ); + if( it == this->invalidLines.end() || *it != nLineNumber ) { // 重複していなければ…… + this->invalidLines.insert( it, nLineNumber ); + return true; + } + return false; +} Index: sakura_core/view/colors/CColorML_KeywordSet.cpp =================================================================== --- sakura_core/view/colors/CColorML_KeywordSet.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_KeywordSet.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,85 @@ +#include "StdAfx.h" +#include "mem/CNativeW.h" +#include "charset/charcode.h" +#include "env/DLLSHAREDATA.h" +#include "view/colors/CColorML_KeywordSet.h" + +/** 文字を分類する。 + @retval 0 キーワードに使える文字ではない。 + @retval その他の数 連続する同じ数の文字が一つのキーワードをつくる。 + たとえば、ABCDEFGという文字列があり、それぞれの文字の CharTypeが順番に 1121133だったとすると、AB、C、DE、FGがキーワード候補になる。 +*/ +static int CharType( const wchar_t wch ); + +/** startより後ろの語の境界の位置を返す。 + startより前の文字は読まない。一番大きい戻り値は line.GetLength()と等しくなる。 +*/ +static CLogicInt NextWordBreak( const CStringRef& line, const CLogicInt start ); + +const CLogicInt CColorML_KeywordSet::IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + CLogicInt& posNextWordHead = *reinterpret_cast( userData ); + if( nPosWithinLine < posNextWordHead ) { + return 0; // 以前の調査でキーワードでないことがわかっている。 + } + const CStringRef& line = pLine->GetStringRefWithEOL(); + const int charType = CharType( line.At( nPosWithinLine ) ); + if( ! charType ) { + return 0; // この文字はキーワード対象文字ではない。 + } + if( 0 < nPosWithinLine && charType == CharType( line.At( nPosWithinLine - 1 ) ) ) { + return 0; // 語の境界ではなかった。 + } + posNextWordHead = NextWordBreak( line, nPosWithinLine ); + + // nPosWithinLine...posWordEnd がキーワード候補。 + CLogicInt posWordEnd = posNextWordHead; + while( posWordEnd <= line.GetLength() ) { + const int ret = GetDllShareData().m_Common.m_sSpecialKeyword.m_CKeyWordSetMgr.SearchKeyWord2( this->keywordSet, line.GetPtr() + nPosWithinLine, posWordEnd - nPosWithinLine ); + if( 0 <= ret ) { + // 登録されたキーワードだった。 + break; + } else if( ret == -1 ) { + // 登録されたキーワードではなかった。 + } else if( ret == -2 ) { + // 長さが足りなかったので延長してリトライ。 + if( posWordEnd < line.GetLength() ) { + posWordEnd = NextWordBreak( line, posWordEnd ); + continue; + } + } + // 登録されたキーワードではなかった。 + posWordEnd = nPosWithinLine; + break; + } + // nPosWithinLine...posWordEnd がキーワード。 + *outColor = this->color; + return std::max( 0, posWordEnd - nPosWithinLine ); +} + +const CLogicInt CColorML_KeywordSet::IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + return 0; +} + + +static inline int CharType( const wchar_t wch ) +{ + if( ! wch || WCODE::IsBlank( wch ) || WCODE::IsLineDelimiter( wch ) || WCODE::IsControlCode( wch ) ) { + return 0; + } + const int charType = IS_KEYWORD_CHAR( wch ) ? 1 : 2; + return charType; +} + +static CLogicInt NextWordBreak( const CStringRef& line, const CLogicInt start ) +{ + const int charType = CharType( line.At( start ) ); + CLogicInt result = start; + for( ; result < line.GetLength(); result += CNativeW::GetSizeOfChar( line.GetPtr(), line.GetLength(), result ) ) { + if( charType != CharType( line.At( result ) ) ) { + break; + } + } + return result; +} Index: sakura_core/view/colors/RKW2.h =================================================================== --- sakura_core/view/colors/RKW2.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/RKW2.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,87 @@ +#pragma once +#include +#include +#include "types/CType.h" /* CTypeConfig, STypeConfig */ +#include "basis/SakuraBasis.h" /* CLogicInt */ +#include "util/design_template.h" /* TSingleton */ +class CEditDoc; +enum EColorIndexType; + +/** 一つのタイプ別設定の正規表現キーワード一式を表す。 + ドキュメントのある行、ある位置の色分け結果を返す。 + 正規表現キーワードの色分け戦略の実務を担当する。 +*/ +class RKW2 +{ +public: + struct State; + + /** 文書( CEditDoc )の行配列と深く結びついた、RKW2が利用する内部情報。 + 文書間で共有はできません。同じ文書でも行の内容が変わるたびに + ヒントの情報を無効化しないといけません。このヒントがないと + ある行を色分けするために、文書の最初から色分けをやり直す羽目になります。 + RKW2::CreateHint()を利用してインスタンスを入手する。 + */ + struct Hint + { + virtual ~Hint() {}; + virtual void InvalidateAllCache() = 0; + virtual void InvalidateLineCache( const CLogicInt nLineNumber ) = 0; + virtual void InvalidateLineCacheAfter( const CLogicInt nLineNumber ) = 0; + }; + static std::auto_ptr CreateHint(); + + RKW2( const STypeConfig& doctype ); + ~RKW2(); + + /** ドキュメントのある行ある桁が正規表現キーワードの*開始位置*であるならば、outColorにキーワードの色をセットし、キーワードの長さを返す。 + さもなければ outColorにはさわらず、0を返す。 + 開始位置であることにこだわるのは、正規表現キーワードが開始位置より前から開始位置をまたいでマッチしてはいけないから。 + 開始位置より前の文字は別の色分けストラテジによって消費されている可能性がある。 + */ + CLogicInt IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, Hint* const pHint, EColorIndexType* const outColor ) const; + + /** IsStartOfKeyword()との違いは nPosWithinLineパラメータが正規表現キーワードの開始位置を規定しないことのみ。 + IsStartOfKeyword()に続けてこれを呼び出すことになろう。IsStartOfKeyword()は nPosWithinLineより前から始まり nPosWithinLineを + 超えて継続するキーワードをマッチしなかったものとして破棄するので、連続して呼び出すことはできない。 + */ + CLogicInt IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, Hint* const pHint, EColorIndexType* const outColor = NULL ) const; + + int InternalStateID( const Hint* pHint ) const; + +private: + RKW2( const RKW2& NO_COPY ); + const std::vector* const states; +}; + + +/** RKW2のインスタンスを手に入れる簡便な方法を提供するクラス。 + 設定ファイル( DLLSHAREDATA.m_Types[].{m_bUseRegexKeyword | nRegexKeyMagicNumber | m_RegexKeywordArr[]} )と結びつき、 + ファイルタイプに基づいた正規表現キーワード( RKW2 )を提供する。タイプ別設定に変更があれば RKW2のインスタンスを + 作り直したりもする(予定)。 +*/ +class RKW2Holder +: public TSingleton +{ +public: + static const RKW2* GetRKW2( const CTypeConfig& doctype ) + { + RKW2Holder* const self = RKW2Holder::Instance(); + if( ! self ) { + return 0; + } + if( self->doctype.GetIndex() != doctype.GetIndex() || ! self->rkw2.get() ) { + self->rkw2.reset( new RKW2( *doctype.GetTypeConfig() ) ); + self->doctype = doctype; + } + return self->rkw2.get(); + } + + RKW2Holder() + : rkw2( 0 ), doctype( 0/*たぶん「基本」*/ ) + {} + +private: + std::auto_ptr rkw2; + CTypeConfig doctype; /* rkw2がどのタイプ別設定の正規表現キーワードであるか。*/ +}; Index: sakura_core/view/colors/JSON_reader.cpp =================================================================== --- sakura_core/view/colors/JSON_reader.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/JSON_reader.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,342 @@ +#include "StdAfx.h" +#include "view/colors/JSON_checker.h" +#include "view/colors/JSON_reader.h" + +/** JSON_checkerのある瞬間の状態(mode, state, stackSize)を記憶するためのクラス。 + stackがない分だけ軽い。 +*/ +class JSON_checker_state +{ +public: + JSON_checker_state( const JSON_checker& jc ) + : mode_( jc.mode() ), state_( jc.state() ), stackSize_( jc.stackSize() ) + {} + void reset( const JSON_checker& jc ) + { this->mode_ = jc.mode(); this->state_ = jc.state(); this->stackSize_ = jc.stackSize(); } + + const JSON_checker::Mode& mode() const { return this->mode_; } + const JSON_checker::State& state() const { return this->state_; } + const JSON_checker::size_type& stackSize() const { return this->stackSize_; } + +private: + JSON_checker::Mode mode_; + JSON_checker::State state_; + JSON_checker::size_type stackSize_; +}; + +/** JSON_reader::parse()の実質的な実装を受け持つクラス。 + JSON_reader.hに書く情報を少なくするために別のクラスにして、 + friend指定だけしておき、ここ(実装ファイル)で宣言している。 +*/ +class JSON_reader_driver +{ +public: + JSON_reader_driver( JSON_reader* const reader ) + : reader( reader ), token() + {} + void charEaten( const JSON_checker& jc, const wchar_t ch, const JSON_checker_state& prevJc ); + +private: + JSON_reader* reader; + JSON_reader::Token token; + void noneChanged( const JSON_checker& jc, const wchar_t ch ); + void stateChanged( const JSON_checker& jc, const wchar_t ch, const JSON_checker_state& prevJc ); + void modePushed( const JSON_checker& jc, const wchar_t ch, const JSON_checker_state& prevJc ); + void modePopped( const JSON_checker& jc, const wchar_t ch, const JSON_checker_state& prevJc ); + void modeChanged( const JSON_checker& jc, const wchar_t ch, const JSON_checker_state& prevJc ); + static bool isNumericState( const JSON_checker::State state ); + static bool isStringState( const JSON_checker::State state ); + static bool isRegexState( const JSON_checker::State state ); +}; + +/** JSON_reader::raise()を呼ぶことにより投げられる例外クラス。 + JSON_reader::raise()は、JSON_readerを継承したクラスが + JSON_reader::parse()を失敗させる手段として用意した。 +*/ +struct UserError +{ + const wchar_t* const message; + UserError( const wchar_t* const message ) + : message( message ) + {} +}; + +/* + JSON_reader::Token 実装 +*/ +const wchar_t* JSON_reader::Token::to_str() const +{ + static const wchar_t* szTypes[NR_TOKENS]; + for( int i = 0; i != NR_TOKENS; ++i ) { + szTypes[i] = L"UNKNOWN"; + } + szTypes[T_IDENT] = L"IDENT"; + szTypes[T_STRING] = L"STRING"; + szTypes[T_RXPATTERN] = L"RXPATTERN"; + szTypes[T_RXFLAG] = L"RXFLAG"; + szTypes[T_NUMBER] = L"NUMBER"; + szTypes[T_TRUE] = L"TRUE"; + szTypes[T_FALSE] = L"FALSE"; + szTypes[T_NULL] = L"NULL"; + + if( this->type < 0 || NR_TOKENS <= this->type ) { + return L"UNKNOWN"; + } + return szTypes[this->type]; +} + +/* + JSON_reader 実装 +*/ +bool JSON_reader::parse() +{ + JSON_reader_driver driver( this ); + JSON_checker jc; + JSON_checker_state prevJc( jc ); + unsigned charIdx = 0; + try { for(;;) { + const wchar_t *begin = 0, *end = 0, *p = 0; + if( ! this->read( &begin, &end ) || ! begin || ! end || end <= begin ) { + break; + } + for( p = begin; p != end; ++p, ++charIdx) { + const wchar_t next_char = *p; + if( ! next_char ) { + break; + } + if( ! jc.nextChar( next_char ) ) { + this->error( charIdx, jc.errorMessage( jc.error ) ); + return false; + } + driver.charEaten( jc, next_char, prevJc ); + prevJc.reset( jc ); + } + if( p == end ) { + continue; + } + break; + } } catch( UserError err ) { + this->error( charIdx, err.message ); + return false; + } + if( ! jc.done() ) { + this->error( charIdx, L"JSON_checker: immature json text.\n" ); + return false; + } + return true; +} + +void JSON_reader::raise( const wchar_t* const errMsg ) +{ + throw UserError( errMsg ); +} + + +/* + JSON_reader_driver 実装 +*/ +void JSON_reader_driver::charEaten( const JSON_checker& jc, const wchar_t ch, const JSON_checker_state& prevJc ) +{ + if( prevJc.stackSize() < jc.stackSize() ) { + this->modePushed( jc, ch, prevJc ); + } else if( jc.stackSize() < prevJc.stackSize() ) { + this->modePopped( jc, ch, prevJc ); + } else if( jc.mode() != prevJc.mode() ) { + this->modeChanged( jc, ch, prevJc ); + } else if( jc.state() != prevJc.state() ) { + this->stateChanged( jc, ch, prevJc ); + } else { + this->noneChanged( jc, ch ); + } +} + +void JSON_reader_driver::noneChanged( const JSON_checker&, const wchar_t ch ) +{ + this->token.value.append( 1, ch ); +} + +void JSON_reader_driver::stateChanged( const JSON_checker& jc, const wchar_t ch, const JSON_checker_state& prevJc ) +{ + switch( prevJc.state() ) + { + case JSON_checker::ID: + this->token.type = JSON_reader::Token::T_IDENT; + this->reader->gotValue( this->token ); + break; + + case JSON_checker::ST: + case JSON_checker::SQ: + if( jc.state() == JSON_checker::OK || jc.state() == JSON_checker::CO ) { + // got quoted string + this->token.type = JSON_reader::Token::T_STRING; + this->reader->gotValue( this->token ); + } + break; + + case JSON_checker::T3: + // got true + this->token.type = JSON_reader::Token::T_TRUE; + this->token.value = L"true"; + this->reader->gotValue( this->token ); + break; + case JSON_checker::F4: + // got false + this->token.type = JSON_reader::Token::T_FALSE; + this->token.value = L"false"; + this->reader->gotValue( this->token ); + break; + case JSON_checker::N3: + // got null + this->token.type = JSON_reader::Token::T_NULL; + this->token.value = L"null"; + this->reader->gotValue( this->token ); + break; + + case JSON_checker::MI: + case JSON_checker::ZE: + case JSON_checker::IN: + case JSON_checker::FR: + case JSON_checker::E1: + case JSON_checker::E2: + case JSON_checker::E3: + if( ! this->isNumericState( jc.state() ) ) { + // got a numeric value + this->token.type = JSON_reader::Token::T_NUMBER; + this->token.value.append( 1, ch ); + this->reader->gotValue( this->token ); + } + break; + + case JSON_checker::RF: + // got regex flag + this->token.type = JSON_reader::Token::T_RXFLAG; + this->reader->gotValue( this->token ); + break; + } + + switch( jc.state() ) + { + case JSON_checker::ID: + this->token.value.clear(); + this->token.value.append( 1, ch ); + break; + + case JSON_checker::ST: + case JSON_checker::SQ: + if( this->isStringState( prevJc.state() ) ) { + this->token.value.append( 1, ch ); // this is not regarded as a state change. + } else { + this->token.value.clear(); + } + break; + case JSON_checker::ES: + case JSON_checker::U1: + case JSON_checker::U2: + case JSON_checker::U3: + case JSON_checker::U4: + this->token.value.append( 1, ch ); // this is not regarded as a state change. + break; + + case JSON_checker::MI: + case JSON_checker::ZE: + case JSON_checker::IN: + case JSON_checker::FR: + if( this->isNumericState( prevJc.state() ) ) { + this->token.value.append( 1, ch ); // this is not regarded as a state change. + } else { + this->token.value.clear(); + this->token.value.append( 1, ch ); + } + break; + case JSON_checker::E1: + case JSON_checker::E2: + case JSON_checker::E3: + this->token.value.append( 1, ch ); // this is not regarded as a state change. + break; + + case JSON_checker::RX: + if( this->isRegexState( prevJc.state() ) ) { + this->token.value.append( 1, ch ); // this is not regarded as a state change. + } else { + this->token.value.clear(); + this->token.value.append( 1, ch ); + } + break; + case JSON_checker::RE: + this->token.value.append( 1, ch ); // this is not regarded as a state change. + break; + case JSON_checker::RF: + // got regex pattern + this->token.type = JSON_reader::Token::T_RXPATTERN; + this->reader->gotValue( this->token ); + this->token.value.clear(); + break; + + default: + this->token.value.clear(); + break; + } +} + +void JSON_reader_driver::modePushed( const JSON_checker& jc, const wchar_t ch, const JSON_checker_state& prevJc ) +{ + this->stateChanged( jc, ch, prevJc ); + switch( jc.mode() ) + { + case JSON_checker::MODE_ARRAY: + this->reader->enterArray(); + break; + case JSON_checker::MODE_KEY: + this->reader->enterObject(); + break; + } +} + +void JSON_reader_driver::modePopped( const JSON_checker& jc, const wchar_t ch, const JSON_checker_state& prevJc ) +{ + this->stateChanged( jc, ch, prevJc ); + switch( prevJc.mode() ) + { + case JSON_checker::MODE_ARRAY: + this->reader->exitArray(); + break; + case JSON_checker::MODE_KEY: + /* empty object */ + case JSON_checker::MODE_OBJECT: + this->reader->exitObject(); + break; + } +} + +void JSON_reader_driver::modeChanged( const JSON_checker& jc, const wchar_t ch, const JSON_checker_state& prevJc ) +{ + this->stateChanged( jc, ch, prevJc ); + switch( prevJc.mode() ) + { + case JSON_checker::MODE_KEY: + // got object key, next is value + // notification has been sent to JSON_checker by this->stateChanged(). + break; + case JSON_checker::MODE_OBJECT: + // got object value and comma, next is another pair. + // notification has been sent to JSON_checker by this->stateChanged(). + break; + } +} + +bool JSON_reader_driver::isNumericState( const JSON_checker::State state ) +{ + return state == JSON_checker::MI || state == JSON_checker::ZE || state == JSON_checker::IN || state == JSON_checker::FR + || state == JSON_checker::E1 || state == JSON_checker::E2 || state == JSON_checker::E3; +} + +bool JSON_reader_driver::isStringState( const JSON_checker::State state ) +{ + return state == JSON_checker::ST || state == JSON_checker::SQ || state == JSON_checker::ES + || state == JSON_checker::U1 || state == JSON_checker::U2 || state == JSON_checker::U3 || state == JSON_checker::U4; +} + +bool JSON_reader_driver::isRegexState( const JSON_checker::State state ) +{ + return state == JSON_checker::RX || state == JSON_checker::RE; +} Index: sakura_core/view/colors/CColorML_Url.cpp =================================================================== --- sakura_core/view/colors/CColorML_Url.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_Url.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,36 @@ +#include "StdAfx.h" +#include "charset/charcode.h" // WCODE::IsAZ() +#include "parse/CWordParse.h" // IsURL() +#include "view/colors/EColorIndexType.h" +#include "CColorML_Url.h" + +const CLogicInt CColorML_Url::IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + const CStringRef& line = pLine->GetStringRefWithEOL(); + if( nPosWithinLine < 0 || line.GetLength() <= nPosWithinLine ) { + return 0; // インデックスが不正。 + } + if( ! WCODE::IsAZ( line.At( nPosWithinLine ) ) ) { + // URLの開始はプロトコル名。http(ttpと tpも認めている)や ftpなので英字以外は不許可。 + // メールアドレスのローカル部の場合は他に各種記号が使えるんだけど対応は保留。 + return 0; + } else if( WCODE::IsAZ( line.At( nPosWithinLine - 1 ) ) ) { + // 一つ前の文字も英字。ffftp://example.com の ftp:// から + // 後ろだけをみれば有効な URLなのだが、こういうのは認めない。 + return 0; + } + + // URL判定開始。 + int urlLength = 0; + if( IsURL( line.GetPtr() + nPosWithinLine, line.GetLength() - nPosWithinLine, &urlLength ) ) { + *outColor = COLORIDX_URL; + return urlLength; + } + return 0; +} + +const CLogicInt CColorML_Url::IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + // IsStartOfKeyword()で適切な長さを返しているので常に 0でいい。 + return 0; +} Index: sakura_core/view/colors/CColorML_Quote.h =================================================================== --- sakura_core/view/colors/CColorML_Quote.h (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_Quote.h (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,37 @@ +#pragma once +#include "View/colors/EColorIndexType.h" +#include "view/colors/ColorMLStrategy.h" + + +class CColorML_Quote +: public CColorML_Base +{ +public: + CColorML_Quote( const EColorIndexType color, const wchar_t delim, const wchar_t escape = L'\0' ) + : color( color ), delim( delim ), escape( escape ) + {} + + virtual const CLogicInt IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + virtual const CLogicInt IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ); + +private: + const EColorIndexType color; + const wchar_t delim; + const wchar_t escape; +}; + + +class CColorML_WQuote +: public CColorML_Quote +{ +public: + CColorML_WQuote( const wchar_t escape = L'\\' ); +}; + + +class CColorML_SQuote +: public CColorML_Quote +{ +public: + CColorML_SQuote( const wchar_t escape = L'\\' ); +}; Index: sakura_core/view/colors/CColorML_Numeric.cpp =================================================================== --- sakura_core/view/colors/CColorML_Numeric.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_Numeric.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,573 @@ +#include "StdAfx.h" +#include "charset/charcode.h" +#include "view/colors/EColorIndexType.h" +#include "view/colors/CColorML_Numeric.h" +static int IsNumber( const CStringRef& cStr, int offset );/* 数値ならその長さを返す */ //@@@ 2001.02.17 by MIK + + +const CLogicInt CColorML_Numeric::IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + const CStringRef& line = pLine->GetStringRefWithEOL(); + if( 0 < nPosWithinLine && IS_KEYWORD_CHAR( line.At( nPosWithinLine - 1 ) ) ) { + return 0; // 単語の境界ではなかった。 + } + const int len = IsNumber( line, nPosWithinLine ); + *outColor = COLORIDX_DIGIT; + return len; +} + +const CLogicInt CColorML_Numeric::IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + // IsStartOfKeyword()で適切な長さを返しているので常に 0で良い。 + return 0; +} + + +// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // +// 実装補助 // +// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // + +//@@@ 2001.11.07 Start by MIK +//#ifdef COMPILE_COLOR_DIGIT +/* + * 数値なら長さを返す。 + * 10進数の整数または小数。16進数(正数)。 + * 文字列 数値(色分け) + * --------------------- + * 123 123 + * 0123 0123 + * 0xfedc 0xfedc + * -123 -123 + * &H9a &H9a (ただしソース中の#ifを有効にしたとき) + * -0x89a 0x89a + * 0.5 0.5 + * 0.56.1 0.56 , 1 (ただしソース中の#ifを有効にしたら"0.56.1"になる) + * .5 5 (ただしソース中の#ifを有効にしたら".5"になる) + * -.5 5 (ただしソース中の#ifを有効にしたら"-.5"になる) + * 123. 123 + * 0x567.8 0x567 , 8 + */ +/* + * 半角数値 + * 1, 1.2, 1.2.3, .1, 0xabc, 1L, 1F, 1.2f, 0x1L, 0x2F, -.1, -1, 1e2, 1.2e+3, 1.2e-3, -1e0 + * 10進数, 16進数, LF接尾語, 浮動小数点数, 負符号 + * IPアドレスのドット連結(本当は数値じゃないんだよね) + */ +static int IsNumber(const CStringRef& cStr,/*const wchar_t *buf,*/ int offset/*, int length*/) +{ + register const wchar_t* p; + register const wchar_t* q; + register int i = 0; + register int d = 0; + register int f = 0; + + p = cStr.GetPtr() + offset; + q = cStr.GetPtr() + cStr.GetLength(); + + if( *p == L'0' ) /* 10進数,Cの16進数 */ + { + p++; i++; + if( ( p < q ) && ( *p == L'x' ) ) /* Cの16進数 */ + { + p++; i++; + while( p < q ) + { + if( ( *p >= L'0' && *p <= L'9' ) + || ( *p >= L'A' && *p <= L'F' ) + || ( *p >= L'a' && *p <= L'f' ) ) + { + p++; i++; + } + else + { + break; + } + } + /* "0x" なら "0" だけが数値 */ + if( i == 2 ) return 1; + + /* 接尾語 */ + if( p < q ) + { + if( *p == L'L' || *p == L'l' || *p == L'F' || *p == L'f' ) + { + p++; i++; + } + } + return i; + } + else if( *p >= L'0' && *p <= L'9' ) + { + p++; i++; + while( p < q ) + { + if( *p < L'0' || *p > L'9' ) + { + if( *p == L'.' ) + { + if( f == 1 ) break; /* 指数部に入っている */ + d++; + if( d > 1 ) + { + if( *(p - 1) == L'.' ) break; /* "." が連続なら中断 */ + } + } + else if( *p == L'E' || *p == L'e' ) + { + if( f == 1 ) break; /* 指数部に入っている */ + if( p + 2 < q ) + { + if( ( *(p + 1) == L'+' || *(p + 1) == L'-' ) + && ( *(p + 2) >= L'0' && *(p + 2) <= L'9' ) ) + { + p++; i++; + p++; i++; + f = 1; + } + else if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) + { + p++; i++; + f = 1; + } + else + { + break; + } + } + else if( p + 1 < q ) + { + if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) + { + p++; i++; + f = 1; + } + else + { + break; + } + } + else + { + break; + } + } + else + { + break; + } + } + p++; i++; + } + if( *(p - 1) == L'.' ) return i - 1; /* 最後が "." なら含めない */ + /* 接尾語 */ + if( p < q ) + { + if( (( d == 0 ) && ( *p == L'L' || *p == L'l' )) + || *p == L'F' || *p == L'f' ) + { + p++; i++; + } + } + return i; + } + else if( *p == L'.' ) + { + while( p < q ) + { + if( *p < L'0' || *p > L'9' ) + { + if( *p == L'.' ) + { + if( f == 1 ) break; /* 指数部に入っている */ + d++; + if( d > 1 ) + { + if( *(p - 1) == L'.' ) break; /* "." が連続なら中断 */ + } + } + else if( *p == L'E' || *p == L'e' ) + { + if( f == 1 ) break; /* 指数部に入っている */ + if( p + 2 < q ) + { + if( ( *(p + 1) == L'+' || *(p + 1) == L'-' ) + && ( *(p + 2) >= L'0' && *(p + 2) <= L'9' ) ) + { + p++; i++; + p++; i++; + f = 1; + } + else if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) + { + p++; i++; + f = 1; + } + else + { + break; + } + } + else if( p + 1 < q ) + { + if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) + { + p++; i++; + f = 1; + } + else + { + break; + } + } + else + { + break; + } + } + else + { + break; + } + } + p++; i++; + } + if( *(p - 1) == L'.' ) return i - 1; /* 最後が "." なら含めない */ + /* 接尾語 */ + if( p < q ) + { + if( *p == L'F' || *p == L'f' ) + { + p++; i++; + } + } + return i; + } + else if( *p == L'E' || *p == L'e' ) + { + p++; i++; + while( p < q ) + { + if( *p < L'0' || *p > L'9' ) + { + if( ( *p == L'+' || *p == L'-' ) && ( *(p - 1) == L'E' || *(p - 1) == L'e' ) ) + { + if( p + 1 < q ) + { + if( *(p + 1) < L'0' || *(p + 1) > L'9' ) + { + /* "0E+", "0E-" */ + break; + } + } + else + { + /* "0E-", "0E+" */ + break; + } + } + else + { + break; + } + } + p++; i++; + } + if( i == 2 ) return 1; /* "0E", 0e" なら "0" が数値 */ + /* 接尾語 */ + if( p < q ) + { + if( (( d == 0 ) && ( *p == L'L' || *p == L'l' )) + || *p == L'F' || *p == L'f' ) + { + p++; i++; + } + } + return i; + } + else + { + /* "0" だけが数値 */ + /*if( *p == L'.' ) return i - 1;*/ /* 最後が "." なら含めない */ + if( p < q ) + { + if( (( d == 0 ) && ( *p == L'L' || *p == L'l' )) + || *p == L'F' || *p == L'f' ) + { + p++; i++; + } + } + return i; + } + } + + else if( *p >= L'1' && *p <= L'9' ) /* 10進数 */ + { + p++; i++; + while( p < q ) + { + if( *p < L'0' || *p > L'9' ) + { + if( *p == L'.' ) + { + if( f == 1 ) break; /* 指数部に入っている */ + d++; + if( d > 1 ) + { + if( *(p - 1) == L'.' ) break; /* "." が連続なら中断 */ + } + } + else if( *p == L'E' || *p == L'e' ) + { + if( f == 1 ) break; /* 指数部に入っている */ + if( p + 2 < q ) + { + if( ( *(p + 1) == L'+' || *(p + 1) == L'-' ) + && ( *(p + 2) >= L'0' && *(p + 2) <= L'9' ) ) + { + p++; i++; + p++; i++; + f = 1; + } + else if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) + { + p++; i++; + f = 1; + } + else + { + break; + } + } + else if( p + 1 < q ) + { + if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) + { + p++; i++; + f = 1; + } + else + { + break; + } + } + else + { + break; + } + } + else + { + break; + } + } + p++; i++; + } + if( *(p - 1) == L'.' ) return i - 1; /* 最後が "." なら含めない */ + /* 接尾語 */ + if( p < q ) + { + if( (( d == 0 ) && ( *p == L'L' || *p == L'l' )) + || *p == L'F' || *p == L'f' ) + { + p++; i++; + } + } + return i; + } + + else if( *p == L'-' ) /* マイナス */ + { + p++; i++; + while( p < q ) + { + if( *p < L'0' || *p > L'9' ) + { + if( *p == L'.' ) + { + if( f == 1 ) break; /* 指数部に入っている */ + d++; + if( d > 1 ) + { + if( *(p - 1) == L'.' ) break; /* "." が連続なら中断 */ + } + } + else if( *p == L'E' || *p == L'e' ) + { + if( f == 1 ) break; /* 指数部に入っている */ + if( p + 2 < q ) + { + if( ( *(p + 1) == L'+' || *(p + 1) == L'-' ) + && ( *(p + 2) >= L'0' && *(p + 2) <= L'9' ) ) + { + p++; i++; + p++; i++; + f = 1; + } + else if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) + { + p++; i++; + f = 1; + } + else + { + break; + } + } + else if( p + 1 < q ) + { + if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) + { + p++; i++; + f = 1; + } + else + { + break; + } + } + else + { + break; + } + } + else + { + break; + } + } + p++; i++; + } + /* "-", "-." だけなら数値でない */ + //@@@ 2001.11.09 start MIK + //if( i <= 2 ) return 0; + //if( *(p - 1) == L'.' ) return i - 1; /* 最後が "." なら含めない */ + if( i == 1 ) return 0; + if( *(p - 1) == L'.' ) + { + i--; + if( i == 1 ) return 0; + return i; + } //@@@ 2001.11.09 end MIK + /* 接尾語 */ + if( p < q ) + { + if( (( d == 0 ) && ( *p == L'L' || *p == L'l' )) + || *p == L'F' || *p == L'f' ) + { + p++; i++; + } + } + return i; + } + + else if( *p == L'.' ) /* 小数点 */ + { + d++; + p++; i++; + while( p < q ) + { + if( *p < L'0' || *p > L'9' ) + { + if( *p == L'.' ) + { + if( f == 1 ) break; /* 指数部に入っている */ + d++; + if( d > 1 ) + { + if( *(p - 1) == L'.' ) break; /* "." が連続なら中断 */ + } + } + else if( *p == L'E' || *p == L'e' ) + { + if( f == 1 ) break; /* 指数部に入っている */ + if( p + 2 < q ) + { + if( ( *(p + 1) == L'+' || *(p + 1) == L'-' ) + && ( *(p + 2) >= L'0' && *(p + 2) <= L'9' ) ) + { + p++; i++; + p++; i++; + f = 1; + } + else if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) + { + p++; i++; + f = 1; + } + else + { + break; + } + } + else if( p + 1 < q ) + { + if( *(p + 1) >= L'0' && *(p + 1) <= L'9' ) + { + p++; i++; + f = 1; + } + else + { + break; + } + } + else + { + break; + } + } + else + { + break; + } + } + p++; i++; + } + /* "." だけなら数値でない */ + if( i == 1 ) return 0; + if( *(p - 1) == L'.' ) return i - 1; /* 最後が "." なら含めない */ + /* 接尾語 */ + if( p < q ) + { + if( *p == L'F' || *p == L'f' ) + { + p++; i++; + } + } + return i; + } + +#if 0 + else if( *p == L'&' ) /* VBの16進数 */ + { + p++; i++; + if( ( p < q ) && ( *p == L'H' ) ) + { + p++; i++; + while( p < q ) + { + if( ( *p >= L'0' && *p <= L'9' ) + || ( *p >= L'A' && *p <= L'F' ) + || ( *p >= L'a' && *p <= L'f' ) ) + { + p++; i++; + } + else + { + break; + } + } + /* "&H" だけなら数値でない */ + if( i == 2 ) i = 0; + return i; + } + + /* "&" だけなら数値でない */ + return 0; + } +#endif + + /* 数値ではない */ + return 0; +} +//@@@ 2001.11.07 End by MIK Index: sakura_core/view/colors/CColorML_Comment.cpp =================================================================== --- sakura_core/view/colors/CColorML_Comment.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/CColorML_Comment.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,71 @@ +#include "StdAfx.h" +#include "util/string_ex.h" +#include "view/colors/EColorIndexType.h" +#include "view/colors/CColorML_Comment.h" + + +const CLogicInt CColorML_LineComment::IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + if( this->commentChar.empty() ) { + return 0; + } + if( 0 <= this->column && this->column != nPosWithinLine ) { + return 0; + } + const CStringRef& line = pLine->GetStringRefWithEOL(); + if( static_cast( line.GetLength() - nPosWithinLine ) < this->commentChar.size() ) { + return 0; + } + if( 0 != wmemicmp_ascii( line.GetPtr() + nPosWithinLine, this->commentChar.c_str(), this->commentChar.size() ) ) { + return 0; + } + *outColor = COLORIDX_COMMENT; + return line.GetLength() - nPosWithinLine; +} + +const CLogicInt CColorML_LineComment::IsInsideKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + // IsStartOfKeyword()で適切な長さを返しているので常に 0 でよい。 + return 0; +} + + +const CLogicInt CColorML_BlockComment::IsStartOfKeyword( const CEditDoc* const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType* const outColor, void** userData ) +{ + if( this->commentBegin.empty() || this->commentEnd.empty() ) { + return 0; // 無効なコメント開始(終了)文字。 + } + const CStringRef& line = pLine->GetStringRefWithEOL(); + if( static_cast( line.GetLength() - nPosWithinLine ) < this->commentBegin.size() ) { + return 0; // 残りの文字数がコメント開始文字の長さに満たない。 + } + if( 0 != wmemicmp_ascii( line.GetPtr() + nPosWithinLine, this->commentBegin.c_str(), this->commentBegin.size() ) ) { + return 0; // コメント開始文字ではなかった。 + } + *reinterpret_cast( userData ) = -1; // IsInsideKeyword()へ、コメント終了位置が未定だというメッセージ。 + *outColor = COLORIDX_COMMENT; + return this->commentBegin.size(); +} + +const CLogicInt CColorML_BlockComment::IsInsideKeyword( const CEditDoc *const pDoc, const CLogicInt nLineNumber, const CDocLine* const pLine, const CLogicInt nPosWithinLine, EColorIndexType *const outColor, void **userData ) +{ + if( *reinterpret_cast( userData ) == nPosWithinLine ) { + return 0; // nPosWithinLine-1 でコメント部分終了。 + } + *outColor = COLORIDX_COMMENT; + const CStringRef& line = pLine->GetStringRefWithEOL(); + if( static_cast( line.GetLength() - nPosWithinLine ) < this->commentEnd.size() ) { + return -1; // 残りの文字数がコメント終了文字の長さに満たない。次の行へ続く。 + } + const wchar_t* const pCommentEndMarker = wcsistr( line.GetPtr() + nPosWithinLine, this->commentEnd.c_str() ); + if( ! pCommentEndMarker ) { + // コメント終了文字がこの行に見つからない。次の行へ続く。 + *reinterpret_cast( userData ) = -1; + return -1; + } else { + // 行内に終了文字を見つけた。次の IsInsideKeyword()で 0を返させて終了。 + const CLogicInt posCommentEnd = pCommentEndMarker - line.GetPtr() + this->commentEnd.size(); + *reinterpret_cast( userData ) = posCommentEnd; // コメント終了の次の文字の位置 + return posCommentEnd - nPosWithinLine; // コメント部分の長さ + } +} Index: sakura_core/view/colors/JSON_checker.cpp =================================================================== --- sakura_core/view/colors/JSON_checker.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 0) +++ sakura_core/view/colors/JSON_checker.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -0,0 +1,304 @@ +#include "StdAfx.h" +#include "view/colors/JSON_checker.h" + +/* JSON_checker.c */ + +/* 2007-08-24 */ + +/* +Copyright (c) 2005 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + + +enum JSON_checker::CharClass +{ + C_REJECT = -1, + C_SPACE, /* space */ + C_WHITE, /* other whitespace */ + C_LCURB, /* { */ + C_RCURB, /* } */ + C_LSQRB, /* [ */ + C_RSQRB, /* ] */ + C_COLON, /* : */ + C_COMMA, /* , */ + C_WQUOTE, /* " */ + C_SQUOTE, /* ' */ + C_BACKS, /* \ */ + C_SLASH, /* / */ + C_STAR, /* * */ + C_PLUS, /* + */ + C_MINUS, /* - */ + C_POINT, /* . */ + C_ZERO , /* 0 */ + C_DIGIT, /* 123456789 */ + C_LOW_A, /* a */ + C_LOW_B, /* b */ + C_LOW_C, /* c */ + C_LOW_D, /* d */ + C_LOW_E, /* e */ + C_LOW_F, /* f */ + C_L_GIM, /* gim */ + C_LOW_L, /* l */ + C_LOW_N, /* n */ + C_LOW_R, /* r */ + C_LOW_S, /* s */ + C_LOW_T, /* t */ + C_LOW_U, /* u */ + C_ABCDF, /* ABCDF */ + C_E, /* E */ + C_IDENT, /* identifier */ + C_ETC, /* everything else */ + NR_CLASSES +}; + +bool JSON_checker::nextChar( const wchar_t nextChar ) +{ + const CharClass nextCharClass = this->classify( nextChar ); + if( nextCharClass == C_REJECT ) { + this->error = E_INVALID_CHAR; + return false; + } + return this->moveNext( nextCharClass ); +} + +const wchar_t* JSON_checker::errorMessage( const Error error ) const +{ + const wchar_t* szErrorMessages[NR_ERRORS]; + for( int i = 0; i != NR_ERRORS; ++i ) { + szErrorMessages[i] = L"other error."; + } + szErrorMessages[E_NO_ERROR] = L"not an error."; + szErrorMessages[E_INVALID_CHAR] = L"invalid char."; + szErrorMessages[E_UNEXPECTED_OBJECT_END] = L"unexpected object end."; + szErrorMessages[E_UNEXPECTED_ARRAY_END] = L"unexpected array end."; + szErrorMessages[E_UNEXPECTED_QUOTE] = L"unexpected quote."; + szErrorMessages[E_UNEXPECTED_COMMA] = L"unexpected comma."; + szErrorMessages[E_UNEXPECTED_COLON] = L"unexpected colon."; + szErrorMessages[E_UNEXPECTED_CHAR] = L"unexpected char."; + szErrorMessages[E_TRANSITION_ERROR] = L"transition error."; + + if( error < 0 || NR_ERRORS <= error ) { + return szErrorMessages[E_NO_ERROR]; + } + return szErrorMessages[error]; +} + +JSON_checker::CharClass JSON_checker::classify( const wchar_t ch ) const +{ + static const CharClass ascii_class[128] = { + /* + This array maps the 128 ASCII characters into character classes. + The remaining Unicode characters should be mapped to C_ETC. + Non-whitespace control characters are errors. + */ + C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, + C_REJECT, C_WHITE , C_WHITE , C_REJECT, C_REJECT, C_WHITE , C_REJECT, C_REJECT, + C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, + C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, C_REJECT, + + C_SPACE , C_ETC , C_WQUOTE, C_ETC , C_IDENT , C_ETC , C_ETC , C_SQUOTE, + C_ETC , C_ETC , C_STAR , C_PLUS , C_COMMA , C_MINUS , C_POINT , C_SLASH, + C_ZERO , C_DIGIT , C_DIGIT , C_DIGIT , C_DIGIT , C_DIGIT , C_DIGIT , C_DIGIT, + C_DIGIT , C_DIGIT , C_COLON , C_ETC , C_ETC , C_ETC , C_ETC , C_ETC, + + C_ETC , C_ABCDF , C_ABCDF , C_ABCDF , C_ABCDF , C_E , C_ABCDF , C_IDENT, + C_IDENT , C_IDENT , C_IDENT , C_IDENT , C_IDENT , C_IDENT , C_IDENT , C_IDENT, + C_IDENT , C_IDENT , C_IDENT , C_IDENT , C_IDENT , C_IDENT , C_IDENT , C_IDENT, + C_IDENT , C_IDENT , C_IDENT , C_LSQRB , C_BACKS , C_RSQRB , C_ETC , C_IDENT, + + C_ETC , C_LOW_A , C_LOW_B , C_LOW_C , C_LOW_D , C_LOW_E , C_LOW_F , C_L_GIM, + C_IDENT , C_L_GIM , C_IDENT , C_IDENT , C_LOW_L , C_L_GIM , C_LOW_N , C_IDENT, + C_IDENT , C_IDENT , C_LOW_R , C_LOW_S , C_LOW_T , C_LOW_U , C_IDENT , C_IDENT, + C_IDENT , C_IDENT , C_IDENT , C_LCURB , C_ETC , C_RCURB , C_ETC , C_ETC + }; + if( 0 <= ch && ch < _countof(ascii_class) ) { + return ascii_class[ch]; + } + return C_ETC; +} + +bool JSON_checker::moveNext( const CharClass nextCharClass ) +{ + static State state_transition_table[NR_STATES][NR_CLASSES] = { +/* + The state transition table takes the current state and the current symbol, + and returns either a new state or an action. An action is represented as a + negative number. A JSON text is accepted if at the end of the text the + state is OK and if the mode is MODE_DONE. + + white 1-9 gim ABCDF id etc + space | { } [ ] : , " ' \ / * + - . 0 | a b c d e f | l n r s t u | E | |*/ +/* start GO*/ {GO,GO,_6,__,_5,__,__,__,__,__,__,_A,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__}, +/* ok OK*/ {OK,OK,__,_8,__,_7,__,_3,__,__,__,_A,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__}, +/* object OB*/ {OB,OB,__,_9,__,__,__,__,ST,SQ,__,_A,__,__,__,__,__,__,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,__}, +/* key KE*/ {KE,KE,__,__,__,__,__,__,ST,SQ,__,_A,__,__,__,__,__,__,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,__}, +/* colon CO*/ {CO,CO,__,__,__,__,_2,__,__,__,__,_A,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__}, +/* value VA*/ {VA,VA,_6,__,_5,__,__,__,ST,SQ,__,_B,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,__,N1,__,__,T1,__,__,__,__,__}, +/* array AR*/ {AR,AR,_6,__,_5,_7,__,__,ST,SQ,__,_B,__,__,MI,__,ZE,IN,__,__,__,__,__,F1,__,__,N1,__,__,T1,__,__,__,__,__}, +/* "string" ST*/ {ST,__,ST,ST,ST,ST,ST,ST,_4,ST,_E,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST}, +/* 'string' SQ*/ {SQ,__,SQ,SQ,SQ,SQ,SQ,SQ,SQ,_4,_E,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ,SQ}, +/* ident ID*/ {__,__,__,__,__,__,_2,__,__,__,__,__,__,__,__,__,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,ID,__}, +/* escape ES*/ {__,__,__,__,__,__,__,__,_D,_D,_D,_D,__,__,__,__,__,__,__,_D,__,__,__,_D,__,__,_D,_D,__,_D,U1,__,__,__,__}, +/* \u U1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,U2,U2,U2,U2,U2,U2,U2,U2,__,__,__,__,__,__,__,U2,U2,__,__}, +/* \uX U2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,U3,U3,U3,U3,U3,U3,U3,U3,__,__,__,__,__,__,__,U3,U3,__,__}, +/* \uXX U3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,U4,U4,U4,U4,U4,U4,U4,U4,__,__,__,__,__,__,__,U4,U4,__,__}, +/* \uXXX U4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,_D,_D,_D,_D,_D,_D,_D,_D,__,__,__,__,__,__,__,_D,_D,__,__}, +/* minus MI*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,ZE,IN,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__}, +/* zero ZE*/ {OK,OK,__,_8,__,_7,__,_3,__,__,__,__,__,__,__,FR,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__}, +/* integer IN*/ {OK,OK,__,_8,__,_7,__,_3,__,__,__,__,__,__,__,FR,IN,IN,__,__,__,__,E1,__,__,__,__,__,__,__,__,__,E1,__,__}, +/* fraction FR*/ {OK,OK,__,_8,__,_7,__,_3,__,__,__,__,__,__,__,__,FR,FR,__,__,__,__,E1,__,__,__,__,__,__,__,__,__,E1,__,__}, +/* e E1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,E2,E2,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__}, +/* ex E2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__}, +/* exp E3*/ {OK,OK,__,_8,__,_7,__,_3,__,__,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__}, +/* t T1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T2,__,__,__,__,__,__,__}, +/* tr T2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T3,__,__,__,__}, +/* tru T3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__,__}, +/* f F1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__}, +/* fa F2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F3,__,__,__,__,__,__,__,__,__}, +/* fal F3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F4,__,__,__,__,__,__}, +/* fals F4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__,__}, +/* n N1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N2,__,__,__,__}, +/* nu N2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N3,__,__,__,__,__,__,__,__,__}, +/* nul N3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__}, +/* comment? CM*/ {__,__,__,__,__,__,__,__,__,__,__,C1,C2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__}, +/* // C1*/ {C1,_C,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1,C1}, +/* / * C2*/ {C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C3,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2}, +/* / ** C3*/ {C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,_C,C3,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2}, +/* regex? R0*/ {RX,__,RX,RX,RX,RX,RX,RX,RX,RX,RE,C1,C2,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX}, +/* regex RX*/ {RX,__,RX,RX,RX,RX,RX,RX,RX,RX,RE,RF,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX}, +/* rx esc RE*/ {RX,__,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX,RX}, +/* rx flag RF*/ {OK,OK,__,_8,__,_7,__,_3,__,__,__,_A,__,__,__,__,__,__,__,__,__,__,__,__,RF,__,__,__,__,__,__,__,__,__,__}, + }; + + const State nextState = state_transition_table[this->currentState][static_cast(nextCharClass)]; + if( 0 <= nextState ) { + /* Change the state. */ + this->currentState = nextState; + } else { + /* Or perform one of the actions. */ + switch( nextState ) { + case _E: /* enter escape sequence */ + this->returnState = this->currentState; + this->currentState = ES; + break; + case _D: /* exit escape sequence */ + this->currentState = this->returnState; + this->returnState = __; + break; + case _C: /* exit comment */ + if( this->returnState <= __ || state_transition_table[this->returnState][C_SPACE] <= __ ) { + this->error = E_TRANSITION_ERROR; + return false; + } + this->currentState = state_transition_table[this->returnState][C_SPACE]; + this->returnState = __; + break; + case _B: /* regex or comment */ + this->returnState = this->currentState; + this->currentState = R0; + break; + case _A: /* enter comment */ + this->returnState = this->currentState; + this->currentState = CM; + break; + case _9: /* empty } */ + if( this->modeStack.back() != MODE_KEY ) { + this->error = E_UNEXPECTED_OBJECT_END; + return false; + } + this->modeStack.pop_back(); + this->currentState = OK; + break; + case _8: /* } */ + if( this->modeStack.back() != MODE_OBJECT ) { + this->error = E_UNEXPECTED_OBJECT_END; + return false; + } + this->modeStack.pop_back(); + this->currentState = OK; + break; + case _7: /* ] */ + if( this->modeStack.back() != MODE_ARRAY ) { + this->error = E_UNEXPECTED_ARRAY_END; + return false; + } + this->modeStack.pop_back(); + this->currentState = OK; + break; + case _6: /* { */ + this->modeStack.push_back( MODE_KEY ); + this->currentState = OB; + break; + case _5: /* [ */ + this->modeStack.push_back( MODE_ARRAY ); + this->currentState = AR; + break; + case _4: /* " or ' */ + switch( this->modeStack.back() ) { + case MODE_KEY: + this->currentState = CO; + break; + case MODE_ARRAY: + case MODE_OBJECT: + this->currentState = OK; + break; + default: + this->error = E_UNEXPECTED_QUOTE; + return false; + } + break; + case _3: /* , */ + switch( this->modeStack.back() ) { + case MODE_OBJECT: + /* + A comma causes a flip from object mode to key mode. + */ + this->modeStack.back() = MODE_KEY; + this->currentState = KE; + break; + case MODE_ARRAY: + this->currentState = VA; + break; + default: + this->error = E_UNEXPECTED_COMMA; + return false; + } + break; + case _2: /* : */ + /* + A colon causes a flip from key mode to object mode. + */ + if( this->modeStack.back() != MODE_KEY ) { + this->error = E_UNEXPECTED_COLON; + return false; + } + this->modeStack.back() = MODE_OBJECT; + this->currentState = VA; + break; + default: /* Bad action. */ + this->error = E_UNEXPECTED_CHAR; + return false; + } + } + return true; +} Index: sakura_core/view/CEditView.cpp =================================================================== --- sakura_core/view/CEditView.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CEditView.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -55,7 +55,8 @@ #include "util/module.h" #include "util/tchar_template.h" #include "util/os.h" //WM_MOUSEWHEEL,IMR_RECONVERTSTRING,WM_XBUTTON*,IMR_CONFIRMRECONVERTSTRING -#include "view/colors/CColorStrategy.h" +#include "view/colors/CColorML_Found.h" +#include "view/colors/ColorMLStrategy.h" CEditView* g_m_pcEditView; @@ -140,7 +141,12 @@ , m_cViewSelect(this) , m_AT_ImmSetReconvertString(NULL) , m_bActivateByMouse( FALSE ) // 2007.10.02 nasukoji +, colorStrategySearchWord( &(pcEditWnd->GetDocument()) ) { + this->lastSearchInfo.pos = CLogicPoint( -1, -1 ); + std::auto_ptr pFound( new CColorML_Found( this ) ); + this->pColorML_Found = static_cast( pFound.get() ); + this->colorStrategySearchWord.PushStrategyUnit( pFound ); } @@ -1075,79 +1081,45 @@ URLの強調表示OFFのチェックはこの関数内で行うように変更 */ bool CEditView::IsCurrentPositionURL( - const CLayoutPoint& ptCaretPos, //!< [in] カーソル位置 - CLogicRange* pUrlRange, //!< [out] URL範囲。ロジック単位。 - std::wstring* pwstrURL //!< [out] URL文字列受け取り先。NULLを指定した場合はURL文字列を受け取らない。 + const CLayoutPoint& ptCaretInLayout, //!< [in] カーソル位置 + CLogicRange* const outRange, //!< [out] URL範囲。ロジック単位。 + std::wstring* const outString //!< [out] URL文字列受け取り先。NULLを指定した場合はURL文字列を受け取らない。 ) { MY_RUNNINGTIMER( cRunningTimer, "CEditView::IsCurrentPositionURL" ); - // URLを強調表示するかどうかチェックする // 2009.05.27 ryoji - bool bDispUrl = CTypeSupport(this,COLORIDX_URL).IsDisp(); - bool bUseRegexKeyword = false; - STypeConfig *TypeDataPtr = &(m_pcEditDoc->m_cDocType.GetDocumentAttribute()); - if( TypeDataPtr->m_bUseRegexKeyword ){ - for( int i = 0; i < MAX_REGEX_KEYWORD; i++ ){ - if( TypeDataPtr->m_RegexKeywordArr[i].m_szKeyword[0] == L'\0' ) - break; - if( TypeDataPtr->m_RegexKeywordArr[i].m_nColorIndex == COLORIDX_URL ){ - bUseRegexKeyword = true; // URL色指定の正規表現キーワードがある - break; - } - } - } - if( !bDispUrl && !bUseRegexKeyword ){ - return false; // URL強調表示しないのでURLではない - } - - // 正規表現キーワード(URL色指定)行検索開始処理 // 2009.05.27 ryoji - if( bUseRegexKeyword ){ - m_cRegexKeyword->RegexKeyLineStart(); - } - /* カーソル位置変換 レイアウト位置(行頭からの表示桁位置、折り返しあり行位置) → 物理位置(行頭からのバイト数、折り返し無し行位置) */ - CLogicPoint ptXY; - m_pcEditDoc->m_cLayoutMgr.LayoutToLogic( - ptCaretPos, - &ptXY - ); - CLogicInt nLineLen; - const wchar_t* pLine = m_pcEditDoc->m_cDocLineMgr.GetLine(ptXY.GetY2())->GetDocLineStrWithEOL(&nLineLen); //2007.10.09 kobake レイアウト・ロジック混在バグ修正 + CLogicPoint ptCaret; + m_pcEditDoc->m_cLayoutMgr.LayoutToLogic( ptCaretInLayout, &ptCaret ); + const CLogicInt lineNum = ptCaret.GetY2(); + const CLogicInt posWithinLine = ptCaret.GetX2(); + if( m_pcEditDoc->m_cDocLineMgr.GetLineCount() <= lineNum ) { + return false; // 対象行が無効。 + } + const CDocLine* const pLine = m_pcEditDoc->m_cDocLineMgr.GetLine( lineNum ); + const wchar_t* const szLine = pLine->GetPtr(); + const CLogicInt lineLen = pLine->GetLengthWithEOL(); + if( lineLen <= posWithinLine ) { + return false; // インデックスが無効。 + } - bool bMatch; - int nMatchColor; - int nUrlLen; - CLogicInt i = CLogicInt(__max(0, ptXY.GetX2() - _MAX_PATH)); // 2009.05.22 ryoji 200->_MAX_PATH - //nLineLen = CLogicInt(__min(nLineLen, ptXY.GetX2() + _MAX_PATH)); - while( i <= ptXY.GetX2() && i < nLineLen ){ - bMatch = ( bUseRegexKeyword - && m_cRegexKeyword->RegexIsKeyword( CStringRef(pLine, nLineLen), i, &nUrlLen, &nMatchColor ) - && nMatchColor == COLORIDX_URL ); - if( !bMatch ){ - bMatch = ( bDispUrl - && (i == 0 || !IS_KEYWORD_CHAR(pLine[i - 1])) // 2009.05.22 ryoji CColor_Url::BeginColor()と同条件に - && IsURL(&pLine[i], (Int)(nLineLen - i), &nUrlLen) ); /* 指定アドレスがURLの先頭ならばTRUEとその長さを返す */ + ColorMLStrategy::Result highlight; + this->m_pcEditDoc->HighlightInfo( lineNum, &highlight ); + const EColorIndexType colorAtCaretPos = highlight.colorInfo.at( posWithinLine ); + if( colorAtCaretPos == COLORIDX_URL ) { + ColorMLStrategy::Result::LineColorInfo::range_type url_range = highlight.colorInfo.range_including( posWithinLine ); + if( outString ) { + outString->assign( szLine + url_range.begin, szLine + url_range.end ); } - if( bMatch ){ - if( i <= ptXY.GetX2() && ptXY.GetX2() < i + CLogicInt(nUrlLen) ){ - /* URLを返す場合 */ - if( pwstrURL ){ - pwstrURL->assign(&pLine[i],nUrlLen); - } - pUrlRange->SetLine(ptXY.GetY2()); - pUrlRange->SetXs(i, i+CLogicInt(nUrlLen)); - return true; - }else{ - i += CLogicInt(nUrlLen); - continue; - } + if( outRange ) { + *outRange = CLogicRange( CLogicPoint( url_range.begin, lineNum ), CLogicPoint( url_range.end, lineNum ) ); } - ++i; + return true; } return false; } @@ -1475,11 +1447,23 @@ GetTextArea().SetTopYohaku( GetDllShareData().m_Common.m_sWindow.m_nRulerBottomSpace ); /* ルーラーとテキストの隙間 */ GetTextArea().SetAreaTop( GetTextArea().GetTopYohaku() ); /* 表示域の上端座標 */ + const STypeConfig& doctype = m_pcEditDoc->m_cDocType.GetDocumentAttribute(); + /* ルーラー表示 */ - if( m_pcEditDoc->m_cDocType.GetDocumentAttribute().m_ColorInfoArr[COLORIDX_RULER].m_bDisp ){ + if( doctype.m_ColorInfoArr[COLORIDX_RULER].m_bDisp ){ GetTextArea().SetAreaTop(GetTextArea().GetAreaTop() + GetDllShareData().m_Common.m_sWindow.m_nRulerHeight); /* ルーラー高さ */ } + // 検索文字列の色設定変更 + std::vector highlightColors; + highlightColors.reserve( COLORIDX_SEARCHTAIL - COLORIDX_SEARCH + 1 ); + for( int color = COLORIDX_SEARCH; color <= COLORIDX_SEARCHTAIL; ++color ) { + if( doctype.m_ColorInfoArr[color].m_bDisp ) { + highlightColors.push_back( static_cast( color ) ); + } + } + this->pColorML_Found->SetColors( highlightColors ); + // フォント更新 GetFontset().UpdateFont(); Index: sakura_core/view/CEditView_Mouse.cpp =================================================================== --- sakura_core/view/CEditView_Mouse.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CEditView_Mouse.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -5,7 +5,7 @@ #include "util/os.h" #include "parse/CWordParse.h" #include "COpeBlk.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" #include "CClipboard.h" #include "doc/CLayout.h" #include "config/system_constants.h" Index: sakura_core/view/CTextDrawer.cpp =================================================================== --- sakura_core/view/CTextDrawer.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/view/CTextDrawer.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -10,7 +10,7 @@ #include "types/CTypeSupport.h" #include "charset/charcode.h" #include "doc/CLayout.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" const CTextArea* CTextDrawer::GetTextArea() const @@ -22,7 +22,6 @@ EColorIndexType CTextDrawer::_GetColorIdx(EColorIndexType nColorIdx) const { -// if(bSearchStringMode)return COLORIDX_SEARCH; //検索ヒット色 if(CTypeSupport(m_pEditView,nColorIdx).IsDisp())return nColorIdx; //特殊色 return COLORIDX_TEXT; //通常色 } Index: sakura_core/CKeyWordSetMgr.cpp =================================================================== --- sakura_core/CKeyWordSetMgr.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/CKeyWordSetMgr.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -371,43 +371,48 @@ return; } -/* n番目のセットから指定キーワードをバイナリサーチ 無いときは-1を返す */ -int CKeyWordSetMgr::SearchKeyWord2( int nIdx, const wchar_t* pszKeyWord, int nKeyWordLen ) +/** iKwdSet番目のセットから指定キーワードをバイナリサーチ 無いときは-1を返す。 + + ハイフンで連結された語のように、非キーワード文字を含んだキーワードも見つけたい。 + 渡されたキーワードで始まるキーワードが登録されているのを見つけたが、 + さらに(非キーワード)文字が続いているために不一致となった場合は -2を返し、リトライのチャンスを与える。 +*/ +int CKeyWordSetMgr::SearchKeyWord2( const int iKwdSet, const wchar_t* const szTestword, const size_t testwordLength ) { - int pc, pr, pl, ret, wcase; - //sort - if(m_IsSorted[nIdx] == 0) SortKeyWord(nIdx); + if( m_IsSorted[iKwdSet] == 0 ) { + SortKeyWord( iKwdSet ); + } - pl = m_nStartIdx[nIdx]; - pr = m_nStartIdx[nIdx] + m_nKeyWordNumArr[nIdx] - 1; -// if( pr < 0 ) return -1; - if( nKeyWordLen > m_nKeyWordMaxLenArr[nIdx] ) return -1; - pc = (pr + 1 - pl) / 2 + pl; - wcase = m_bKEYWORDCASEArr[nIdx]; - while(pl <= pr) { - if( wcase ) { - ret = wcsncmp( pszKeyWord, m_szKeyWordArr[pc], nKeyWordLen ); - } else { - ret = wcsnicmp( pszKeyWord, m_szKeyWordArr[pc], nKeyWordLen ); - } + if( static_cast(m_nKeyWordMaxLenArr[iKwdSet]) < testwordLength ) { + return -1; // 字数オーバー。 + } + + int result = -1; // -1=見つからなかった。-2=与えられたキーワードの長さが足りないために見つからなかった。 + int (*const fcmp)(const wchar_t*, const wchar_t*, size_t) = m_bKEYWORDCASEArr[iKwdSet] ? wcsncmp : wcsnicmp; + int left = m_nStartIdx[iKwdSet]; + int right = m_nStartIdx[iKwdSet] + m_nKeyWordNumArr[iKwdSet] - 1; + int center = left + (right - left + 1) / 2; + while( left <= right ) { + const wchar_t* const szCenter = m_szKeyWordArr[center]; + int ret = fcmp( szTestword, szCenter, testwordLength ); if( ret == 0 ) { - if( (int)wcslen( m_szKeyWordArr[pc] ) > nKeyWordLen ) { - ret = -1; - } else { - return pc - m_nStartIdx[nIdx]; + const size_t centerLength = wcslen( szCenter ); + if( testwordLength == centerLength ) { + return center - m_nStartIdx[iKwdSet]; // N番目のキーワードが一致した。 + } else if( testwordLength < centerLength ) { + result = -2; // 長さが足りなくて不一致。 } + ret = testwordLength - centerLength; } - if( ret < 0 ) { - pr = pc - 1; + right = center - 1; } else { - pl = pc + 1; + left = center + 1; } - - pc = (pr + 1 - pl) / 2 + pl; + center = left + (right - left + 1) / 2; } - return -1; + return result; } //MIK END //MIK START 2000.12.01 START Index: sakura_core/CRegexKeyword.cpp =================================================================== --- sakura_core/CRegexKeyword.cpp (.../mirror/sakura-editor/sakura/trunk2) (リビジョン 43889) +++ sakura_core/CRegexKeyword.cpp (.../private/sakura-editor/shjs_style_regex_keyword) (リビジョン 45197) @@ -20,7 +20,7 @@ #include "stdafx.h" #include "CRegexKeyword.h" #include "CBregexp.h" -#include "view/colors/CColorStrategy.h" +#include "view/colors/EColorIndexType.h" #if 0 #include 属性に変更があったパス: . ___________________________________________________________________ 追加: svk:merge + 063d25e1-a40e-0410-9609-b70a13b3acad:/sakura/branches/unicode:1230 063d25e1-a40e-0410-9609-b70a13b3acad:/sakura/branches/unicode2:1433 063d25e1-a40e-0410-9609-b70a13b3acad:/sakura/trunk:1167 063d25e1-a40e-0410-9609-b70a13b3acad:/sakura/trunk2:1711