void EditMarkAll(HWND hwnd, int iMarkOccurrences, BOOL bMarkOccurrencesMatchCase, BOOL bMarkOccurrencesMatchWords,
//BLUEnLIVE
BOOL bMarkOccurrencesMarkVisibleOnly, BOOL bMarkOccurrencesDisplayMarkCount
//BLUEnLIVE
)
{
struct TextToFind ttf;
int iPos;
char *pszText;
int iTextLenDoc;
int iTextStartLine;
int iTextEndLine;
int iTextStartLineDoc;
int iTextEndLineDoc;
int iTextStart;
int iTextEnd;
int iSelStart;
int iSelEnd;
int iSelCount;
// extern으로 지정, Edit.c와 Notepad2.c에서 공유
iMatchesCount = 0;
ZeroMemory(&ttf,sizeof(ttf));
if (bMarkOccurrencesMarkVisibleOnly) {
iTextStartLine = (int)SendMessage(hwnd,SCI_GETFIRSTVISIBLELINE,0,0);
iTextStartLineDoc = (int)SendMessage(hwnd,SCI_DOCLINEFROMVISIBLE,iTextStartLine,0);
iTextStart = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,iTextStartLineDoc, 0);
iTextEndLine = iTextStartLine + (int)SendMessage(hwnd,SCI_LINESONSCREEN,0,0);
iTextEndLineDoc = (int)SendMessage(hwnd,SCI_DOCLINEFROMVISIBLE,iTextEndLine,0);
iTextEnd = (int)SendMessage(hwnd,SCI_GETLINEENDPOSITION,iTextEndLineDoc, 0);
ttf.chrg.cpMin = iTextStart;
ttf.chrg.cpMax = iTextEnd;
} else {
ttf.chrg.cpMin = 0;
ttf.chrg.cpMax = iTextLenDoc;
}
ttf.lpstrText = pszText;
// set style
SendMessage(hwnd, SCI_INDICSETALPHA, 1, 100);
SendMessage(hwnd, SCI_INDICSETFORE, 1, 0xff << ((iMarkOccurrences - 1) << 3));
SendMessage(hwnd, SCI_INDICSETSTYLE, 1, INDIC_ROUNDBOX);
//iMatchesCount = 0;
while ((iPos = (int)SendMessage(hwnd, SCI_FINDTEXT,
(bMarkOccurrencesMatchCase ? SCFIND_MATCHCASE : 0) | (bMarkOccurrencesMatchWords ? SCFIND_WHOLEWORD : 0),
(LPARAM)&ttf)) != -1
&& ++iMatchesCount < 2000)
{
// mark this match
SendMessage(hwnd, SCI_INDICATORFILLRANGE, iPos, iSelCount);
ttf.chrg.cpMin = ttf.chrgText.cpMin + iSelCount;
if (ttf.chrg.cpMin >= ttf.chrg.cpMax)
break;
}
//display 하지 않는 경우를 대비하여 0으로 초기화
iMatchesCount = 0;
//일치 갯수 전시: BLUEnLIVE
if (bMarkOccurrencesDisplayMarkCount) {
ZeroMemory(&ttf,sizeof(ttf));
ttf.chrg.cpMin = 0;
ttf.chrg.cpMax = iTextLenDoc;
ttf.lpstrText = pszText;
//iMatchesCount = 0;
while ((iPos = (int)SendMessage(hwnd, SCI_FINDTEXT,
(bMarkOccurrencesMatchCase ? SCFIND_MATCHCASE : 0) | (bMarkOccurrencesMatchWords ? SCFIND_WHOLEWORD : 0),
(LPARAM)&ttf)) != -1
/* && ++iMatchesCount < 2000 */)
{
++iMatchesCount;
ttf.chrg.cpMin = ttf.chrgText.cpMin + iSelCount;
if (ttf.chrg.cpMin >= ttf.chrg.cpMax)
break;
}
UpdateStatusbar();
}
LocalFree(pszText);
return;
}
다음 아이디어 참 좋은거 같습니다.
함수 서명을 바꾸는 것을 절대 안되고...
이름처럼 전역 변수로 bMarkOccurenceScreen으로 선언하면 좋을 거 같습니다.
if (bMarkOccurrencesMarkVisibleOnly) {
iTextStartLine = (int)SendMessage(hwnd,SCI_GETFIRSTVISIBLELINE,0,0);
iTextStartLineDoc = (int)SendMessage(hwnd,SCI_DOCLINEFROMVISIBLE,iTextStartLine,0);
iTextStart = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,iTextStartLineDoc, 0);
iTextEndLine = iTextStartLine + (int)SendMessage(hwnd,SCI_LINESONSCREEN,0,0);
iTextEndLineDoc = (int)SendMessage(hwnd,SCI_DOCLINEFROMVISIBLE,iTextEndLine,0);
iTextEnd = (int)SendMessage(hwnd,SCI_GETLINEENDPOSITION,iTextEndLineDoc, 0);
ttf.chrg.cpMin = iTextStart;
ttf.chrg.cpMax = iTextEnd;
} else {
ttf.chrg.cpMin = 0;
ttf.chrg.cpMax = iTextLenDoc;
}
그리고 제시해 주신 코드에서 //일치 갯수 전시: BLUEnLIVE
if (bMarkOccurrencesDisplayMarkCount) {
ZeroMemory(&ttf,sizeof(ttf));
ttf.chrg.cpMin = 0;
ttf.chrg.cpMax = iTextLenDoc;
ttf.lpstrText = pszText;
일치 갯수를 알기 위해 범위를 문서로 전체로 하는 건,
대용량 파일임이 대상임을 고려할 때 심각한 랙의 원인이 됩니다.
while (++iMatchesCount < 2000)
void EditMarkAll(HWND hwnd, int iMarkOccurrences, BOOL bMarkOccurrencesMatchCase, BOOL bMarkOccurrencesMatchWords)
{
struct TextToFind ttf;
int iPos;
char *pszText;
int iTextLenDoc;
int iTextStartLine;
int iTextEndLine;
int iTextStartLineDoc;
int iTextEndLineDoc;
int iTextStart;
int iTextEnd;
int iSelStart;
int iSelEnd;
int iSelCount;
// extern으로 지정, Edit.c와 Notepad2.c에서 공유
if (bMarkOccurrencesMarkVisibleOnly) {
iTextStartLine = (int)SendMessage(hwnd,SCI_GETFIRSTVISIBLELINE,0,0);
iTextStartLineDoc = (int)SendMessage(hwnd,SCI_DOCLINEFROMVISIBLE,iTextStartLine,0);
iTextStart = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,iTextStartLineDoc, 0);
iTextEndLine = iTextStartLine + (int)SendMessage(hwnd,SCI_LINESONSCREEN,0,0);
iTextEndLineDoc = (int)SendMessage(hwnd,SCI_DOCLINEFROMVISIBLE,iTextEndLine,0);
iTextEnd = (int)SendMessage(hwnd,SCI_GETLINEENDPOSITION,iTextEndLineDoc, 0);
ttf.chrg.cpMin = iTextStart;
ttf.chrg.cpMax = iTextEnd;
} else {
//ttf.chrg.cpMin = 0; //ZeroMemory 했으니 불필요
ttf.chrg.cpMax = iTextLenDoc;
}
ttf.lpstrText = pszText;
// set style
SendMessage(hwnd, SCI_INDICSETALPHA, 1, 100);
SendMessage(hwnd, SCI_INDICSETFORE, 1, 0xff << ((iMarkOccurrences - 1) << 3));
SendMessage(hwnd, SCI_INDICSETSTYLE, 1, INDIC_ROUNDBOX);
//iMatchesCount = 0;
while ((iPos = (int)SendMessage(hwnd, SCI_FINDTEXT,
(bMarkOccurrencesMatchCase ? SCFIND_MATCHCASE : 0) | (bMarkOccurrencesMatchWords ? SCFIND_WHOLEWORD : 0),
(LPARAM)&ttf)) != -1
&& ++iMatchesCount <= 2000)
{
// mark this match
SendMessage(hwnd, SCI_INDICATORFILLRANGE, iPos, iSelCount);
ttf.chrg.cpMin = ttf.chrgText.cpMin + iSelCount;
if (ttf.chrg.cpMin >= ttf.chrg.cpMax)
break;
}
// 전체에 대해 표시할 때만 개수 전시
if (bMarkOccurrencesMarkVisibleOnly) {
iMatchesCount = 0;
} else {
UpdateStatusbar();
}
LocalFree(pszText);
return;
}
//iMatchesCount = 0;
while ((iPos = (int)SendMessage(hwnd, SCI_FINDTEXT,
(bMarkOccurrencesMatchCase ? SCFIND_MATCHCASE : 0) | (bMarkOccurrencesMatchWords ? SCFIND_WHOLEWORD : 0),
(LPARAM)&ttf)) != -1
&& ++iMatchesCount <= 2000)
{
// mark this match
SendMessage(hwnd, SCI_INDICATORFILLRANGE, iPos, iSelCount);
ttf.chrg.cpMin = ttf.chrgText.cpMin + iSelCount;
if (ttf.chrg.cpMin >= ttf.chrg.cpMax)
break;
}
// 전체에 대해 표시할 때만 개수 전시
if (bMarkOccurrencesMarkVisibleOnly) {
iMatchesCount = 0;
} else {
UpdateStatusbar();
}
LocalFree(pszText);
return;
}
while ((iPos = (int)SendMessage(hwnd<span style="color: #660;" class
// 전체에 대해 표시할 때만 개수 전시
if (bMarkOccurrencesMarkVisibleOnly) {
iMatchesCount = 0;
} else {
UpdateStatusbar();
}
LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
LPNMHDR pnmh = (LPNMHDR)lParam;
struct SCNotification* scn = (struct SCNotification*)lParam;
switch(pnmh->idFrom)
{
case IDC_EDIT:
switch(pnmh->code)
{
case SCN_UPDATEUI:
// mark occurrences of text currently selected
//if (scn->updated & SC_UPDATE_SELECTION) // BLUEnLIVE
if (scn->updated & (SC_UPDATE_SELECTION | SC_UPDATE_V_SCROLL | SC_UPDATE_H_SCROLL))
EditMarkAll(hwndEdit, iMarkOccurrences, bMarkOccurrencesMatchCase, bMarkOccurrencesMatchWords);
if (scn->updated & ~(SC_UPDATE_V_SCROLL | SC_UPDATE_H_SCROLL)) {
UpdateToolbar();
UpdateStatusbar();
/////////////////////
// (중간 생략)
/////////////////////
case SCN_ZOOM:
UpdateLineNumberWidth();
EditMarkAll(hwndEdit, iMarkOccurrences, bMarkOccurrencesMatchCase, bMarkOccurrencesMatchWords); //BLUEnLIVE
break;
/////////////////////
// (이하 생략)
/////////////////////
SCI_FINDTEXT(int searchFlags, Sci_TextToFind *ttf)
이 메시지는 문서 안에서 텍스트를 찾는다. 현재 위치를 사용하거나 이동시키지 않는다. searchFlags 인자는 검색 유형을 제어한다. 여기에는 정규 표현식 검색을 포함한다.
역방향으로 검색해서 앞의 검색 문자열을 찾을 수 있다. 검색 범위에서 시작 위치보다 먼저 끝을 지정하면 된다.
Sci_TextToFind 구조는 Scintilla.h에 정의되어 있다; chrg.cpMin와 chrg.cpMax를 문서에서 검색할 범위로 설정한다. SCFIND_REGEXP가 이 플래그에 포함되지 않으면, chrg.cpMax를 chrg.cpMin보다 작게 설정하여 거꾸로 검색할 수 있다. SCFIND_REGEXP가 포함되면, 검색은 (chrg.cpMax가 chrg.cpMin보다 작더라도) 언제나 앞으로 수행된다.
Sci_TextToFind의 lpstrText 멤버를 그 검색 패턴을 보유한 0 종료 텍스트 문자열을 가리키도록 설정한다. 언어에서 Sci_TextToFind를 사용하기가 어렵다면, 대신에 SCI_SEARCHINTARGET을 사용해 보자.
검색에 실패하면 반환 값은 -1이다. 성공하면 발견된 텍스트의 시작 위치를 돌려준다. Sci_TextToFind의 멤버인 chrgText.cpMin과 chrgText.cpMax는 발견된 텍스트이 시작 위치와 끝 위치로 채워진다.
다음도 참조: SCI_SEARCHINTARGET
Sci_TextToFind
이 구조는 Win32 구조 FINDTEXTEX와 정확하게 같은 모양을 갖도록 정의된다. 예전 코드는 신틸라를 RichEdit 콘트롤로 취급했었다.
struct Sci_TextToFind {
struct Sci_CharacterRange chrg; // 검색할 범위;
char *lpstrText; // 검색 패턴 (0 종료)
struct Sci_CharacterRange chrgText; // 부합한 텍스트의 위치로 반환됨
};
Sci_TextRange 그리고 Sci_CharacterRange
신틸라를 RichEdit으로 취급하는 이전 코드가 작동하도록 이 구조는 정확하게 Win32 TEXTRANGE 그리고 CHARRANGE와 똑같은 모양으로 정의된다.
앞으로 Scintilla가 모든 플랫폼에서 64-비트로 빌드될 때 Sci_PositionCR 유형은 64-비트가 되도록 재정의될 것이다.
1. chrg.cpMax과 chrg.cpMin을 비교하는 것은 SCFIND_REGEXP를 반드시 참조해야 한다.
2. Sci_PositionCR은 현재 32비트로 고정이다.