From 049f0e6d8facd7bd7c25fb02618eca7d72615f94 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Fri, 27 Oct 2017 16:28:07 +0200 Subject: [PATCH 01/11] + first refactoring for find/replace (RegExpr) operations --- scintilla/Scintilla.vcxproj | 1 + scintilla/Scintilla.vcxproj.filters | 3 + scintilla/deelx/DeelxRegexSearch.cxx | 4 +- scintilla/deelx/deelx.h | 4673 ++++++++++++++++++++++++++ src/Dialogs.c | 10 +- src/Dlapi.c | 8 +- src/Edit.c | 394 ++- src/Helpers.c | 30 +- src/Helpers.h | 32 +- src/Notepad3.c | 126 +- src/Print.cpp | 8 +- src/Styles.c | 32 +- 12 files changed, 5025 insertions(+), 296 deletions(-) create mode 100644 scintilla/deelx/deelx.h diff --git a/scintilla/Scintilla.vcxproj b/scintilla/Scintilla.vcxproj index d81bf071e..0bb68de23 100644 --- a/scintilla/Scintilla.vcxproj +++ b/scintilla/Scintilla.vcxproj @@ -270,6 +270,7 @@ + diff --git a/scintilla/Scintilla.vcxproj.filters b/scintilla/Scintilla.vcxproj.filters index 1cc3bd5a1..1c2cf0698 100644 --- a/scintilla/Scintilla.vcxproj.filters +++ b/scintilla/Scintilla.vcxproj.filters @@ -443,6 +443,9 @@ include + + deelx + diff --git a/scintilla/deelx/DeelxRegexSearch.cxx b/scintilla/deelx/DeelxRegexSearch.cxx index 4c7900763..5b5f8bd20 100644 --- a/scintilla/deelx/DeelxRegexSearch.cxx +++ b/scintilla/deelx/DeelxRegexSearch.cxx @@ -43,6 +43,7 @@ #include "CharClassify.h" #include "Document.h" // --------------------------------------------------------------- +//#include "deelx.h" // DEELX - Regular Expression Engine (v1.2) #include "deelx64.h" // DEELX - Regular Expression Engine (v1.3) // --------------------------------------------------------------- @@ -129,7 +130,7 @@ long DeelxRegexSearch::FindText(Document* doc,int minPos,int maxPos,const char * bool caseSensitive,bool word,bool wordStart,int searchFlags,int *length) { const bool right2left = false; // always left-to-right match mode - const bool extended = false; // ignore spaces and use '#' as line-comment) + const bool extended = false; // ignore spaces and use '#' as line-comment) // Range endpoints should not be inside DBCS characters, but just in case, move them. minPos = doc->MovePositionOutsideChar(minPos,1,false); @@ -140,6 +141,7 @@ long DeelxRegexSearch::FindText(Document* doc,int minPos,int maxPos,const char * int compileFlags = deelx::NO_FLAG; compileFlags |= (deelx::MULTILINE | deelx::GLOBAL); // the .(dot) does not match line-breaks //compileFlags |= (deelx::SINGLELINE | deelx::MULTILINE | deelx::GLOBAL); // the .(dot) also matches line-breaks + compileFlags |= (extended) ? deelx::EXTENDED : deelx::NO_FLAG; compileFlags |= (!caseSensitive) ? deelx::IGNORECASE : deelx::NO_FLAG; compileFlags |= (right2left) ? deelx::RIGHTTOLEFT : deelx::NO_FLAG; diff --git a/scintilla/deelx/deelx.h b/scintilla/deelx/deelx.h new file mode 100644 index 000000000..03d40e26a --- /dev/null +++ b/scintilla/deelx/deelx.h @@ -0,0 +1,4673 @@ +// deelx.h +// +// DEELX Regular Expression Engine (v1.2) +// +// Copyright 2006 ~ 2012 (c) RegExLab.com +// All Rights Reserved. +// +// http://www.regexlab.com/deelx/ +// +// Author: Ê·ÊÙΰ (sswater shi) +// sswater@gmail.com +// +// $Revision: 864 $ +// + +#ifndef __DEELX_REGEXP__H__ +#define __DEELX_REGEXP__H__ + +#include +#include +#include +#include +#include + +namespace deelx { + +// integer type for pointer arithmetic & casts (64-bit aware) +typedef int index_t; + + +extern "C" { + typedef int (*POSIX_FUNC)(int); + int isblank(int c); +} + +// +// Data Reference +// +template class CBufferRefT +{ +public: + CBufferRefT(const ELT * pcsz, int length); + CBufferRefT(const ELT * pcsz); + +public: + int nCompare (const ELT * pcsz) const; + int nCompareNoCase(const ELT * pcsz) const; + int Compare (const ELT * pcsz) const; + int CompareNoCase(const ELT * pcsz) const; + int Compare (const CBufferRefT &) const; + int CompareNoCase(const CBufferRefT &) const; + + ELT At (int nIndex, ELT def = 0) const; + ELT operator [] (int nIndex) const; + + const ELT * GetBuffer() const; + int GetSize() const; + +public: + virtual ~CBufferRefT(); + +// Content +protected: + ELT * m_pBuffer; + int m_nSize; +}; + +// +// Implemenation +// +template CBufferRefT :: CBufferRefT(const ELT * pcsz, int length) +{ + m_pBuffer = (ELT *)pcsz; + m_nSize = length; +} + +template CBufferRefT :: CBufferRefT(const ELT * pcsz) +{ + m_pBuffer = (ELT *)pcsz; + m_nSize = 0; + + if(pcsz != 0) while(m_pBuffer[m_nSize] != 0) m_nSize ++; +} + +template int CBufferRefT :: nCompare(const ELT * pcsz) const +{ + for(int i=0; i int CBufferRefT :: nCompareNoCase(const ELT * pcsz) const +{ + for(int i=0; i inline int CBufferRefT :: Compare(const ELT * pcsz) const +{ + return nCompare(pcsz) ? 1 : (int)pcsz[m_nSize]; +} + +template inline int CBufferRefT :: CompareNoCase(const ELT * pcsz) const +{ + return nCompareNoCase(pcsz) ? 1 : (int)pcsz[m_nSize]; +} + +template inline int CBufferRefT :: Compare(const CBufferRefT & cref) const +{ + return m_nSize == cref.m_nSize ? nCompare(cref.GetBuffer()) : 1; +} + +template inline int CBufferRefT :: CompareNoCase(const CBufferRefT & cref) const +{ + return m_nSize == cref.m_nSize ? nCompareNoCase(cref.GetBuffer()) : 1; +} + +template inline ELT CBufferRefT :: At(int nIndex, ELT def) const +{ + return nIndex >= m_nSize ? def : m_pBuffer[nIndex]; +} + +template inline ELT CBufferRefT :: operator [] (int nIndex) const +{ + return nIndex >= m_nSize ? 0 : m_pBuffer[nIndex]; +} + +template const ELT * CBufferRefT :: GetBuffer() const +{ + static const ELT _def[] = {0}; return m_pBuffer ? m_pBuffer : _def; +} + +template inline int CBufferRefT :: GetSize() const +{ + return m_nSize; +} + +template CBufferRefT :: ~CBufferRefT() +{ +} + +// +// Data Buffer +// +template class CBufferT : public CBufferRefT +{ +public: + CBufferT(const ELT * pcsz, int length); + CBufferT(const ELT * pcsz); + CBufferT(); + +public: + ELT & operator [] (int nIndex); + const ELT & operator [] (int nIndex) const; + void Append(const ELT * pcsz, int length, int eol = 0); + void Append(ELT el, int eol = 0); + +public: + void Push(ELT el); + void Push(const CBufferRefT & buf); + int Pop (ELT & el); + int Pop (CBufferT & buf); + int Peek(ELT & el) const; + +public: + const ELT * GetBuffer() const; + ELT * GetBuffer(); + ELT * Detach(); + void Release(); + void Prepare(int index, int fill = 0); + void Restore(int size); + + ELT * PrepareInsert(int nPos, int nSize) + { + int nOldSize = CBufferRefT::m_nSize; + Restore(nPos > CBufferRefT::m_nSize ? nPos : CBufferRefT::m_nSize + nSize); + + if( nPos < nOldSize ) + { + ELT * from = CBufferRefT::m_pBuffer + nPos, * to = CBufferRefT::m_pBuffer + nPos + nSize; + memmove(to, from, sizeof(ELT) * (nOldSize - nPos)); + } + + return CBufferRefT::m_pBuffer + nPos; + } + + void Insert(int nIndex, const ELT & rT) + { + Insert(nIndex, &rT, 1); + } + + void Insert(int nIndex, const ELT * pT, int nSize) + { + memcpy(PrepareInsert(nIndex, nSize), pT, sizeof(ELT) * nSize); + } + + void Remove(int nIndex) + { + Remove(nIndex, 1); + } + + void Remove(int nIndex, int nSize) + { + if( nIndex < CBufferRefT :: m_nSize ) + { + if( nIndex + nSize >= CBufferRefT :: m_nSize ) + { + Restore(nIndex); + } + else + { + memmove(CBufferRefT :: m_pBuffer + nIndex, CBufferRefT :: m_pBuffer + nIndex + nSize, sizeof(ELT) * (CBufferRefT :: m_nSize - nIndex - nSize)); + Restore(CBufferRefT :: m_nSize - nSize); + } + } + } + + void SetMaxLength(int nSize) + { + if( nSize > m_nMaxLength ) + { + if( m_nMaxLength < 8 ) + m_nMaxLength = 8; + + if( nSize > m_nMaxLength ) + m_nMaxLength *= 2; + + if( nSize > m_nMaxLength ) + { + m_nMaxLength = nSize + 11; + m_nMaxLength -= m_nMaxLength & 0x07; + } + + CBufferRefT :: m_pBuffer = (ELT *) realloc(CBufferRefT :: m_pBuffer, sizeof(ELT) * m_nMaxLength); + } + } + +public: + virtual ~CBufferT(); + +// Content +protected: + int m_nMaxLength; +}; + +// +// Implemenation +// +template CBufferT :: CBufferT(const ELT * pcsz, int length) : CBufferRefT (0, length) +{ + m_nMaxLength = CBufferRefT :: m_nSize + 1; + + CBufferRefT :: m_pBuffer = (ELT *) malloc(sizeof(ELT) * m_nMaxLength); + memcpy(CBufferRefT::m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT :: m_nSize); + CBufferRefT::m_pBuffer[CBufferRefT :: m_nSize] = 0; +} + +template CBufferT :: CBufferT(const ELT * pcsz) : CBufferRefT (pcsz) +{ + m_nMaxLength = CBufferRefT :: m_nSize + 1; + + CBufferRefT :: m_pBuffer = (ELT *) malloc(sizeof(ELT) * m_nMaxLength); + memcpy(CBufferRefT::m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT :: m_nSize); + CBufferRefT::m_pBuffer[CBufferRefT :: m_nSize] = 0; +} + +template CBufferT :: CBufferT() : CBufferRefT (0, 0) +{ + m_nMaxLength = 0; + CBufferRefT::m_pBuffer = 0; +} + +template inline ELT & CBufferT :: operator [] (int nIndex) +{ + return CBufferRefT::m_pBuffer[nIndex]; +} + +template inline const ELT & CBufferT :: operator [] (int nIndex) const +{ + return CBufferRefT::m_pBuffer[nIndex]; +} + +template void CBufferT :: Append(const ELT * pcsz, int length, int eol) +{ + int nNewLength = m_nMaxLength; + + // Check length + if(nNewLength < 8) + nNewLength = 8; + + if(CBufferRefT :: m_nSize + length + eol > nNewLength) + nNewLength *= 2; + + if(CBufferRefT :: m_nSize + length + eol > nNewLength) + { + nNewLength = CBufferRefT :: m_nSize + length + eol + 11; + nNewLength -= nNewLength % 8; + } + + // Realloc + if(nNewLength > m_nMaxLength) + { + CBufferRefT :: m_pBuffer = (ELT *) realloc(CBufferRefT::m_pBuffer, sizeof(ELT) * nNewLength); + m_nMaxLength = nNewLength; + } + + // Append + memcpy(CBufferRefT::m_pBuffer + CBufferRefT :: m_nSize, pcsz, sizeof(ELT) * length); + CBufferRefT :: m_nSize += length; + + if(eol > 0) CBufferRefT::m_pBuffer[CBufferRefT :: m_nSize] = 0; +} + +template inline void CBufferT :: Append(ELT el, int eol) +{ + Append(&el, 1, eol); +} + +template void CBufferT :: Push(ELT el) +{ + // Realloc + if(CBufferRefT :: m_nSize >= m_nMaxLength) + { + int nNewLength = m_nMaxLength * 2; + if( nNewLength < 8 ) nNewLength = 8; + + CBufferRefT :: m_pBuffer = (ELT *) realloc(CBufferRefT::m_pBuffer, sizeof(ELT) * nNewLength); + m_nMaxLength = nNewLength; + } + + // Append + CBufferRefT::m_pBuffer[CBufferRefT :: m_nSize++] = el; +} + +template void CBufferT :: Push(const CBufferRefT & buf) +{ + for(int i=0; i inline int CBufferT :: Pop(ELT & el) +{ + if(CBufferRefT :: m_nSize > 0) + { + el = CBufferRefT::m_pBuffer[--CBufferRefT :: m_nSize]; + return 1; + } + else + { + return 0; + } +} + +template int CBufferT :: Pop (CBufferT & buf) +{ + int size, res = 1; + res = res && Pop(*(ELT*)&size); + buf.Restore(size); + + for(int i=size-1; i>=0; i--) + { + res = res && Pop(buf[i]); + } + + return res; +} + +template inline int CBufferT :: Peek(ELT & el) const +{ + if(CBufferRefT :: m_nSize > 0) + { + el = CBufferRefT::m_pBuffer[CBufferRefT :: m_nSize - 1]; + return 1; + } + else + { + return 0; + } +} + +template const ELT * CBufferT :: GetBuffer() const +{ + static const ELT _def[] = {0}; return CBufferRefT::m_pBuffer ? CBufferRefT::m_pBuffer : _def; +} + +template ELT * CBufferT :: GetBuffer() +{ + static const ELT _def[] = {0}; return CBufferRefT::m_pBuffer ? CBufferRefT::m_pBuffer : (ELT *)_def; +} + +template ELT * CBufferT :: Detach() +{ + ELT * pBuffer = CBufferRefT::m_pBuffer; + + CBufferRefT :: m_pBuffer = 0; + CBufferRefT :: m_nSize = m_nMaxLength = 0; + + return pBuffer; +} + +template void CBufferT :: Release() +{ + ELT * pBuffer = Detach(); + + if(pBuffer != 0) free(pBuffer); +} + +template void CBufferT :: Prepare(int index, int fill) +{ + int nNewSize = index + 1; + + // Realloc + if(nNewSize > m_nMaxLength) + { + int nNewLength = m_nMaxLength; + + if( nNewLength < 8 ) + nNewLength = 8; + + if( nNewSize > nNewLength ) + nNewLength *= 2; + + if( nNewSize > nNewLength ) + { + nNewLength = nNewSize + 11; + nNewLength -= nNewLength % 8; + } + + CBufferRefT :: m_pBuffer = (ELT *) realloc(CBufferRefT::m_pBuffer, sizeof(ELT) * nNewLength); + m_nMaxLength = nNewLength; + } + + // size + if( CBufferRefT :: m_nSize < nNewSize ) + { + memset(CBufferRefT::m_pBuffer + CBufferRefT :: m_nSize, fill, sizeof(ELT) * (nNewSize - CBufferRefT :: m_nSize)); + CBufferRefT :: m_nSize = nNewSize; + } +} + +template inline void CBufferT :: Restore(int size) +{ + SetMaxLength(size); + CBufferRefT :: m_nSize = size; +} + +template CBufferT :: ~CBufferT() +{ + if(CBufferRefT::m_pBuffer != 0) free(CBufferRefT::m_pBuffer); +} + +template class CSortedBufferT : public CBufferT +{ +public: + CSortedBufferT(int reverse = 0); + CSortedBufferT(int(*)(const void *, const void *)); + +public: + void Add(const T & rT); + void Add(const T * pT, int nSize); + int Remove(const T & rT); + void RemoveAll(); + + void SortFreeze() { m_bSortFreezed = 1; } + void SortUnFreeze(); + +public: + int Find(const T & rT, int(* compare)(const void *, const void *) = 0) { return FindAs(*(T*)&rT, compare); } + int FindAs(const T & rT, int(*)(const void *, const void *) = 0); + int GetSize() const { return CBufferRefT::m_nSize; } + T & operator [] (int nIndex) { return CBufferT :: operator [] (nIndex); } + +protected: + int (* m_fncompare)(const void *, const void *); + static int compareT(const void *, const void *); + static int compareReverseT(const void *, const void *); + + int m_bSortFreezed; +}; + +template CSortedBufferT :: CSortedBufferT(int reverse) +{ + m_fncompare = reverse ? compareReverseT : compareT; + m_bSortFreezed = 0; +} + +template CSortedBufferT :: CSortedBufferT(int (* compare)(const void *, const void *)) +{ + m_fncompare = compare; + m_bSortFreezed = 0; +} + +template void CSortedBufferT :: Add(const T & rT) +{ + if(m_bSortFreezed != 0) + { + Append(rT); + return; + } + + int a = 0, b = CBufferRefT::m_nSize - 1, c = CBufferRefT::m_nSize / 2; + + while(a <= b) + { + int r = m_fncompare(&rT, &CBufferRefT::m_pBuffer[c]); + + if ( r < 0 ) b = c - 1; + else if( r > 0 ) a = c + 1; + else break; + + c = (a + b + 1) / 2; + } + + Insert(c, rT); +} + +template void CSortedBufferT :: Add(const T * pT, int nSize) +{ + Append(pT, nSize); + + if(m_bSortFreezed == 0) + { + qsort(CBufferRefT::m_pBuffer, CBufferRefT::m_nSize, sizeof(T), m_fncompare); + } +} + +template int CSortedBufferT :: FindAs(const T & rT, int(* compare)(const void *, const void *)) +{ + const T * pT = (const T *)bsearch(&rT, CBufferRefT::m_pBuffer, CBufferRefT::m_nSize, sizeof(T), compare == 0 ? m_fncompare : compare); + + if( pT != NULL ) + return pT - CBufferRefT::m_pBuffer; + else + return -1; +} + +template int CSortedBufferT :: Remove(const T & rT) +{ + int pos = Find(rT); + if( pos >= 0 ) CBufferT :: Remove(pos); + return pos; +} + +template inline void CSortedBufferT :: RemoveAll() +{ + CBufferT::Restore(0); +} + +template void CSortedBufferT :: SortUnFreeze() +{ + if(m_bSortFreezed != 0) + { + m_bSortFreezed = 0; + qsort(CBufferRefT::m_pBuffer, CBufferRefT::m_nSize, sizeof(T), m_fncompare); + } +} + +template int CSortedBufferT :: compareT(const void * elem1, const void * elem2) +{ + if( *(const T *)elem1 == *(const T *)elem2 ) + return 0; + else if( *(const T *)elem1 < *(const T *)elem2 ) + return -1; + else + return 1; +} + +template int CSortedBufferT :: compareReverseT(const void * elem1, const void * elem2) +{ + if( *(const T *)elem1 == *(const T *)elem2 ) + return 0; + else if( *(const T *)elem1 > *(const T *)elem2 ) + return -1; + else + return 1; +} + +// +// Context +// +class CContext +{ +public: + CBufferT m_stack; + CBufferT m_capturestack, m_captureindex; + +public: + int m_nCurrentPos; + int m_nBeginPos; + int m_nLastBeginPos; + int m_nParenZindex; + int m_nCursiveLimit; + + void * m_pMatchString; + int m_pMatchStringLength; +}; + +class CContextShot +{ +public: + CContextShot(CContext * pContext) + { + m_nCurrentPos = pContext->m_nCurrentPos; + nsize = pContext->m_stack.GetSize(); + ncsize = pContext->m_capturestack.GetSize(); + } + + void Restore(CContext * pContext) + { + pContext->m_stack.Restore(nsize); + pContext->m_capturestack.Restore(ncsize); + pContext->m_nCurrentPos = m_nCurrentPos; + } + +public: + int m_nCurrentPos; + int nsize ; + int ncsize; +}; + +// +// Interface +// +class ElxInterface +{ +public: + virtual int Match (CContext * pContext) const = 0; + virtual int MatchNext(CContext * pContext) const = 0; + +public: + virtual ~ElxInterface() {}; +}; + +// +// Alternative +// +template class CAlternativeElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CAlternativeElxT(); + +public: + CBufferT m_elxlist; +}; + +typedef CAlternativeElxT <0> CAlternativeElx; + +// +// Assert +// +template class CAssertElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CAssertElxT(ElxInterface * pelx, int byes = 1); + +public: + ElxInterface * m_pelx; + int m_byes; +}; + +typedef CAssertElxT <0> CAssertElx; + +// +// Back reference elx +// +template class CBackrefElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CBackrefElxT(int nnumber, int brightleft, int bignorecase); + +public: + int m_nnumber; + int m_brightleft; + int m_bignorecase; + + CBufferT m_szNamed; +}; + +// +// Implementation +// +template CBackrefElxT :: CBackrefElxT(int nnumber, int brightleft, int bignorecase) +{ + m_nnumber = nnumber; + m_brightleft = brightleft; + m_bignorecase = bignorecase; +} + +template int CBackrefElxT :: Match(CContext * pContext) const +{ + // check number, for named + if( m_nnumber < 0 || m_nnumber >= pContext->m_captureindex.GetSize() ) return 0; + + int index = pContext->m_captureindex[m_nnumber]; + if( index < 0 ) return 0; + + // check enclosed + int pos1 = pContext->m_capturestack[index + 1]; + int pos2 = pContext->m_capturestack[index + 2]; + + if( pos2 < 0 ) pos2 = pContext->m_nCurrentPos; + + // info + int lpos = pos1 < pos2 ? pos1 : pos2; + int rpos = pos1 < pos2 ? pos2 : pos1; + int slen = rpos - lpos; + + const CHART * pcsz = (const CHART *)pContext->m_pMatchString; + int npos = pContext->m_nCurrentPos; + int tlen = pContext->m_pMatchStringLength; + + // compare + int bsucc; + CBufferRefT refstr(pcsz + lpos, slen); + + if( m_brightleft ) + { + if(npos < slen) + return 0; + + if(m_bignorecase) + bsucc = ! refstr.nCompareNoCase(pcsz + (npos - slen)); + else + bsucc = ! refstr.nCompare (pcsz + (npos - slen)); + + if( bsucc ) + { + pContext->m_stack.Push(npos); + pContext->m_nCurrentPos -= slen; + } + } + else + { + if(npos + slen > tlen) + return 0; + + if(m_bignorecase) + bsucc = ! refstr.nCompareNoCase(pcsz + npos); + else + bsucc = ! refstr.nCompare (pcsz + npos); + + if( bsucc ) + { + pContext->m_stack.Push(npos); + pContext->m_nCurrentPos += slen; + } + } + + return bsucc; +} + +template int CBackrefElxT :: MatchNext(CContext * pContext) const +{ + int npos = 0; + + pContext->m_stack.Pop(npos); + pContext->m_nCurrentPos = npos; + + return 0; +} + +// RCHART +#ifndef RCHART + #define RCHART(ch) ((CHART)ch) +#endif + +// BOUNDARY_TYPE +enum BOUNDARY_TYPE +{ + BOUNDARY_FILE_BEGIN, // begin of whole text + BOUNDARY_FILE_END , // end of whole text + BOUNDARY_FILE_END_N, // end of whole text, or before newline at the end + BOUNDARY_LINE_BEGIN, // begin of line + BOUNDARY_LINE_END , // end of line + BOUNDARY_WORD_BEGIN, // begin of word + BOUNDARY_WORD_END , // end of word + BOUNDARY_WORD_EDGE +}; + +// +// Boundary Elx +// +template class CBoundaryElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CBoundaryElxT(int ntype, int byes = 1); + +protected: + static int IsWordChar(CHART ch); + +public: + int m_ntype; + int m_byes; +}; + +// +// Implementation +// +template CBoundaryElxT :: CBoundaryElxT(int ntype, int byes) +{ + m_ntype = ntype; + m_byes = byes; +} + +template int CBoundaryElxT :: Match(CContext * pContext) const +{ + const CHART * pcsz = (const CHART *)pContext->m_pMatchString; + int npos = pContext->m_nCurrentPos; + int tlen = pContext->m_pMatchStringLength; + + CHART chL = npos > 0 ? pcsz[npos - 1] : 0; + CHART chR = npos < tlen ? pcsz[npos ] : 0; + + int bsucc = 0; + + switch(m_ntype) + { + case BOUNDARY_FILE_BEGIN: + bsucc = (npos <= 0); + break; + + case BOUNDARY_FILE_END: + bsucc = (npos >= tlen); + break; + + case BOUNDARY_FILE_END_N: + bsucc = (npos >= tlen) || (pcsz[tlen-1] == RCHART('\n') && (npos == tlen-1 || (pcsz[tlen-2] == RCHART('\r') && npos == tlen-2))); + break; + + case BOUNDARY_LINE_BEGIN: + bsucc = (npos <= 0 ) || (chL == RCHART('\n')) || ((chL == RCHART('\r')) && (chR != RCHART('\n'))); + break; + + case BOUNDARY_LINE_END: + bsucc = (npos >= tlen) || (chR == RCHART('\r')) || ((chR == RCHART('\n')) && (chL != RCHART('\r'))); + break; + + case BOUNDARY_WORD_BEGIN: + bsucc = ! IsWordChar(chL) && IsWordChar(chR); + break; + + case BOUNDARY_WORD_END: + bsucc = IsWordChar(chL) && ! IsWordChar(chR); + break; + + case BOUNDARY_WORD_EDGE: + bsucc = IsWordChar(chL) ? ! IsWordChar(chR) : IsWordChar(chR); + break; + } + + return m_byes ? bsucc : ! bsucc; +} + +template int CBoundaryElxT :: MatchNext(CContext *) const +{ + return 0; +} + +template inline int CBoundaryElxT :: IsWordChar(CHART ch) +{ + return (ch >= RCHART('A') && ch <= RCHART('Z')) || (ch >= RCHART('a') && ch <= RCHART('z')) || (ch >= RCHART('0') && ch <= RCHART('9')) || (ch == RCHART('_')); +} + +// +// Bracket +// +template class CBracketElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CBracketElxT(int nnumber, int bright); + static int CheckCaptureIndex(int & index, CContext * pContext, int number); + +public: + int m_nnumber; + int m_bright; + + CBufferT m_szNamed; +}; + +template CBracketElxT :: CBracketElxT(int nnumber, int bright) +{ + m_nnumber = nnumber; + m_bright = bright; +} + +template inline int CBracketElxT :: CheckCaptureIndex(int & index, CContext * pContext, int number) +{ + if( index >= pContext->m_capturestack.GetSize() ) + index = pContext->m_capturestack.GetSize() - 4; + + while(index >= 0) + { + if(pContext->m_capturestack[index] == number) + { + return 1; + } + + index -= 4; + } + + + return 0; +} + +// +// capturestack[index+0] => Group number +// capturestack[index+1] => Capture start pos +// capturestack[index+2] => Capture end pos +// capturestack[index+3] => Capture enclose z-index, zindex<0 means inner group with same name +// +template int CBracketElxT :: Match(CContext * pContext) const +{ + // check, for named + if(m_nnumber < 0) return 0; + + if( ! m_bright ) + { + pContext->m_captureindex.Prepare(m_nnumber, -1); + int index = pContext->m_captureindex[m_nnumber]; + + // check + if(CheckCaptureIndex(index, pContext, m_nnumber) && pContext->m_capturestack[index+2] < 0) + { + pContext->m_capturestack[index+3] --; + return 1; + } + + // save + pContext->m_captureindex[m_nnumber] = pContext->m_capturestack.GetSize(); + + pContext->m_capturestack.Push(m_nnumber); + pContext->m_capturestack.Push(pContext->m_nCurrentPos); + pContext->m_capturestack.Push(-1); + pContext->m_capturestack.Push( 0); // z-index + } + else + { + // check + int index = pContext->m_captureindex[m_nnumber]; + + if(CheckCaptureIndex(index, pContext, m_nnumber)) + { + if(pContext->m_capturestack[index + 3] < 0) // check inner group with same name + { + pContext->m_capturestack[index + 3] ++; + return 1; + } + + // save + pContext->m_capturestack[index + 2] = pContext->m_nCurrentPos; + pContext->m_capturestack[index + 3] = pContext->m_nParenZindex ++; + } + } + + return 1; +} + +template int CBracketElxT :: MatchNext(CContext * pContext) const +{ + int index = pContext->m_captureindex[m_nnumber]; + if( ! CheckCaptureIndex(index, pContext, m_nnumber) ) + { + return 0; + } + + if( ! m_bright ) + { + if(pContext->m_capturestack[index + 3] < 0) + { + pContext->m_capturestack[index + 3] ++; + return 0; + } + + pContext->m_capturestack.Restore(pContext->m_capturestack.GetSize() - 4); + + // to find + CheckCaptureIndex(index, pContext, m_nnumber); + + // new index + pContext->m_captureindex[m_nnumber] = index; + } + else + { + if( pContext->m_capturestack[index + 2] >= 0 ) + { + pContext->m_capturestack[index + 2] = -1; + pContext->m_capturestack[index + 3] = 0; + } + else + { + pContext->m_capturestack[index + 3] --; + } + } + + return 0; +} + +// +// Deletage +// +template class CDelegateElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CDelegateElxT(int ndata = 0); + +public: + ElxInterface * m_pelx; + int m_ndata; // +0 : recursive to + // -3 : named recursive + + CBufferT m_szNamed; +}; + +template CDelegateElxT :: CDelegateElxT(int ndata) +{ + m_pelx = 0; + m_ndata = ndata; +} + +template int CDelegateElxT :: Match(CContext * pContext) const +{ + if(m_pelx != 0) + { + if(pContext->m_nCursiveLimit > 0) + { + pContext->m_nCursiveLimit --; + int result = m_pelx->Match(pContext); + pContext->m_nCursiveLimit ++; + return result; + } + else + return 0; + } + else + return 1; +} + +template int CDelegateElxT :: MatchNext(CContext * pContext) const +{ + if(m_pelx != 0) + return m_pelx->MatchNext(pContext); + else + return 0; +} + +// +// Empty +// +template class CEmptyElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CEmptyElxT(); +}; + +typedef CEmptyElxT <0> CEmptyElx; + +// +// Global +// +template class CGlobalElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CGlobalElxT(); +}; + +typedef CGlobalElxT <0> CGlobalElx; + +// +// Repeat +// +template class CRepeatElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CRepeatElxT(ElxInterface * pelx, int ntimes); + +protected: + int MatchFixed (CContext * pContext) const; + int MatchNextFixed(CContext * pContext) const; + int MatchForward (CContext * pContext) const + { + CContextShot shot(pContext); + + if( ! m_pelx->Match(pContext) ) + return 0; + + if(pContext->m_nCurrentPos != shot.m_nCurrentPos) + return 1; + + if( ! m_pelx->MatchNext(pContext) ) + return 0; + + if(pContext->m_nCurrentPos != shot.m_nCurrentPos) + return 1; + + shot.Restore(pContext); + return 0; + } + +public: + ElxInterface * m_pelx; + int m_nfixed; +}; + +typedef CRepeatElxT <0> CRepeatElx; + +// +// Greedy +// +template class CGreedyElxT : public CRepeatElxT +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CGreedyElxT(ElxInterface * pelx, int nmin = 0, int nmax = INT_MAX); + +protected: + int MatchVart (CContext * pContext) const; + int MatchNextVart(CContext * pContext) const; + +public: + int m_nvart; +}; + +typedef CGreedyElxT <0> CGreedyElx; + +// +// Independent +// +template class CIndependentElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CIndependentElxT(ElxInterface * pelx); + +public: + ElxInterface * m_pelx; +}; + +typedef CIndependentElxT <0> CIndependentElx; + +// +// List +// +template class CListElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CListElxT(int brightleft); + +public: + CBufferT m_elxlist; + int m_brightleft; +}; + +typedef CListElxT <0> CListElx; + +// +// Posix Elx +// +template class CPosixElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CPosixElxT(const char * posix, int brightleft); + +public: + POSIX_FUNC m_posixfun; + int m_brightleft; + int m_byes; +}; + +// +// Implementation +// +template CPosixElxT :: CPosixElxT(const char * posix, int brightleft) +{ + m_brightleft = brightleft; + + if(posix[1] == '^') + { + m_byes = 0; + posix += 2; + } + else + { + m_byes = 1; + posix += 1; + } + + if (!strncmp(posix, "alnum:", 6)) m_posixfun = ::isalnum ; + else if(!strncmp(posix, "alpha:", 6)) m_posixfun = ::isalpha ; + else if(!strncmp(posix, "ascii:", 6)) m_posixfun = ::isascii ; + else if(!strncmp(posix, "cntrl:", 6)) m_posixfun = ::iscntrl ; + else if(!strncmp(posix, "digit:", 6)) m_posixfun = ::isdigit ; + else if(!strncmp(posix, "graph:", 6)) m_posixfun = ::isgraph ; + else if(!strncmp(posix, "lower:", 6)) m_posixfun = ::islower ; + else if(!strncmp(posix, "print:", 6)) m_posixfun = ::isprint ; + else if(!strncmp(posix, "punct:", 6)) m_posixfun = ::ispunct ; + else if(!strncmp(posix, "space:", 6)) m_posixfun = ::isspace ; + else if(!strncmp(posix, "upper:", 6)) m_posixfun = ::isupper ; + else if(!strncmp(posix, "xdigit:",7)) m_posixfun = ::isxdigit; + else if(!strncmp(posix, "blank:", 6)) m_posixfun = isblank ; + else m_posixfun = 0 ; +} + +inline int isblank(int c) +{ + return c == 0x20 || c == '\t'; +} + +template int CPosixElxT :: Match(CContext * pContext) const +{ + if(m_posixfun == 0) return 0; + + int tlen = pContext->m_pMatchStringLength; + int npos = pContext->m_nCurrentPos; + + // check + int at = m_brightleft ? npos - 1 : npos; + if( at < 0 || at >= tlen ) + return 0; + + CHART ch = ((const CHART *)pContext->m_pMatchString)[at]; + + int bsucc = (*m_posixfun)(ch); + + if( ! m_byes ) + bsucc = ! bsucc; + + if( bsucc ) + pContext->m_nCurrentPos += m_brightleft ? -1 : 1; + + return bsucc; +} + +template int CPosixElxT :: MatchNext(CContext * pContext) const +{ + pContext->m_nCurrentPos -= m_brightleft ? -1 : 1; + return 0; +} + +// +// Possessive +// +template class CPossessiveElxT : public CGreedyElxT +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CPossessiveElxT(ElxInterface * pelx, int nmin = 0, int nmax = INT_MAX); +}; + +typedef CPossessiveElxT <0> CPossessiveElx; + +// +// Range Elx +// +template class CRangeElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CRangeElxT(int brightleft, int byes); + +public: + int IsContainChar(CHART ch) const; + +public: + CBufferT m_ranges; + CBufferT m_chars; + CBufferT m_embeds; + +public: + int m_brightleft; + int m_byes; +}; + +// +// Implementation +// +template CRangeElxT :: CRangeElxT(int brightleft, int byes) +{ + m_brightleft = brightleft; + m_byes = byes; +} + +template int CRangeElxT :: Match(CContext * pContext) const +{ + int tlen = pContext->m_pMatchStringLength; + int npos = pContext->m_nCurrentPos; + + // check + int at = m_brightleft ? npos - 1 : npos; + if( at < 0 || at >= tlen ) + return 0; + + CHART ch = ((const CHART *)pContext->m_pMatchString)[at]; + int bsucc = 0, i; + + // compare + for(i=0; !bsucc && iMatch(pContext)) + { + pContext->m_nCurrentPos = npos; + bsucc = 1; + } + } + + if( ! m_byes ) + bsucc = ! bsucc; + + if( bsucc ) + pContext->m_nCurrentPos += m_brightleft ? -1 : 1; + + return bsucc; +} + +template int CRangeElxT :: IsContainChar(CHART ch) const +{ + int bsucc = 0, i; + + // compare + for(i=0; !bsucc && i int CRangeElxT :: MatchNext(CContext * pContext) const +{ + pContext->m_nCurrentPos -= m_brightleft ? -1 : 1; + return 0; +} + +// +// Reluctant +// +template class CReluctantElxT : public CRepeatElxT +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CReluctantElxT(ElxInterface * pelx, int nmin = 0, int nmax = INT_MAX); + +protected: + int MatchVart (CContext * pContext) const; + int MatchNextVart(CContext * pContext) const; + +public: + int m_nvart; +}; + +typedef CReluctantElxT <0> CReluctantElx; + +// +// String Elx +// +template class CStringElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CStringElxT(const CHART * fixed, int nlength, int brightleft, int bignorecase); + +public: + CBufferT m_szPattern; + int m_brightleft; + int m_bignorecase; +}; + +// +// Implementation +// +template CStringElxT :: CStringElxT(const CHART * fixed, int nlength, int brightleft, int bignorecase) : m_szPattern(fixed, nlength) +{ + m_brightleft = brightleft; + m_bignorecase = bignorecase; +} + +template int CStringElxT :: Match(CContext * pContext) const +{ + const CHART * pcsz = (const CHART *)pContext->m_pMatchString; + int npos = pContext->m_nCurrentPos; + int tlen = pContext->m_pMatchStringLength; + int slen = m_szPattern.GetSize(); + + int bsucc; + + if(m_brightleft) + { + if(npos < slen) + return 0; + + if(m_bignorecase) + bsucc = ! m_szPattern.nCompareNoCase(pcsz + (npos - slen)); + else + bsucc = ! m_szPattern.nCompare (pcsz + (npos - slen)); + + if( bsucc ) + pContext->m_nCurrentPos -= slen; + } + else + { + if(npos + slen > tlen) + return 0; + + if(m_bignorecase) + bsucc = ! m_szPattern.nCompareNoCase(pcsz + npos); + else + bsucc = ! m_szPattern.nCompare (pcsz + npos); + + if( bsucc ) + pContext->m_nCurrentPos += slen; + } + + return bsucc; +} + +template int CStringElxT :: MatchNext(CContext * pContext) const +{ + int slen = m_szPattern.GetSize(); + + if(m_brightleft) + pContext->m_nCurrentPos += slen; + else + pContext->m_nCurrentPos -= slen; + + return 0; +} + +// +// CConditionElx +// +template class CConditionElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CConditionElxT(); + +public: + // backref condition + int m_nnumber; + CBufferT m_szNamed; + + // elx condition + ElxInterface * m_pelxask; + + // selection + ElxInterface * m_pelxyes, * m_pelxno; +}; + +template CConditionElxT :: CConditionElxT() +{ + m_nnumber = -1; +} + +template int CConditionElxT :: Match(CContext * pContext) const +{ + // status + int nbegin = pContext->m_nCurrentPos; + int nsize = pContext->m_stack.GetSize(); + int ncsize = pContext->m_capturestack.GetSize(); + + // condition result + int condition_yes = 0; + + // backref type + if( m_nnumber >= 0 ) + { + do + { + if(m_nnumber >= pContext->m_captureindex.GetSize()) break; + + int index = pContext->m_captureindex[m_nnumber]; + if( index < 0) break; + + // else valid + condition_yes = 1; + } + while(0); + } + else + { + if( m_pelxask == 0 ) + condition_yes = 1; + else + condition_yes = m_pelxask->Match(pContext); + + pContext->m_stack.Restore(nsize); + pContext->m_nCurrentPos = nbegin; + } + + // elx result + int bsucc; + if( condition_yes ) + bsucc = m_pelxyes == 0 ? 1 : m_pelxyes->Match(pContext); + else + bsucc = m_pelxno == 0 ? 1 : m_pelxno ->Match(pContext); + + if( bsucc ) + { + pContext->m_stack.Push(ncsize); + pContext->m_stack.Push(condition_yes); + } + else + { + pContext->m_capturestack.Restore(ncsize); + } + + return bsucc; +} + +template int CConditionElxT :: MatchNext(CContext * pContext) const +{ + // pop + int ncsize, condition_yes; + + pContext->m_stack.Pop(condition_yes); + pContext->m_stack.Pop(ncsize); + + // elx result + int bsucc; + if( condition_yes ) + bsucc = m_pelxyes == 0 ? 0 : m_pelxyes->MatchNext(pContext); + else + bsucc = m_pelxno == 0 ? 0 : m_pelxno ->MatchNext(pContext); + + if( bsucc ) + { + pContext->m_stack.Push(ncsize); + pContext->m_stack.Push(condition_yes); + } + else + { + pContext->m_capturestack.Restore(ncsize); + } + + return bsucc; +} + +// +// MatchResult +// +template class MatchResultT +{ +public: + int IsMatched() const; + +public: + int GetStart() const; + int GetEnd () const; + +public: + int MaxGroupNumber() const; + int GetGroupStart(int nGroupNumber) const; + int GetGroupEnd (int nGroupNumber) const; + +public: + MatchResultT(const MatchResultT & from) { *this = from; } + MatchResultT(CContext * pContext = 0, int nMaxNumber = -1); + MatchResultT & operator = (const MatchResultT &); + inline operator int() const { return IsMatched(); } + +public: + CBufferT m_result; +}; + +typedef MatchResultT <0> MatchResult; + +// Stocked Elx IDs +enum STOCKELX_ID_DEFINES +{ + STOCKELX_EMPTY = 0, + + /////////////////////// + + STOCKELX_DOT_ALL, + STOCKELX_DOT_NOT_ALL, + + STOCKELX_WORD, + STOCKELX_WORD_NOT, + + STOCKELX_SPACE, + STOCKELX_SPACE_NOT, + + STOCKELX_DIGITAL, + STOCKELX_DIGITAL_NOT, + + ////////////////////// + + STOCKELX_DOT_ALL_RIGHTLEFT, + STOCKELX_DOT_NOT_ALL_RIGHTLEFT, + + STOCKELX_WORD_RIGHTLEFT, + STOCKELX_WORD_RIGHTLEFT_NOT, + + STOCKELX_SPACE_RIGHTLEFT, + STOCKELX_SPACE_RIGHTLEFT_NOT, + + STOCKELX_DIGITAL_RIGHTLEFT, + STOCKELX_DIGITAL_RIGHTLEFT_NOT, + + ///////////////////// + + STOCKELX_COUNT +}; + +// REGEX_FLAGS +#ifndef _REGEX_FLAGS_DEFINED + enum REGEX_FLAGS + { + NO_FLAG = 0, + SINGLELINE = 0x01, + MULTILINE = 0x02, + GLOBAL = 0x04, + IGNORECASE = 0x08, + RIGHTTOLEFT = 0x10, + EXTENDED = 0x20 + }; + #define _REGEX_FLAGS_DEFINED +#endif + +// +// Builder T +// +template class CBuilderT +{ +public: + typedef CDelegateElxT CDelegateElx; + typedef CBracketElxT CBracketElx; + typedef CBackrefElxT CBackrefElx; + typedef CConditionElxT CConditionElx; + +// Methods +public: + ElxInterface * Build(const CBufferRefT & pattern, int flags); + int GetNamedNumber(const CBufferRefT & named) const; + void Clear(); + +public: + CBuilderT(); + ~CBuilderT(); + +// Public Attributes +public: + ElxInterface * m_pTopElx; + int m_nFlags; + int m_nMaxNumber; + int m_nNextNamed; + int m_nGroupCount; + + CBufferT m_objlist; + CBufferT m_grouplist; + CBufferT m_recursivelist; + CBufferT m_namedlist; + CBufferT m_namedbackreflist; + CBufferT m_namedconditionlist; + +// CHART_INFO +protected: + struct CHART_INFO + { + public: + CHART ch; + int type; + int pos; + int len; + + public: + CHART_INFO(CHART c, int t, int p = 0, int l = 0) { ch = c; type = t; pos = p; len = l; } + inline int operator == (const CHART_INFO & ci) { return ch == ci.ch && type == ci.type; } + inline int operator != (const CHART_INFO & ci) { return ! operator == (ci); } + }; + +protected: + static unsigned int Hex2Int(const CHART * pcsz, int length, int & used); + static int ReadDec(char * & str, unsigned int & dec); + void MoveNext(); + int GetNext2(); + + ElxInterface * BuildAlternative(int vaflags); + ElxInterface * BuildList (int & flags); + ElxInterface * BuildRepeat (int & flags); + ElxInterface * BuildSimple (int & flags); + ElxInterface * BuildCharset (int & flags); + ElxInterface * BuildRecursive (int & flags); + ElxInterface * BuildBoundary (int & flags); + ElxInterface * BuildBackref (int & flags); + + ElxInterface * GetStockElx (int nStockId); + ElxInterface * Keep(ElxInterface * pElx); + +// Private Attributes +protected: + CBufferRefT m_pattern; + CHART_INFO prev, curr, next, nex2; + int m_nNextPos; + int m_nCharsetDepth; + int m_bQuoted; + POSIX_FUNC m_quote_fun; + + // Backup current pos + struct Snapshot + { + CHART_INFO prev, curr, next, nex2; + int m_nNextPos; + int m_nCharsetDepth; + int m_bQuoted; + POSIX_FUNC m_quote_fun; + Snapshot():prev(0,0),curr(0,0),next(0,0),nex2(0,0) {} + }; + void Backup (Snapshot * pdata) { memcpy(pdata, &prev, sizeof(Snapshot)); } + void Restore(Snapshot * pdata) { memcpy(&prev, pdata, sizeof(Snapshot)); } + + ElxInterface * m_pStockElxs[STOCKELX_COUNT]; +}; + +// +// Implementation +// +template CBuilderT :: CBuilderT() : m_pattern(0, 0), prev(0, 0), curr(0, 0), next(0, 0), nex2(0, 0) +{ + Clear(); +} + +template CBuilderT :: ~CBuilderT() +{ + Clear(); +} + +template int CBuilderT :: GetNamedNumber(const CBufferRefT & named) const +{ + for(int i=0; im_elxlist[0])->m_szNamed.CompareNoCase(named) ) + return ((CBracketElx *)m_namedlist[i]->m_elxlist[0])->m_nnumber; + } + + return -3; +} + +template ElxInterface * CBuilderT :: Build(const CBufferRefT & pattern, int flags) +{ + // init + m_pattern = pattern; + m_nNextPos = 0; + m_nCharsetDepth = 0; + m_nMaxNumber = 0; + m_nNextNamed = 0; + m_nFlags = flags; + m_bQuoted = 0; + m_quote_fun = 0; + + m_grouplist .Restore(0); + m_recursivelist .Restore(0); + m_namedlist .Restore(0); + m_namedbackreflist .Restore(0); + m_namedconditionlist.Restore(0); + + int i; + for(i=0; i<3; i++) MoveNext(); + + // build + m_pTopElx = BuildAlternative(flags); + + // group 0 + m_grouplist.Prepare(0); + m_grouplist[0] = m_pTopElx; + + // append named to unnamed + m_nGroupCount = m_grouplist.GetSize(); + + m_grouplist.Prepare(m_nMaxNumber + m_namedlist.GetSize()); + + for(i=0; im_elxlist[0]; + CBracketElx * pright = (CBracketElx *)m_namedlist[i]->m_elxlist[2]; + + // append + m_grouplist[m_nGroupCount ++] = m_namedlist[i]; + + if( pleft->m_nnumber > 0 ) + continue; + + // same name + int find_same_name = GetNamedNumber(pleft->m_szNamed); + if( find_same_name >= 0 ) + { + pleft ->m_nnumber = find_same_name; + pright->m_nnumber = find_same_name; + } + else + { + m_nMaxNumber ++; + + pleft ->m_nnumber = m_nMaxNumber; + pright->m_nnumber = m_nMaxNumber; + } + } + + for(i=1; im_elxlist[0]; + + if( pleft->m_nnumber > m_nMaxNumber ) + m_nMaxNumber = pleft->m_nnumber; + } + + // connect recursive + for(i=0; im_ndata == -3 ) + m_recursivelist[i]->m_ndata = GetNamedNumber(m_recursivelist[i]->m_szNamed); + + if( m_recursivelist[i]->m_ndata >= 0 && m_recursivelist[i]->m_ndata <= m_nMaxNumber ) + { + if( m_recursivelist[i]->m_ndata == 0 ) + m_recursivelist[i]->m_pelx = m_pTopElx; + else for(int j=1; jm_ndata == ((CBracketElx *)((CListElx*)m_grouplist[j])->m_elxlist[0])->m_nnumber) + { + m_recursivelist[i]->m_pelx = m_grouplist[j]; + break; + } + } + } + } + + // named backref + for(i=0; im_nnumber = GetNamedNumber(m_namedbackreflist[i]->m_szNamed); + } + + // named condition + for(i=0; im_szNamed); + if( nn >= 0 ) + { + m_namedconditionlist[i]->m_nnumber = nn; + m_namedconditionlist[i]->m_pelxask = 0; + } + } + + return m_pTopElx; +} + +template void CBuilderT :: Clear() +{ + for(int i=0; i unsigned int CBuilderT :: Hex2Int(const CHART * pcsz, int length, int & used) +{ + unsigned int result = 0; + int & i = used; + + for(i=0; i= RCHART('0') && pcsz[i] <= RCHART('9')) + result = (result << 4) + (pcsz[i] - RCHART('0')); + else if(pcsz[i] >= RCHART('A') && pcsz[i] <= RCHART('F')) + result = (result << 4) + (0x0A + (pcsz[i] - RCHART('A'))); + else if(pcsz[i] >= RCHART('a') && pcsz[i] <= RCHART('f')) + result = (result << 4) + (0x0A + (pcsz[i] - RCHART('a'))); + else + break; + } + + return result; +} + +template inline ElxInterface * CBuilderT :: Keep(ElxInterface * pelx) +{ + m_objlist.Push(pelx); + return pelx; +} + +template void CBuilderT :: MoveNext() +{ + // forwards + prev = curr; + curr = next; + next = nex2; + + // get nex2 + while( ! GetNext2() ) {}; +} + +template int CBuilderT :: GetNext2() +{ + // check length + if(m_nNextPos >= m_pattern.GetSize()) + { + nex2 = CHART_INFO(0, 1, m_nNextPos, 0); + return 1; + } + + int delta = 1; + CHART ch = m_pattern[m_nNextPos]; + + // if quoted + if(m_bQuoted) + { + if(ch == RCHART('\\')) + { + if(m_pattern[m_nNextPos + 1] == RCHART('E')) + { + m_quote_fun = 0; + m_bQuoted = 0; + m_nNextPos += 2; + return 0; + } + } + + if(m_quote_fun != 0) + nex2 = CHART_INFO((CHART)(*m_quote_fun)((int)ch), 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + + m_nNextPos += delta; + + return 1; + } + + // common + switch(ch) + { + case RCHART('\\'): + { + CHART ch1 = m_pattern[m_nNextPos+1]; + + // backref + if(ch1 >= RCHART('0') && ch1 <= RCHART('9')) + { + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + break; + } + + // escape + delta = 2; + + switch(ch1) + { + case RCHART('A'): + case RCHART('Z'): + case RCHART('z'): + case RCHART('w'): + case RCHART('W'): + case RCHART('s'): + case RCHART('S'): + case RCHART('B'): + case RCHART('d'): + case RCHART('D'): + case RCHART('k'): + case RCHART('g'): + nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta); + break; + + case RCHART('b'): + if(m_nCharsetDepth > 0) + nex2 = CHART_INFO('\b', 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta); + break; + + /* + case RCHART('<'): + case RCHART('>'): + if(m_nCharsetDepth > 0) + nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta); + break; + */ + + case RCHART('x'): + if(m_pattern[m_nNextPos+2] != '{') + { + int red = 0; + unsigned int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 2, 2, red); + + delta += red; + + if(red > 0) + nex2 = CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); + + break; + } + + case RCHART('u'): + if(m_pattern[m_nNextPos+2] != '{') + { + int red = 0; + unsigned int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 2, 4, red); + + delta += red; + + if(red > 0) + nex2 = CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); + } + else + { + int red = 0; + unsigned int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 3, sizeof(int) * 2, red); + + delta += red; + + while(m_nNextPos + delta < m_pattern.GetSize() && m_pattern.At(m_nNextPos + delta) != RCHART('}')) + delta ++; + + delta ++; // skip '}' + + nex2 = CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta); + } + break; + + case RCHART('a'): nex2 = CHART_INFO(RCHART('\a'), 0, m_nNextPos, delta); break; + case RCHART('f'): nex2 = CHART_INFO(RCHART('\f'), 0, m_nNextPos, delta); break; + case RCHART('n'): nex2 = CHART_INFO(RCHART('\n'), 0, m_nNextPos, delta); break; + case RCHART('r'): nex2 = CHART_INFO(RCHART('\r'), 0, m_nNextPos, delta); break; + case RCHART('t'): nex2 = CHART_INFO(RCHART('\t'), 0, m_nNextPos, delta); break; + case RCHART('v'): nex2 = CHART_INFO(RCHART('\v'), 0, m_nNextPos, delta); break; + case RCHART('e'): nex2 = CHART_INFO(RCHART( 27 ), 0, m_nNextPos, delta); break; + + case RCHART('G'): // skip '\G' + if(m_nCharsetDepth > 0) + { + m_nNextPos += 2; + return 0; + } + else + { + nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta); + break; + } + + case RCHART('L'): + if( ! m_quote_fun ) m_quote_fun = ::tolower; + + case RCHART('U'): + if( ! m_quote_fun ) m_quote_fun = ::toupper; + + case RCHART('Q'): + { + m_bQuoted = 1; + m_nNextPos += 2; + return 0; + } + + case RCHART('E'): + { + m_quote_fun = 0; + m_bQuoted = 0; + m_nNextPos += 2; + return 0; + } + + case 0: + if(m_nNextPos+1 >= m_pattern.GetSize()) + { + delta = 1; + nex2 = CHART_INFO(ch , 0, m_nNextPos, delta); + } + else + nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); // common '\0' char + break; + + default: + nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); + break; + } + } + break; + + case RCHART('*'): + case RCHART('+'): + case RCHART('?'): + case RCHART('.'): + case RCHART('{'): + case RCHART('}'): + case RCHART(')'): + case RCHART('|'): + case RCHART('$'): + if(m_nCharsetDepth > 0) + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + break; + + case RCHART('-'): + if(m_nCharsetDepth > 0) + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + break; + + case RCHART('('): + { + CHART ch1 = m_pattern[m_nNextPos+1]; + CHART ch2 = m_pattern[m_nNextPos+2]; + + // skip remark + if(ch1 == RCHART('?') && ch2 == RCHART('#')) + { + m_nNextPos += 2; + while(m_nNextPos < m_pattern.GetSize()) + { + if(m_pattern[m_nNextPos] == RCHART(')')) + break; + + m_nNextPos ++; + } + + if(m_pattern[m_nNextPos] == RCHART(')')) + { + m_nNextPos ++; + + // get next nex2 + return 0; + } + } + else + { + if(m_nCharsetDepth > 0) + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + } + } + break; + + case RCHART('#'): + if(m_nFlags & EXTENDED) + { + // skip remark + m_nNextPos ++; + + while(m_nNextPos < m_pattern.GetSize()) + { + if(m_pattern[m_nNextPos] == RCHART('\n') || m_pattern[m_nNextPos] == RCHART('\r')) + break; + + m_nNextPos ++; + } + + // get next nex2 + return 0; + } + else + { + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + } + break; + + case RCHART(' '): + case RCHART('\f'): + case RCHART('\n'): + case RCHART('\r'): + case RCHART('\t'): + case RCHART('\v'): + if(m_nFlags & EXTENDED) + { + m_nNextPos ++; + + // get next nex2 + return 0; + } + else + { + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + } + break; + + case RCHART('['): + if( m_nCharsetDepth == 0 || m_pattern.At(m_nNextPos + 1, 0) == RCHART(':') ) + { + m_nCharsetDepth ++; + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + } + else + { + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + } + break; + + case RCHART(']'): + if(m_nCharsetDepth > 0) + { + m_nCharsetDepth --; + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + } + else + { + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + } + break; + + case RCHART(':'): + if(next == CHART_INFO(RCHART('['), 1)) + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + break; + + case RCHART('^'): + if(m_nCharsetDepth == 0 || next == CHART_INFO(RCHART('['), 1) || (curr == CHART_INFO(RCHART('['), 1) && next == CHART_INFO(RCHART(':'), 1))) + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + break; + + case 0: + if(m_nNextPos >= m_pattern.GetSize()) + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); // end of string + else + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); // common '\0' char + break; + + default: + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + break; + } + + m_nNextPos += delta; + + return 1; +} + +template ElxInterface * CBuilderT :: GetStockElx(int nStockId) +{ + ElxInterface ** pStockElxs = m_pStockElxs; + + // check + if(nStockId < 0 || nStockId >= STOCKELX_COUNT) + return GetStockElx(0); + + // create if no + if(pStockElxs[nStockId] == 0) + { + switch(nStockId) + { + case STOCKELX_EMPTY: + pStockElxs[nStockId] = Keep(new CEmptyElx()); + break; + + case STOCKELX_WORD: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 1)); + + pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z')); + pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z')); + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + pRange->m_chars .Push(RCHART('_')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_WORD_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 0)); + + pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z')); + pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z')); + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + pRange->m_chars .Push(RCHART('_')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DOT_ALL: + pStockElxs[nStockId] = Keep(new CRangeElxT (0, 0)); + break; + + case STOCKELX_DOT_NOT_ALL: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 0)); + + pRange->m_chars .Push(RCHART('\n')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_SPACE: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 1)); + + pRange->m_chars .Push(RCHART(' ')); + pRange->m_chars .Push(RCHART('\t')); + pRange->m_chars .Push(RCHART('\r')); + pRange->m_chars .Push(RCHART('\n')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_SPACE_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 0)); + + pRange->m_chars .Push(RCHART(' ')); + pRange->m_chars .Push(RCHART('\t')); + pRange->m_chars .Push(RCHART('\r')); + pRange->m_chars .Push(RCHART('\n')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DIGITAL: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 1)); + + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DIGITAL_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 0)); + + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_WORD_RIGHTLEFT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 1)); + + pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z')); + pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z')); + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + pRange->m_chars .Push(RCHART('_')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_WORD_RIGHTLEFT_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 0)); + + pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z')); + pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z')); + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + pRange->m_chars .Push(RCHART('_')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DOT_ALL_RIGHTLEFT: + pStockElxs[nStockId] = Keep(new CRangeElxT (1, 0)); + break; + + case STOCKELX_DOT_NOT_ALL_RIGHTLEFT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 0)); + + pRange->m_chars .Push(RCHART('\n')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_SPACE_RIGHTLEFT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 1)); + + pRange->m_chars .Push(RCHART(' ')); + pRange->m_chars .Push(RCHART('\t')); + pRange->m_chars .Push(RCHART('\r')); + pRange->m_chars .Push(RCHART('\n')); + pRange->m_chars .Push(RCHART('\f')); + pRange->m_chars .Push(RCHART('\v')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_SPACE_RIGHTLEFT_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 0)); + + pRange->m_chars .Push(RCHART(' ')); + pRange->m_chars .Push(RCHART('\t')); + pRange->m_chars .Push(RCHART('\r')); + pRange->m_chars .Push(RCHART('\n')); + pRange->m_chars .Push(RCHART('\f')); + pRange->m_chars .Push(RCHART('\v')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DIGITAL_RIGHTLEFT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 1)); + + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DIGITAL_RIGHTLEFT_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 0)); + + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + + pStockElxs[nStockId] = pRange; + } + break; + } + } + + // return + return pStockElxs[nStockId]; +} + +template ElxInterface * CBuilderT :: BuildAlternative(int vaflags) +{ + if(curr == CHART_INFO(0, 1)) + return GetStockElx(STOCKELX_EMPTY); + + // flag instance + int flags = vaflags; + + // first part + ElxInterface * pAlternativeOne = BuildList(flags); + + // check alternative + if(curr == CHART_INFO(RCHART('|'), 1)) + { + CAlternativeElx * pAlternative = (CAlternativeElx *)Keep(new CAlternativeElx()); + pAlternative->m_elxlist.Push(pAlternativeOne); + + // loop + while(curr == CHART_INFO(RCHART('|'), 1)) + { + // skip '|' itself + MoveNext(); + + pAlternativeOne = BuildList(flags); + pAlternative->m_elxlist.Push(pAlternativeOne); + } + + return pAlternative; + } + + return pAlternativeOne; +} + +template ElxInterface * CBuilderT :: BuildList(int & flags) +{ + if(curr == CHART_INFO(0, 1) || curr == CHART_INFO(RCHART('|'), 1) || curr == CHART_INFO(RCHART(')'), 1)) + return GetStockElx(STOCKELX_EMPTY); + + // first + ElxInterface * pListOne = BuildRepeat(flags); + + if(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('|'), 1) && curr != CHART_INFO(RCHART(')'), 1)) + { + CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT)); + pList->m_elxlist.Push(pListOne); + + while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('|'), 1) && curr != CHART_INFO(RCHART(')'), 1)) + { + pListOne = BuildRepeat(flags); + + // add + pList->m_elxlist.Push(pListOne); + } + + return pList; + } + + return pListOne; +} + +template ElxInterface * CBuilderT :: BuildRepeat(int & flags) +{ + // simple + ElxInterface * pSimple = BuildSimple(flags); + + if(curr.type == 0) return pSimple; + + // is quantifier or not + int bIsQuantifier = 1; + + // quantifier range + unsigned int nMin = 0, nMax = 0; + + switch(curr.ch) + { + case RCHART('{'): + { + CBufferT re; + + // skip '{' + MoveNext(); + + // copy + while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('}'), 1)) + { + re.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + + // skip '}' + MoveNext(); + + // read + int red; + char * str = re.GetBuffer(); + + if( ! ReadDec(str, nMin) ) + red = 0; + else if( *str != ',' ) + red = 1; + else + { + str ++; + + if( ! ReadDec(str, nMax) ) + red = 2; + else + red = 3; + } + + // check + if(red <= 1 ) nMax = nMin; + if(red == 2 ) nMax = INT_MAX; + if(nMax < nMin) nMax = nMin; + } + break; + + case RCHART('?'): + nMin = 0; + nMax = 1; + + // skip '?' + MoveNext(); + break; + + case RCHART('*'): + nMin = 0; + nMax = INT_MAX; + + // skip '*' + MoveNext(); + break; + + case RCHART('+'): + nMin = 1; + nMax = INT_MAX; + + // skip '+' + MoveNext(); + break; + + default: + bIsQuantifier = 0; + break; + } + + // do quantify + if(bIsQuantifier) + { + // 0 times + if(nMax == 0) + return GetStockElx(STOCKELX_EMPTY); + + // fixed times + if(nMin == nMax) + { + if(curr == CHART_INFO(RCHART('?'), 1) || curr == CHART_INFO(RCHART('+'), 1)) + MoveNext(); + + return Keep(new CRepeatElx(pSimple, nMin)); + } + + // range times + if(curr == CHART_INFO(RCHART('?'), 1)) + { + MoveNext(); + return Keep(new CReluctantElx(pSimple, nMin, nMax)); + } + else if(curr == CHART_INFO(RCHART('+'), 1)) + { + MoveNext(); + return Keep(new CPossessiveElx(pSimple, nMin, nMax)); + } + else + { + return Keep(new CGreedyElx(pSimple, nMin, nMax)); + } + } + + return pSimple; +} + +template ElxInterface * CBuilderT :: BuildSimple(int & flags) +{ + CBufferT fixed; + + while(curr != CHART_INFO(0, 1)) + { + if(curr.type == 0) + { + if(next == CHART_INFO(RCHART('{'), 1) || next == CHART_INFO(RCHART('?'), 1) || next == CHART_INFO(RCHART('*'), 1) || next == CHART_INFO(RCHART('+'), 1)) + { + if(fixed.GetSize() == 0) + { + fixed.Append(curr.ch, 1); + MoveNext(); + } + + break; + } + else + { + fixed.Append(curr.ch, 1); + MoveNext(); + } + } + else if(curr.type == 1) + { + CHART vch = curr.ch; + + // end of simple + if(vch == RCHART(')') || vch == RCHART('|')) + break; + + // has fixed already + if(fixed.GetSize() > 0) + break; + + // left parentheses + if(vch == RCHART('(')) + { + return BuildRecursive(flags); + } + + // char set + if( vch == RCHART('[') || vch == RCHART('.') || vch == RCHART('w') || vch == RCHART('W') || + vch == RCHART('s') || vch == RCHART('S') || vch == RCHART('d') || vch == RCHART('D') + ) + { + return BuildCharset(flags); + } + + // boundary + if( vch == RCHART('^') || vch == RCHART('$') || vch == RCHART('A') || vch == RCHART('Z') || vch == RCHART('z') || + vch == RCHART('b') || vch == RCHART('B') || vch == RCHART('G') // vch == RCHART('<') || vch == RCHART('>') + ) + { + return BuildBoundary(flags); + } + + // backref + if(vch == RCHART('\\') || vch == RCHART('k') || vch == RCHART('g')) + { + return BuildBackref(flags); + } + + // treat vchar as char + fixed.Append(curr.ch, 1); + MoveNext(); + } + } + + if(fixed.GetSize() > 0) + return Keep(new CStringElxT (fixed.GetBuffer(), fixed.GetSize(), flags & RIGHTTOLEFT, flags & IGNORECASE)); + else + return GetStockElx(STOCKELX_EMPTY); +} + +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +template ElxInterface * CBuilderT :: BuildCharset(int & flags) +{ + // char + CHART ch = curr.ch; + + // skip + MoveNext(); + + switch(ch) + { + case RCHART('.'): + return GetStockElx( + flags & RIGHTTOLEFT ? + ((flags & SINGLELINE) ? STOCKELX_DOT_ALL_RIGHTLEFT : STOCKELX_DOT_NOT_ALL_RIGHTLEFT) : + ((flags & SINGLELINE) ? STOCKELX_DOT_ALL : STOCKELX_DOT_NOT_ALL) + ); + + case RCHART('w'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_WORD_RIGHTLEFT : STOCKELX_WORD); + + case RCHART('W'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_WORD_RIGHTLEFT_NOT : STOCKELX_WORD_NOT); + + case RCHART('s'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_SPACE_RIGHTLEFT : STOCKELX_SPACE); + + case RCHART('S'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_SPACE_RIGHTLEFT_NOT : STOCKELX_SPACE_NOT); + + case RCHART('d'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_DIGITAL_RIGHTLEFT : STOCKELX_DIGITAL); + + case RCHART('D'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_DIGITAL_RIGHTLEFT_NOT : STOCKELX_DIGITAL_NOT); + + case RCHART('['): + { + CRangeElxT * pRange; + + // create + if(curr == CHART_INFO(RCHART(':'), 1)) + { + // Backup before posix + Snapshot shot; + Backup(&shot); + + CBufferT posix; + + do { + posix.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + while(curr.ch != RCHART(0) && curr != CHART_INFO(RCHART(']'), 1)); + + MoveNext(); // skip ']' + + // posix + CPosixElxT * pposix = (CPosixElxT *) Keep(new CPosixElxT (posix.GetBuffer(), flags & RIGHTTOLEFT)); + if(pposix->m_posixfun != 0) + { + return pposix; + } + + // restore if not posix + Restore(&shot); + } + + if(curr == CHART_INFO(RCHART('^'), 1)) + { + MoveNext(); // skip '^' + pRange = (CRangeElxT *)Keep(new CRangeElxT (flags & RIGHTTOLEFT, 0)); + } + else + { + pRange = (CRangeElxT *)Keep(new CRangeElxT (flags & RIGHTTOLEFT, 1)); + } + + // parse + while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART(']'), 1)) + { + ch = curr.ch; + + if(curr.type == 1 && ( + ch == RCHART('.') || ch == RCHART('w') || ch == RCHART('W') || ch == RCHART('s') || ch == RCHART('S') || ch == RCHART('d') || ch == RCHART('D') || + (ch == RCHART('[') && next == CHART_INFO(RCHART(':'), 1)) + )) + { + pRange->m_embeds.Push(BuildCharset(flags)); + } + else if(next == CHART_INFO(RCHART('-'), 1) && nex2.type == 0) + { + pRange->m_ranges.Push(ch); pRange->m_ranges.Push(nex2.ch); + + // next + MoveNext(); + MoveNext(); + MoveNext(); + } + else + { + pRange->m_chars.Push(ch); + + // next + MoveNext(); + } + } + + // skip ']' + MoveNext(); + + if( flags & IGNORECASE ) + { + CBufferT & ranges = pRange->m_ranges; + int i, oldcount = ranges.GetSize() / 2; + + for(i=0; i= RCHART('A') ) + { + newmin = tolower( max(RCHART('A'), ranges[i*2 ]) ); + newmax = tolower( min(RCHART('Z'), ranges[i*2+1]) ); + + if( newmin < ranges[i*2] || newmax > ranges[i*2+1] ) + { + ranges.Push(newmin); + ranges.Push(newmax); + } + } + + if( ranges[i*2] <= RCHART('z') && ranges[i*2+1] >= RCHART('a') ) + { + newmin = toupper( max(RCHART('a'), ranges[i*2 ]) ); + newmax = toupper( min(RCHART('z'), ranges[i*2+1]) ); + + if( newmin < ranges[i*2] || newmax > ranges[i*2+1] ) + { + ranges.Push(newmin); + ranges.Push(newmax); + } + } + } + + CBufferT & chars = pRange->m_chars; + oldcount = chars.GetSize(); + for(i=0; iIsContainChar(tolower(chars[i])) ) + chars.Push(tolower(chars[i])); + + if( islower(chars[i]) && ! pRange->IsContainChar(toupper(chars[i])) ) + chars.Push(toupper(chars[i])); + } + } + + return pRange; + } + } + + return GetStockElx(STOCKELX_EMPTY); +} + +template ElxInterface * CBuilderT :: BuildRecursive(int & flags) +{ + // skip '(' + MoveNext(); + + if(curr == CHART_INFO(RCHART('?'), 1)) + { + ElxInterface * pElx = 0; + + // skip '?' + MoveNext(); + + int bNegative = 0; + CHART named_end = RCHART('>'); + + switch(curr.ch) + { + case RCHART('!'): + bNegative = 1; + + case RCHART('='): + { + MoveNext(); // skip '!' or '=' + pElx = Keep(new CAssertElx(BuildAlternative(flags & ~RIGHTTOLEFT), !bNegative)); + } + break; + + case RCHART('<'): + switch(next.ch) + { + case RCHART('!'): + bNegative = 1; + + case RCHART('='): + MoveNext(); // skip '<' + MoveNext(); // skip '!' or '=' + { + pElx = Keep(new CAssertElx(BuildAlternative(flags | RIGHTTOLEFT), !bNegative)); + } + break; + + default: // named group + break; + } + // break if assertion // else named + if(pElx != 0) break; + + case RCHART('P'): + if(curr.ch == RCHART('P')) MoveNext(); // skip 'P' + + case RCHART('\''): + if (curr.ch == RCHART('<' )) named_end = RCHART('>' ); + else if(curr.ch == RCHART('\'')) named_end = RCHART('\''); + MoveNext(); // skip '<' or '\'' + { + // named number + int nThisBackref = m_nNextNamed ++; + + CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT)); + CBracketElx * pleft = (CBracketElx *)Keep(new CBracketElx(-1, flags & RIGHTTOLEFT ? 1 : 0)); + CBracketElx * pright = (CBracketElx *)Keep(new CBracketElx(-1, flags & RIGHTTOLEFT ? 0 : 1)); + + // save name + CBufferT & name = pleft->m_szNamed; + CBufferT num; + + while(curr.ch != RCHART(0) && curr.ch != named_end) + { + name.Append(curr.ch, 1); + num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + MoveNext(); // skip '>' or '\'' + + // check + unsigned int number; + char * str = num.GetBuffer(); + + if( ReadDec(str, number) ? ( *str == '\0') : 0 ) + { + pleft ->m_nnumber = number; + pright->m_nnumber = number; + + name.Release(); + } + + // left, center, right + pList->m_elxlist.Push(pleft); + pList->m_elxlist.Push(BuildAlternative(flags)); + pList->m_elxlist.Push(pright); + + // for recursive + m_namedlist.Prepare(nThisBackref); + m_namedlist[nThisBackref] = pList; + + pElx = pList; + } + break; + + case RCHART('>'): + { + MoveNext(); // skip '>' + pElx = Keep(new CIndependentElx(BuildAlternative(flags))); + } + break; + + case RCHART('R'): + MoveNext(); // skip 'R' + while(curr.ch != RCHART(0) && isspace(curr.ch)) MoveNext(); // skip space + + if(curr.ch == RCHART('<') || curr.ch == RCHART('\'')) + { + named_end = curr.ch == RCHART('<') ? RCHART('>') : RCHART('\''); + CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(-3)); + + MoveNext(); // skip '<' or '\\' + + // save name + CBufferT & name = pDelegate->m_szNamed; + CBufferT num; + + while(curr.ch != RCHART(0) && curr.ch != named_end) + { + name.Append(curr.ch, 1); + num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + MoveNext(); // skip '>' or '\'' + + // check + unsigned int number; + char * str = num.GetBuffer(); + + if( ReadDec(str, number) ? ( *str == '\0') : 0 ) + { + pDelegate->m_ndata = number; + name.Release(); + } + + m_recursivelist.Push(pDelegate); + pElx = pDelegate; + } + else + { + CBufferT rto; + while(curr.ch != RCHART(0) && curr.ch != RCHART(')')) + { + rto.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + + unsigned int rtono = 0; + char * str = rto.GetBuffer(); + ReadDec(str, rtono); + + CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(rtono)); + + m_recursivelist.Push(pDelegate); + pElx = pDelegate; + } + break; + + case RCHART('('): + { + CConditionElx * pConditionElx = (CConditionElx *)Keep(new CConditionElx()); + + // condition + ElxInterface * & pCondition = pConditionElx->m_pelxask; + + if(next == CHART_INFO(RCHART('?'), 1)) + { + pCondition = BuildRecursive(flags); + } + else // named, assert or number + { + MoveNext(); // skip '(' + int pos0 = curr.pos; + + // save elx condition + pCondition = Keep(new CAssertElx(BuildAlternative(flags), 1)); + + // save name + pConditionElx->m_szNamed.Append(m_pattern.GetBuffer() + pos0, curr.pos - pos0, 1); + + // save number + CBufferT numstr; + while(pos0 < curr.pos) + { + CHART ch = m_pattern[pos0]; + numstr.Append(((ch & (CHART)0xff) == ch) ? (char)ch : 0, 1); + pos0 ++; + } + + unsigned int number; + char * str = numstr.GetBuffer(); + + // valid group number + if( ReadDec(str, number) ? ( *str == '\0') : 0 ) + { + pConditionElx->m_nnumber = number; + pCondition = 0; + } + else // maybe elx, maybe named + { + pConditionElx->m_nnumber = -1; + m_namedconditionlist.Push(pConditionElx); + } + + MoveNext(); // skip ')' + } + + // alternative + { + int newflags = flags; + + pConditionElx->m_pelxyes = BuildList(newflags); + } + + if(curr.ch == RCHART('|')) + { + MoveNext(); // skip '|' + + pConditionElx->m_pelxno = BuildAlternative(flags); + } + else + { + pConditionElx->m_pelxno = 0; + } + + pElx = pConditionElx; + } + break; + + default: + while(curr.ch != RCHART(0) && isspace(curr.ch)) MoveNext(); // skip space + + if(curr.ch >= RCHART('0') && curr.ch <= RCHART('9')) // recursive (?1) => (?R1) + { + CBufferT rto; + while(curr.ch != RCHART(0) && curr.ch != RCHART(')')) + { + rto.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + + unsigned int rtono = 0; + char * str = rto.GetBuffer(); + ReadDec(str, rtono); + + CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(rtono)); + + m_recursivelist.Push(pDelegate); + pElx = pDelegate; + } + else + { + // flag + int newflags = flags; + while(curr != CHART_INFO(0, 1) && curr.ch != RCHART(':') && curr.ch != RCHART(')') && curr != CHART_INFO(RCHART('('), 1)) + { + int tochange = 0; + + switch(curr.ch) + { + case RCHART('i'): + case RCHART('I'): + tochange = IGNORECASE; + break; + + case RCHART('s'): + case RCHART('S'): + tochange = SINGLELINE; + break; + + case RCHART('m'): + case RCHART('M'): + tochange = MULTILINE; + break; + + case RCHART('g'): + case RCHART('G'): + tochange = GLOBAL; + break; + + case RCHART('-'): + bNegative = 1; + break; + } + + if(bNegative) + newflags &= ~tochange; + else + newflags |= tochange; + + // move to next char + MoveNext(); + } + + if(curr.ch == RCHART(':') || curr == CHART_INFO(RCHART('('), 1)) + { + // skip ':' + if(curr.ch == RCHART(':')) MoveNext(); + + pElx = BuildAlternative(newflags); + } + else + { + // change parent flags + flags = newflags; + + pElx = GetStockElx(STOCKELX_EMPTY); + } + } + break; + } + + MoveNext(); // skip ')' + + return pElx; + } + else + { + // group and number + CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT)); + int nThisBackref = ++ m_nMaxNumber; + + // left, center, right + pList->m_elxlist.Push(Keep(new CBracketElx(nThisBackref, flags & RIGHTTOLEFT ? 1 : 0))); + pList->m_elxlist.Push(BuildAlternative(flags)); + pList->m_elxlist.Push(Keep(new CBracketElx(nThisBackref, flags & RIGHTTOLEFT ? 0 : 1))); + + // for recursive + m_grouplist.Prepare(nThisBackref); + m_grouplist[nThisBackref] = pList; + + // right + MoveNext(); // skip ')' + + return pList; + } +} + +template ElxInterface * CBuilderT :: BuildBoundary(int & flags) +{ + // char + CHART ch = curr.ch; + + // skip + MoveNext(); + + switch(ch) + { + case RCHART('^'): + return Keep(new CBoundaryElxT ((flags & MULTILINE) ? BOUNDARY_LINE_BEGIN : BOUNDARY_FILE_BEGIN)); + + case RCHART('$'): + return Keep(new CBoundaryElxT ((flags & MULTILINE) ? BOUNDARY_LINE_END : BOUNDARY_FILE_END)); + + case RCHART('b'): + return Keep(new CBoundaryElxT (BOUNDARY_WORD_EDGE)); + + case RCHART('B'): + return Keep(new CBoundaryElxT (BOUNDARY_WORD_EDGE, 0)); + + case RCHART('A'): + return Keep(new CBoundaryElxT (BOUNDARY_FILE_BEGIN)); + + case RCHART('Z'): + return Keep(new CBoundaryElxT (BOUNDARY_FILE_END_N)); + + case RCHART('z'): + return Keep(new CBoundaryElxT (BOUNDARY_FILE_END)); + + case RCHART('G'): + if(flags & GLOBAL) + return Keep(new CGlobalElx()); + else + return GetStockElx(STOCKELX_EMPTY); + + default: + return GetStockElx(STOCKELX_EMPTY); + } +} + +template ElxInterface * CBuilderT :: BuildBackref(int & flags) +{ + // skip '\\' or '\k' or '\g' + MoveNext(); + + if(curr.ch == RCHART('<') || curr.ch == RCHART('\'')) + { + CHART named_end = curr.ch == RCHART('<') ? RCHART('>') : RCHART('\''); + CBackrefElxT * pbackref = (CBackrefElxT *)Keep(new CBackrefElxT (-1, flags & RIGHTTOLEFT, flags & IGNORECASE)); + + MoveNext(); // skip '<' or '\'' + + // save name + CBufferT & name = pbackref->m_szNamed; + CBufferT num; + + while(curr.ch != RCHART(0) && curr.ch != named_end) + { + name.Append(curr.ch, 1); + num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + MoveNext(); // skip '>' or '\'' + + // check + unsigned int number; + char * str = num.GetBuffer(); + + if( ReadDec(str, number) ? ( *str == '\0') : 0 ) + { + pbackref->m_nnumber = number; + name.Release(); + } + else + { + m_namedbackreflist.Push(pbackref); + } + + return pbackref; + } + else + { + unsigned int nbackref = 0; + + for(int i=0; i<3; i++) + { + if(curr.ch >= RCHART('0') && curr.ch <= RCHART('9')) + nbackref = nbackref * 10 + (curr.ch - RCHART('0')); + else + break; + + MoveNext(); + } + + return Keep(new CBackrefElxT (nbackref, flags & RIGHTTOLEFT, flags & IGNORECASE)); + } +} + +template int CBuilderT :: ReadDec(char * & str, unsigned int & dec) +{ + int s = 0; + while(str[s] != 0 && isspace(str[s])) s++; + + if(str[s] < '0' || str[s] > '9') return 0; + + dec = 0; + unsigned int i; + + for(i = s; i= '0' && str[i] <= '9') + dec = dec * 10 + (str[i] - '0'); + else + break; + } + + while(str[i] != 0 && isspace(str[i])) i++; + str += i; + + return 1; +} + +// +// Regexp +// +template class CRegexpT +{ +public: + CRegexpT(const CHART * pattern = 0, int flags = 0); + CRegexpT(const CHART * pattern, int length, int flags); + void Compile(const CHART * pattern, int flags = 0); + void Compile(const CHART * pattern, int length, int flags); + +public: + MatchResult MatchExact(const CHART * tstring, CContext * pContext = 0) const; + MatchResult MatchExact(const CHART * tstring, int length, CContext * pContext = 0) const; + MatchResult Match(const CHART * tstring, int start = -1, CContext * pContext = 0) const; + MatchResult Match(const CHART * tstring, int length, int start, CContext * pContext = 0) const; + MatchResult Match(CContext * pContext) const; + CContext * PrepareMatch(const CHART * tstring, int start = -1, CContext * pContext = 0) const; + CContext * PrepareMatch(const CHART * tstring, int length, int start, CContext * pContext = 0) const; + CHART * Replace(const CHART * tstring, const CHART * replaceto, int start = -1, int ntimes = -1, MatchResult * result = 0, CContext * pContext = 0) const; + CHART * Replace(const CHART * tstring, int string_length, const CHART * replaceto, int to_length, int & result_length, int start = -1, int ntimes = -1, MatchResult * result = 0, CContext * pContext = 0) const; + int GetNamedGroupNumber(const CHART * group_name) const; + +public: + static void ReleaseString (CHART * tstring ); + static void ReleaseContext(CContext * pContext); + +public: + CBuilderT m_builder; +}; + +// +// Implementation +// +template CRegexpT :: CRegexpT(const CHART * pattern, int flags) +{ + Compile(pattern, CBufferRefT(pattern).GetSize(), flags); +} + +template CRegexpT :: CRegexpT(const CHART * pattern, int length, int flags) +{ + Compile(pattern, length, flags); +} + +template inline void CRegexpT :: Compile(const CHART * pattern, int flags) +{ + Compile(pattern, CBufferRefT(pattern).GetSize(), flags); +} + +template void CRegexpT :: Compile(const CHART * pattern, int length, int flags) +{ + m_builder.Clear(); + if(pattern != 0) m_builder.Build(CBufferRefT(pattern, length), flags); +} + +template inline MatchResult CRegexpT :: MatchExact(const CHART * tstring, CContext * pContext) const +{ + return MatchExact(tstring, CBufferRefT(tstring).GetSize(), pContext); +} + +template MatchResult CRegexpT :: MatchExact(const CHART * tstring, int length, CContext * pContext) const +{ + if(m_builder.m_pTopElx == 0) + return 0; + + // info + int endpos = 0; + + CContext context; + if(pContext == 0) pContext = &context; + + pContext->m_stack.Restore(0); + pContext->m_capturestack.Restore(0); + pContext->m_captureindex.Restore(0); + + pContext->m_nParenZindex = 0; + pContext->m_nLastBeginPos = -1; + pContext->m_pMatchString = (void*)tstring; + pContext->m_pMatchStringLength = length; + pContext->m_nCursiveLimit = 100; + + if(m_builder.m_nFlags & RIGHTTOLEFT) + { + pContext->m_nBeginPos = length; + pContext->m_nCurrentPos = length; + endpos = 0; + } + else + { + pContext->m_nBeginPos = 0; + pContext->m_nCurrentPos = 0; + endpos = length; + } + + pContext->m_captureindex.Prepare(m_builder.m_nMaxNumber, -1); + pContext->m_captureindex[0] = 0; + pContext->m_capturestack.Push(0); + pContext->m_capturestack.Push(pContext->m_nCurrentPos); + pContext->m_capturestack.Push(-1); + pContext->m_capturestack.Push(-1); + + // match + if( ! m_builder.m_pTopElx->Match( pContext ) ) + return 0; + else + { + while( pContext->m_nCurrentPos != endpos ) + { + if( ! m_builder.m_pTopElx->MatchNext( pContext ) ) + return 0; + else + { + if( pContext->m_nLastBeginPos == pContext->m_nBeginPos && pContext->m_nBeginPos == pContext->m_nCurrentPos ) + return 0; + else + pContext->m_nLastBeginPos = pContext->m_nCurrentPos; + } + } + + // end pos + pContext->m_capturestack[2] = pContext->m_nCurrentPos; + + return MatchResult( pContext, m_builder.m_nMaxNumber ); + } +} + +template MatchResult CRegexpT :: Match(const CHART * tstring, int start, CContext * pContext) const +{ + return Match(tstring, CBufferRefT(tstring).GetSize(), start, pContext); +} + +template MatchResult CRegexpT :: Match(const CHART * tstring, int length, int start, CContext * pContext) const +{ + if(m_builder.m_pTopElx == 0) + return 0; + + CContext context; + if(pContext == 0) pContext = &context; + + PrepareMatch(tstring, length, start, pContext); + + return Match( pContext ); +} + +template MatchResult CRegexpT :: Match(CContext * pContext) const +{ + if(m_builder.m_pTopElx == 0) + return 0; + + int endpos, delta; + + if(m_builder.m_nFlags & RIGHTTOLEFT) + { + endpos = -1; + delta = -1; + } + else + { + endpos = pContext->m_pMatchStringLength + 1; + delta = 1; + } + + while(pContext->m_nCurrentPos != endpos) + { + pContext->m_captureindex.Restore(0); + pContext->m_stack .Restore(0); + pContext->m_capturestack.Restore(0); + + pContext->m_captureindex.Prepare(m_builder.m_nMaxNumber, -1); + pContext->m_captureindex[0] = 0; + pContext->m_capturestack.Push(0); + pContext->m_capturestack.Push(pContext->m_nCurrentPos); + pContext->m_capturestack.Push(-1); + pContext->m_capturestack.Push(-1); + + if( m_builder.m_pTopElx->Match( pContext ) ) + { + pContext->m_capturestack[2] = pContext->m_nCurrentPos; + + // zero width + if( pContext->m_capturestack[1] == pContext->m_nCurrentPos ) + { + pContext->m_nCurrentPos += delta; + } + + // save pos + pContext->m_nLastBeginPos = pContext->m_nBeginPos; + pContext->m_nBeginPos = pContext->m_nCurrentPos; + + // return + return MatchResult( pContext, m_builder.m_nMaxNumber ); + } + else + { + pContext->m_nCurrentPos += delta; + } + } + + return 0; +} + +template inline CContext * CRegexpT :: PrepareMatch(const CHART * tstring, int start, CContext * pContext) const +{ + return PrepareMatch(tstring, CBufferRefT(tstring).GetSize(), start, pContext); +} + +template CContext * CRegexpT :: PrepareMatch(const CHART * tstring, int length, int start, CContext * pContext) const +{ + if(m_builder.m_pTopElx == 0) + return 0; + + if(pContext == 0) pContext = new CContext(); + + pContext->m_nParenZindex = 0; + pContext->m_nLastBeginPos = -1; + pContext->m_pMatchString = (void*)tstring; + pContext->m_pMatchStringLength = length; + pContext->m_nCursiveLimit = 100; + + if(start < 0) + { + if(m_builder.m_nFlags & RIGHTTOLEFT) + { + pContext->m_nBeginPos = length; + pContext->m_nCurrentPos = length; + } + else + { + pContext->m_nBeginPos = 0; + pContext->m_nCurrentPos = 0; + } + } + else + { + if(start > length) start = length + ((m_builder.m_nFlags & RIGHTTOLEFT)?0:1); + + pContext->m_nBeginPos = start; + pContext->m_nCurrentPos = start; + } + + return pContext; +} + +template inline int CRegexpT :: GetNamedGroupNumber(const CHART * group_name) const +{ + return m_builder.GetNamedNumber(group_name); +} + +template CHART * CRegexpT :: Replace(const CHART * tstring, const CHART * replaceto, int start, int ntimes, MatchResult * result, CContext * pContext) const +{ + int result_length = 0; + return Replace(tstring, CBufferRefT(tstring).GetSize(), replaceto, CBufferRefT(replaceto).GetSize(), result_length, start, ntimes, result, pContext); +} + +template CHART * CRegexpT :: Replace(const CHART * tstring, int string_length, const CHART * replaceto, int to_length, int & result_length, int start, int ntimes, MatchResult * remote_result, CContext * oContext) const +{ + if(m_builder.m_pTopElx == 0) return 0; + + // --- compile replace to --- + + CBufferT compiledto; + + static const CHART rtoptn[] = { RCHART('\\'), RCHART('$' ), RCHART('('), RCHART('?'), RCHART(':'), RCHART('[' ), RCHART('$' ), RCHART('&' ), RCHART('`' ), RCHART('\''), RCHART('+'), RCHART('_' ), RCHART('\\'), RCHART('d'), RCHART(']'), RCHART('|'), RCHART('\\'), RCHART('{'), RCHART('.'), RCHART('*'), RCHART('?'), RCHART('\\'), RCHART('}'), RCHART(')' ), RCHART('\0') }; + static CRegexpT rtoreg(rtoptn); + + MatchResult local_result(0), * result = remote_result ? remote_result : & local_result; + + // prepare + CContext * pContext = rtoreg.PrepareMatch(replaceto, to_length, -1, oContext); + int lastIndex = 0, nmatch = 0; + + while( ((*result) = rtoreg.Match(pContext)).IsMatched() ) + { + int delta = result->GetStart() - lastIndex; + if( delta > 0 ) + { + compiledto.Push(lastIndex); + compiledto.Push(delta); + } + + lastIndex = result->GetStart(); + delta = 2; + + switch(replaceto[lastIndex + 1]) + { + case RCHART('$'): + compiledto.Push(lastIndex); + compiledto.Push(1); + break; + + case RCHART('&'): + case RCHART('`'): + case RCHART('\''): + case RCHART('+'): + case RCHART('_'): + compiledto.Push(-1); + compiledto.Push((int)replaceto[lastIndex + 1]); + break; + + case RCHART('{'): + delta = result->GetEnd() - result->GetStart(); + nmatch = m_builder.GetNamedNumber(CBufferRefT (replaceto + (lastIndex + 2), delta - 3)); + + if(nmatch > 0 && nmatch <= m_builder.m_nMaxNumber) + { + compiledto.Push(-2); + compiledto.Push(nmatch); + } + else + { + compiledto.Push(lastIndex); + compiledto.Push(delta); + } + break; + + default: + nmatch = 0; + for(delta=1; delta<=3; delta++) + { + CHART ch = replaceto[lastIndex + delta]; + + if(ch < RCHART('0') || ch > RCHART('9')) + break; + + nmatch = nmatch * 10 + (ch - RCHART('0')); + } + + if(nmatch > m_builder.m_nMaxNumber) + { + while(nmatch > m_builder.m_nMaxNumber) + { + nmatch /= 10; + delta --; + } + + if(nmatch == 0) + { + delta = 1; + } + } + + if(delta == 1) + { + compiledto.Push(lastIndex); + compiledto.Push(1); + } + else + { + compiledto.Push(-2); + compiledto.Push(nmatch); + } + break; + } + + lastIndex += delta; + } + + if(lastIndex < to_length) + { + compiledto.Push(lastIndex); + compiledto.Push(to_length - lastIndex); + } + + int rightleft = m_builder.m_nFlags & RIGHTTOLEFT; + + int tb = rightleft ? compiledto.GetSize() - 2 : 0; + int te = rightleft ? -2 : compiledto.GetSize(); + int ts = rightleft ? -2 : 2; + + // --- compile complete --- + + int beginpos = rightleft ? string_length : 0; + int endpos = rightleft ? 0 : string_length; + + int toIndex0 = 0; + int toIndex1 = 0; + int i, ntime; + + CBufferT buffer; + + // prepare + pContext = PrepareMatch(tstring, string_length, start, pContext); + lastIndex = beginpos; + + // Match + for(ntime = 0; ntimes < 0 || ntime < ntimes; ntime ++) + { + (*result) = Match(pContext); + + if( ! result->IsMatched() ) + break; + + // before + if( rightleft ) + { + int distance = lastIndex - result->GetEnd(); + if( distance ) + { + buffer.Push(tstring + result->GetEnd()); + buffer.Push((const CHART *)distance); + + toIndex1 -= distance; + } + lastIndex = result->GetStart(); + } + else + { + int distance = result->GetStart() - lastIndex; + if( distance ) + { + buffer.Push(tstring + lastIndex); + buffer.Push((const CHART *)distance); + + toIndex1 += distance; + } + lastIndex = result->GetEnd(); + } + + toIndex0 = toIndex1; + + // middle + for(i=tb; i!=te; i+=ts) + { + int off = compiledto[i]; + int len = compiledto[i + 1]; + + const CHART * sub = replaceto + off; + + if( off == -1 ) + { + switch(RCHART(len)) + { + case RCHART('&'): + sub = tstring + result->GetStart(); + len = result->GetEnd() - result->GetStart(); + break; + + case RCHART('`'): + sub = tstring; + len = result->GetStart(); + break; + + case RCHART('\''): + sub = tstring + result->GetEnd(); + len = string_length - result->GetEnd(); + break; + + case RCHART('+'): + for(nmatch = result->MaxGroupNumber(); nmatch >= 0; nmatch --) + { + if(result->GetGroupStart(nmatch) >= 0) break; + } + sub = tstring + result->GetGroupStart(nmatch); + len = result->GetGroupEnd(nmatch) - result->GetGroupStart(nmatch); + break; + + case RCHART('_'): + sub = tstring; + len = string_length; + break; + } + } + else if( off == -2 ) + { + sub = tstring + result->GetGroupStart(len); + len = result->GetGroupEnd(len) - result->GetGroupStart(len); + } + + buffer.Push(sub); + buffer.Push((const CHART *)len); + + toIndex1 += rightleft ? (-len) : len; + } + } + + // after + if(rightleft) + { + if(endpos < lastIndex) + { + buffer.Push(tstring + endpos); + buffer.Push((const CHART *)(lastIndex - endpos)); + } + } + else + { + if(lastIndex < endpos) + { + buffer.Push(tstring + lastIndex); + buffer.Push((const CHART *)(endpos - lastIndex)); + } + } + + if(oContext == 0) ReleaseContext(pContext); + + // join string + result_length = 0; + for(i=0; i result_string; + result_string.Prepare(result_length); + result_string.Restore(0); + + if(rightleft) + { + for(i=buffer.GetSize()-2; i>=0; i-=2) + { + result_string.Append(buffer[i], (int)buffer[i+1]); + } + } + else + { + for(i=0; im_result.Append(result_length, 3); + result->m_result.Append(ntime); + + if(rightleft) + { + result->m_result.Append(result_length - toIndex1); + result->m_result.Append(result_length - toIndex0); + } + else + { + result->m_result.Append(toIndex0); + result->m_result.Append(toIndex1); + } + + return result_string.Detach(); +} + +template inline void CRegexpT :: ReleaseString(CHART * tstring) +{ + if(tstring != 0) free(tstring); +} + +template inline void CRegexpT :: ReleaseContext(CContext * pContext) +{ + if(pContext != 0) delete pContext; +} + +// +// All implementations +// +template CAlternativeElxT :: CAlternativeElxT() +{ +} + +template int CAlternativeElxT :: Match(CContext * pContext) const +{ + if(m_elxlist.GetSize() == 0) + return 1; + + // try all + for(int n = 0; n < m_elxlist.GetSize(); n++) + { + if(m_elxlist[n]->Match(pContext)) + { + pContext->m_stack.Push(n); + return 1; + } + } + + return 0; +} + +template int CAlternativeElxT :: MatchNext(CContext * pContext) const +{ + if(m_elxlist.GetSize() == 0) + return 0; + + int n = 0; + + // recall prev + pContext->m_stack.Pop(n); + + // prev + if(m_elxlist[n]->MatchNext(pContext)) + { + pContext->m_stack.Push(n); + return 1; + } + else + { + // try rest + for(n++; n < m_elxlist.GetSize(); n++) + { + if(m_elxlist[n]->Match(pContext)) + { + pContext->m_stack.Push(n); + return 1; + } + } + + return 0; + } +} + +// assertx.cpp: implementation of the CAssertElx class. +// +template CAssertElxT :: CAssertElxT(ElxInterface * pelx, int byes) +{ + m_pelx = pelx; + m_byes = byes; +} + +template int CAssertElxT :: Match(CContext * pContext) const +{ + int nbegin = pContext->m_nCurrentPos; + int nsize = pContext->m_stack.GetSize(); + int ncsize = pContext->m_capturestack.GetSize(); + int bsucc; + + // match + if( m_byes ) + bsucc = m_pelx->Match(pContext); + else + bsucc = ! m_pelx->Match(pContext); + + // status + pContext->m_stack.Restore(nsize); + pContext->m_nCurrentPos = nbegin; + + if( bsucc ) + pContext->m_stack.Push(ncsize); + else + pContext->m_capturestack.Restore(ncsize); + + return bsucc; +} + +template int CAssertElxT :: MatchNext(CContext * pContext) const +{ + int ncsize = 0; + + pContext->m_stack.Pop(ncsize); + pContext->m_capturestack.Restore(ncsize); + + return 0; +} + +// emptyelx.cpp: implementation of the CEmptyElx class. +// +template CEmptyElxT :: CEmptyElxT() +{ +} + +template int CEmptyElxT :: Match(CContext *) const +{ + return 1; +} + +template int CEmptyElxT :: MatchNext(CContext *) const +{ + return 0; +} + +// globalx.cpp: implementation of the CGlobalElx class. +// +template CGlobalElxT ::CGlobalElxT() +{ +} + +template int CGlobalElxT :: Match(CContext * pContext) const +{ + return pContext->m_nCurrentPos == pContext->m_nBeginPos; +} + +template int CGlobalElxT :: MatchNext(CContext *) const +{ + return 0; +} + +// greedelx.cpp: implementation of the CGreedyElx class. +// +template CGreedyElxT :: CGreedyElxT(ElxInterface * pelx, int nmin, int nmax) : CRepeatElxT (pelx, nmin) +{ + m_nvart = nmax - nmin; +} + +template int CGreedyElxT :: Match(CContext * pContext) const +{ + if( ! CRepeatElxT :: MatchFixed(pContext) ) + return 0; + + while( ! MatchVart(pContext) ) + { + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + } + + return 1; +} + +template int CGreedyElxT :: MatchNext(CContext * pContext) const +{ + if( MatchNextVart(pContext) ) + return 1; + + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + + while( ! MatchVart(pContext) ) + { + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + } + + return 1; +} + +template int CGreedyElxT :: MatchVart(CContext * pContext) const +{ + int n = 0; + int nbegin00 = pContext->m_nCurrentPos; + int nsize = pContext->m_stack.GetSize(); + int ncsize = pContext->m_capturestack.GetSize(); + + while(n < m_nvart && CRepeatElx::MatchForward(pContext)) + { + n ++; + } + + pContext->m_stack.Push(ncsize); + pContext->m_stack.Push(nsize); + pContext->m_stack.Push(pContext->m_nCurrentPos); + pContext->m_stack.Push(1); + pContext->m_stack.Push(nbegin00); + pContext->m_stack.Push(n); + + return 1; +} + +template int CGreedyElxT :: MatchNextVart(CContext * pContext) const +{ + int n, nbegin00, nsize, ncsize; + CSortedBufferT nbegin99; + pContext->m_stack.Pop(n); + pContext->m_stack.Pop(nbegin00); + pContext->m_stack.Pop(nbegin99); + pContext->m_stack.Pop(nsize); + pContext->m_stack.Pop(ncsize); + + if(n == 0) return 0; + + int n0 = n; + + if( ! CRepeatElxT::m_pelx->MatchNext(pContext) ) + { + n --; + } + + // not to re-match + else if(pContext->m_nCurrentPos == nbegin00) + { + pContext->m_stack.Restore(nsize); + pContext->m_capturestack.Restore(ncsize); + pContext->m_nCurrentPos = nbegin00; + + return 0; + } + + // fix 2012-10-26, thanks to chenlx01@sohu.com + else + { + CContextShot shot(pContext); + + while(n < m_nvart && CRepeatElx::MatchForward(pContext)) + { + n ++; + } + + if(nbegin99.Find(pContext->m_nCurrentPos) >= 0) + { + shot.Restore(pContext); + n = n0; + } + else + { + nbegin99.Add(pContext->m_nCurrentPos); + } + } + + pContext->m_stack.Push(ncsize); + pContext->m_stack.Push(nsize); + pContext->m_stack.Push(nbegin99); + pContext->m_stack.Push(nbegin00); + pContext->m_stack.Push(n); + + return 1; +} + +// indepelx.cpp: implementation of the CIndependentElx class. +// +template CIndependentElxT :: CIndependentElxT(ElxInterface * pelx) +{ + m_pelx = pelx; +} + +template int CIndependentElxT :: Match(CContext * pContext) const +{ + int nbegin = pContext->m_nCurrentPos; + int nsize = pContext->m_stack.GetSize(); + int ncsize = pContext->m_capturestack.GetSize(); + + // match + int bsucc = m_pelx->Match(pContext); + + // status + pContext->m_stack.Restore(nsize); + + if( bsucc ) + { + pContext->m_stack.Push(nbegin); + pContext->m_stack.Push(ncsize); + } + + return bsucc; +} + +template int CIndependentElxT :: MatchNext(CContext * pContext) const +{ + int nbegin = 0, ncsize = 0; + + pContext->m_stack.Pop(ncsize); + pContext->m_stack.Pop(nbegin); + + pContext->m_capturestack.Restore(ncsize); + pContext->m_nCurrentPos = nbegin; + + return 0; +} + +// listelx.cpp: implementation of the CListElx class. +// +template CListElxT :: CListElxT(int brightleft) +{ + m_brightleft = brightleft; +} + +template int CListElxT :: Match(CContext * pContext) const +{ + if(m_elxlist.GetSize() == 0) + return 1; + + // prepare + int bol = m_brightleft ? m_elxlist.GetSize() : -1; + int stp = m_brightleft ? -1 : 1; + int eol = m_brightleft ? -1 : m_elxlist.GetSize(); + + // from first + int n = bol + stp; + + // match all + while(n != eol) + { + if(m_elxlist[n]->Match(pContext)) + { + n += stp; + } + else + { + n -= stp; + + while(n != bol && ! m_elxlist[n]->MatchNext(pContext)) + n -= stp; + + if(n != bol) + n += stp; + else + return 0; + } + } + + return 1; +} + +template int CListElxT :: MatchNext(CContext * pContext) const +{ + if(m_elxlist.GetSize() == 0) + return 0; + + // prepare + int bol = m_brightleft ? m_elxlist.GetSize() : -1; + int stp = m_brightleft ? -1 : 1; + int eol = m_brightleft ? -1 : m_elxlist.GetSize(); + + // from last + int n = eol - stp; + + while(n != bol && ! m_elxlist[n]->MatchNext(pContext)) + n -= stp; + + if(n != bol) + n += stp; + else + return 0; + + // match rest + while(n != eol) + { + if(m_elxlist[n]->Match(pContext)) + { + n += stp; + } + else + { + n -= stp; + + while(n != bol && ! m_elxlist[n]->MatchNext(pContext)) + n -= stp; + + if(n != bol) + n += stp; + else + return 0; + } + } + + return 1; +} + +// mresult.cpp: implementation of the MatchResult class. +// +template MatchResultT :: MatchResultT(CContext * pContext, int nMaxNumber) +{ + if(pContext != 0) + { + m_result.Prepare(nMaxNumber * 2 + 3, -1); + + // matched + m_result[0] = 1; + m_result[1] = nMaxNumber; + + for(int n = 0; n <= nMaxNumber; n++) + { + int index = pContext->m_captureindex[n]; + //if( index < 0 ) continue; + if( ! CBracketElxT::CheckCaptureIndex(index, pContext, n) ) continue; + + // check enclosed + int pos1 = pContext->m_capturestack[index + 1]; + int pos2 = pContext->m_capturestack[index + 2]; + + // info + m_result[n*2 + 2] = pos1 < pos2 ? pos1 : pos2; + m_result[n*2 + 3] = pos1 < pos2 ? pos2 : pos1; + } + } +} + +template inline int MatchResultT :: IsMatched() const +{ + return m_result.At(0, 0); +} + +template inline int MatchResultT :: MaxGroupNumber() const +{ + return m_result.At(1, 0); +} + +template inline int MatchResultT :: GetStart() const +{ + return m_result.At(2, -1); +} + +template inline int MatchResultT :: GetEnd() const +{ + return m_result.At(3, -1); +} + +template inline int MatchResultT :: GetGroupStart(int nGroupNumber) const +{ + return m_result.At(2 + nGroupNumber * 2, -1); +} + +template inline int MatchResultT :: GetGroupEnd(int nGroupNumber) const +{ + return m_result.At(2 + nGroupNumber * 2 + 1, -1); +} + +template MatchResultT & MatchResultT :: operator = (const MatchResultT & result) +{ + m_result.Restore(0); + if(result.m_result.GetSize() > 0) m_result.Append(result.m_result.GetBuffer(), result.m_result.GetSize()); + + return *this; +} + +// posselx.cpp: implementation of the CPossessiveElx class. +// +template CPossessiveElxT :: CPossessiveElxT(ElxInterface * pelx, int nmin, int nmax) : CGreedyElxT (pelx, nmin, nmax) +{ +} + +template int CPossessiveElxT :: Match(CContext * pContext) const +{ + int nbegin = pContext->m_nCurrentPos; + int nsize = pContext->m_stack.GetSize(); + int ncsize = pContext->m_capturestack.GetSize(); + int bsucc = 1; + + // match + if( ! CRepeatElxT :: MatchFixed(pContext) ) + { + bsucc = 0; + } + else + { + while( ! CGreedyElxT :: MatchVart(pContext) ) + { + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + { + bsucc = 0; + break; + } + } + } + + // status + pContext->m_stack.Restore(nsize); + + if( bsucc ) + { + pContext->m_stack.Push(nbegin); + pContext->m_stack.Push(ncsize); + } + + return bsucc; +} + +template int CPossessiveElxT :: MatchNext(CContext * pContext) const +{ + int nbegin = 0, ncsize = 0; + + pContext->m_stack.Pop(ncsize); + pContext->m_stack.Pop(nbegin); + + pContext->m_capturestack.Restore(ncsize); + pContext->m_nCurrentPos = nbegin; + + return 0; +} + +// reluctx.cpp: implementation of the CReluctantElx class. +// +template CReluctantElxT :: CReluctantElxT(ElxInterface * pelx, int nmin, int nmax) : CRepeatElxT (pelx, nmin) +{ + m_nvart = nmax - nmin; +} + +template int CReluctantElxT :: Match(CContext * pContext) const +{ + if( ! CRepeatElxT :: MatchFixed(pContext) ) + return 0; + + while( ! MatchVart(pContext) ) + { + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + } + + return 1; +} + +template int CReluctantElxT :: MatchNext(CContext * pContext) const +{ + if( MatchNextVart(pContext) ) + return 1; + + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + + while( ! MatchVart(pContext) ) + { + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + } + + return 1; +} + +template int CReluctantElxT :: MatchVart(CContext * pContext) const +{ + pContext->m_stack.Push(0); + + return 1; +} + +template int CReluctantElxT :: MatchNextVart(CContext * pContext) const +{ + int n = 0, nbegin = pContext->m_nCurrentPos; + + pContext->m_stack.Pop(n); + + if(n < m_nvart && CRepeatElxT :: m_pelx->Match(pContext)) + { + while(pContext->m_nCurrentPos == nbegin) + { + if( ! CRepeatElxT :: m_pelx->MatchNext(pContext) ) break; + } + + if(pContext->m_nCurrentPos != nbegin) + { + n ++; + + pContext->m_stack.Push(nbegin); + pContext->m_stack.Push(n); + + return 1; + } + } + + while(n > 0) + { + pContext->m_stack.Pop(nbegin); + + while( CRepeatElxT :: m_pelx->MatchNext(pContext) ) + { + if(pContext->m_nCurrentPos != nbegin) + { + pContext->m_stack.Push(nbegin); + pContext->m_stack.Push(n); + + return 1; + } + } + + n --; + } + + return 0; +} + +// repeatx.cpp: implementation of the CRepeatElx class. +// +template CRepeatElxT :: CRepeatElxT(ElxInterface * pelx, int ntimes) +{ + m_pelx = pelx; + m_nfixed = ntimes; +} + +template int CRepeatElxT :: Match(CContext * pContext) const +{ + return MatchFixed(pContext); +} + +template int CRepeatElxT :: MatchNext(CContext * pContext) const +{ + return MatchNextFixed(pContext); +} + +template int CRepeatElxT :: MatchFixed(CContext * pContext) const +{ + if(m_nfixed == 0) + return 1; + + int n = 0; + + while(n < m_nfixed) + { + if(m_pelx->Match(pContext)) + { + n ++; + } + else + { + n --; + + while(n >= 0 && ! m_pelx->MatchNext(pContext)) + n --; + + if(n >= 0) + n ++; + else + return 0; + } + } + + return 1; +} + +template int CRepeatElxT :: MatchNextFixed(CContext * pContext) const +{ + if(m_nfixed == 0) + return 0; + + // from last + int n = m_nfixed - 1; + + while(n >= 0 && ! m_pelx->MatchNext(pContext)) + n --; + + if(n >= 0) + n ++; + else + return 0; + + // match rest + while(n < m_nfixed) + { + if(m_pelx->Match(pContext)) + { + n ++; + } + else + { + n --; + + while(n >= 0 && ! m_pelx->MatchNext(pContext)) + n --; + + if(n >= 0) + n ++; + else + return 0; + } + } + + return 1; +} + +// Regexp +typedef CRegexpT CRegexpA; +typedef CRegexpT CRegexpW; + +#if defined(_UNICODE) || defined(UNICODE) + typedef CRegexpW CRegexp; +#else + typedef CRegexpA CRegexp; +#endif + +} // namespace deelx + +#endif//__DEELX_REGEXP__H__ diff --git a/src/Dialogs.c b/src/Dialogs.c index c1841ab99..12e2d5fa2 100644 --- a/src/Dialogs.c +++ b/src/Dialogs.c @@ -363,7 +363,7 @@ INT_PTR CALLBACK RunDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam) if (GetOpenFileName(&ofn)) { PathQuoteSpaces(szFile); - if (StringCchLen(szArg2)) + if (StringCchLen(szArg2,COUNTOF(szArg2))) { StringCchCat(szFile,COUNTOF(szFile),L" "); StringCchCat(szFile,COUNTOF(szFile),szArg2); @@ -383,7 +383,7 @@ INT_PTR CALLBACK RunDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam) if (GetDlgItemText(hwnd,IDC_COMMANDLINE,args,MAX_PATH)) if (ExtractFirstArgument(args,args,NULL,MAX_PATH)) - if (StringCchLen(args)) + if (StringCchLenW(args,COUNTOF(args))) bEnableOK = TRUE; EnableWindow(GetDlgItem(hwnd,IDOK),bEnableOK); @@ -410,7 +410,7 @@ INT_PTR CALLBACK RunDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam) bQuickExit = TRUE; } - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { StringCchCopy(wchDirectory,COUNTOF(wchDirectory),szCurFile); PathRemoveFileSpec(wchDirectory); } @@ -644,7 +644,7 @@ BOOL OpenWithDlg(HWND hwnd,LPCWSTR lpstrFile) WCHAR szParam[MAX_PATH] = { L'\0' }; WCHAR wchDirectory[MAX_PATH] = { L'\0' }; - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { StringCchCopy(wchDirectory,COUNTOF(wchDirectory),szCurFile); PathRemoveFileSpec(wchDirectory); } @@ -2365,7 +2365,7 @@ INT_PTR InfoBox(int iType,LPCWSTR lpstrSetting,int uidMessage,...) ib.lpstrMessage = LocalAlloc(LPTR, HUGE_BUFFER * sizeof(WCHAR)); StringCchVPrintfW(ib.lpstrMessage,HUGE_BUFFER,wchFormat,(LPVOID)((PUINT_PTR)&uidMessage + 1)); ib.lpstrSetting = (LPWSTR)lpstrSetting; - ib.bDisableCheckBox = (StringCchLen(szIniFile) == 0 || lstrlen(lpstrSetting) == 0 || iMode == 2) ? TRUE : FALSE; + ib.bDisableCheckBox = (StringCchLenW(szIniFile,COUNTOF(szIniFile)) == 0 || lstrlen(lpstrSetting) == 0 || iMode == 2) ? TRUE : FALSE; if (iType == MBYESNO) idDlg = IDD_INFOBOX2; diff --git a/src/Dlapi.c b/src/Dlapi.c index 461a02d46..9d6c1277f 100644 --- a/src/Dlapi.c +++ b/src/Dlapi.c @@ -875,12 +875,12 @@ BOOL DirList_SelectItem(HWND hwnd,LPCWSTR lpszDisplayName,LPCWSTR lpszFullPath) int i = -1; - if (!lpszFullPath || !StringCchLenN(lpszFullPath,MAX_PATH)) + if (!lpszFullPath || !StringCchLen(lpszFullPath,MAX_PATH)) return(FALSE); else GetShortPathName(lpszFullPath,szShortPath,MAX_PATH); - if (!lpszDisplayName || !StringCchLenN(lpszDisplayName,MAX_PATH)) + if (!lpszDisplayName || !StringCchLen(lpszDisplayName,MAX_PATH)) SHGetFileInfo(lpszFullPath,0,&shfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME); else StringCchCopyN(shfi.szDisplayName,COUNTOF(shfi.szDisplayName),lpszDisplayName,MAX_PATH); @@ -896,7 +896,7 @@ BOOL DirList_SelectItem(HWND hwnd,LPCWSTR lpszDisplayName,LPCWSTR lpszFullPath) DirList_GetItem(hwnd,i,&dli); GetShortPathName(dli.szFileName,dli.szFileName,MAX_PATH); - if (!StringCchCompareI(dli.szFileName,szShortPath)) + if (!StringCchCompareIN(dli.szFileName,COUNTOF(dli.szFileName),szShortPath,COUNTOF(szShortPath))) { ListView_SetItemState(hwnd,i,LVIS_FLAGS,LVIS_FLAGS); ListView_EnsureVisible(hwnd,i,FALSE); @@ -928,7 +928,7 @@ void DirList_CreateFilter(PDL_FILTER pdlf,LPCWSTR lpszFileSpec, StringCchCopyN(pdlf->tFilterBuf,COUNTOF(pdlf->tFilterBuf),lpszFileSpec,DL_FILTER_BUFSIZE); pdlf->bExcludeFilter = bExcludeFilter; - if (!StringCchCompareX(lpszFileSpec,L"*.*") || !StringCchLenN(lpszFileSpec,DL_FILTER_BUFSIZE)) + if (!StringCchCompareX(lpszFileSpec,L"*.*") || !StringCchLen(lpszFileSpec,DL_FILTER_BUFSIZE)) return; pdlf->nCount = 1; diff --git a/src/Edit.c b/src/Edit.c index 13802a50d..39fc591a1 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -234,7 +234,7 @@ void EditInitWordDelimiter(HWND hwnd) IniGetString(L"Settings2",L"ExtendedWhiteSpaceChars",L"",buffer,COUNTOF(buffer)); char whitesp[DELIM_BUFFER] = { '\0' }; - if (StringCchLen(buffer) > 0) { + if (StringCchLen(buffer,COUNTOF(buffer)) > 0) { WideCharToMultiByteStrg(CP_ACP, buffer, whitesp); } @@ -1680,7 +1680,7 @@ void EditChar2Hex(HWND hwnd) { } SendMessage(hwnd,SCI_REPLACESEL,0,(LPARAM)ch); - SendMessage(hwnd,SCI_SETSEL,iSelStart,iSelStart+ StringCchLenA(ch)); + SendMessage(hwnd,SCI_SETSEL,iSelStart,iSelStart + StringCchLenA(ch,COUNTOF(ch))); } } else @@ -1777,7 +1777,7 @@ void EditModifyNumber(HWND hwnd,BOOL bIncrease) { return; if (!StrChrIA(chNumber, 'x') && sscanf_s(chNumber, "%d", &iNumber) == 1) { - iWidth = StringCchLenA(chNumber); + iWidth = StringCchLenA(chNumber,COUNTOF(chNumber)); if (iNumber >= 0) { if (bIncrease && iNumber < INT_MAX) iNumber++; @@ -1786,19 +1786,19 @@ void EditModifyNumber(HWND hwnd,BOOL bIncrease) { StringCchPrintfA(chFormat,COUNTOF(chFormat),"%%0%ii",iWidth); StringCchPrintfA(chNumber,COUNTOF(chNumber),chFormat,iNumber); SendMessage(hwnd,SCI_REPLACESEL,0,(LPARAM)chNumber); - SendMessage(hwnd,SCI_SETSEL,iSelStart,iSelStart+StringCchLenA(chNumber)); + SendMessage(hwnd,SCI_SETSEL,iSelStart,iSelStart + StringCchLenA(chNumber,COUNTOF(chNumber))); } } else if (sscanf_s(chNumber, "%x", &iNumber) == 1) { int i; BOOL bUppercase = FALSE; - iWidth = StringCchLenA(chNumber) - 2; + iWidth = StringCchLenA(chNumber,COUNTOF(chNumber)) - 2; if (iNumber >= 0) { if (bIncrease && iNumber < INT_MAX) iNumber++; if (!bIncrease && iNumber > 0) iNumber--; - for (i = StringCchLenA(chNumber) -1 ; i >= 0; i--) { + for (i = StringCchLenA(chNumber,COUNTOF(chNumber)) -1 ; i >= 0; i--) { if (IsCharLowerA(chNumber[i])) break; else if (IsCharUpper(chNumber[i])) { @@ -1812,7 +1812,7 @@ void EditModifyNumber(HWND hwnd,BOOL bIncrease) { StringCchPrintfA(chFormat,COUNTOF(chFormat),"%%#0%ix",iWidth); StringCchPrintfA(chNumber,COUNTOF(chNumber),chFormat,iNumber); SendMessage(hwnd,SCI_REPLACESEL,0,(LPARAM)chNumber); - SendMessage(hwnd,SCI_SETSEL,iSelStart,iSelStart+StringCchLenA(chNumber)); + SendMessage(hwnd,SCI_SETSEL,iSelStart,iSelStart+StringCchLenA(chNumber,COUNTOF(chNumber))); } } } @@ -2362,7 +2362,7 @@ void EditModifyLines(HWND hwnd,LPCWSTR pwszPrefix,LPCWSTR pwszAppend) iLineEnd--; } - if (StringCchLenA(mszPrefix1)) { + if (StringCchLenA(mszPrefix1,COUNTOF(mszPrefix1))) { p = StrStrA(mszPrefix1, "$("); while (!bPrefixNum && p) { @@ -2431,7 +2431,7 @@ void EditModifyLines(HWND hwnd,LPCWSTR pwszPrefix,LPCWSTR pwszAppend) } } - if (StringCchLenA(mszAppend1)) { + if (StringCchLenA(mszAppend1,COUNTOF(mszAppend1))) { p = StrStrA(mszAppend1, "$("); while (!bAppendNum && p) { @@ -2523,7 +2523,7 @@ void EditModifyLines(HWND hwnd,LPCWSTR pwszPrefix,LPCWSTR pwszAppend) iPos = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine,0); SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iPos,0); SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)iPos,0); - SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(mszInsert),(LPARAM)mszInsert); + SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(mszInsert,COUNTOF(mszInsert)),(LPARAM)mszInsert); } if (lstrlen(pwszAppend)) { @@ -2543,7 +2543,7 @@ void EditModifyLines(HWND hwnd,LPCWSTR pwszPrefix,LPCWSTR pwszAppend) iPos = (int)SendMessage(hwnd,SCI_GETLINEENDPOSITION,(WPARAM)iLine,0); SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iPos,0); SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)iPos,0); - SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(mszInsert),(LPARAM)mszInsert); + SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(mszInsert,COUNTOF(mszInsert)),(LPARAM)mszInsert); } } SendMessage(hwnd,SCI_ENDUNDOACTION,0,0); @@ -2738,7 +2738,7 @@ void EditAlignText(HWND hwnd,int nMode) *p++ = L' '; *p = 0; } - StringCchCat(p,(length - StringCchLen(wchNewLineBuf)),pWords[i]); + StringCchCat(p,(length - StringCchLenW(wchNewLineBuf,COUNTOF(wchNewLineBuf))),pWords[i]); p = StrEnd(p); } @@ -2748,7 +2748,7 @@ void EditAlignText(HWND hwnd,int nMode) SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iPos,0); iPos = (int)SendMessage(hwnd,SCI_GETLINEENDPOSITION,(WPARAM)iLine,0); SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)iPos,0); - SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(tchLineBuf),(LPARAM)tchLineBuf); + SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(tchLineBuf,COUNTOF(tchLineBuf)),(LPARAM)tchLineBuf); SendMessage(hwnd,SCI_SETLINEINDENTATION,(WPARAM)iLine,(LPARAM)iMinIndent); } @@ -2764,7 +2764,7 @@ void EditAlignText(HWND hwnd,int nMode) for (i = 1; i < iWords; i++) { *p++ = L' '; *p = 0; - StringCchCat(p,(COUNTOF(wchNewLineBuf) - StringCchLen(wchNewLineBuf)),pWords[i]); + StringCchCat(p,(COUNTOF(wchNewLineBuf) - StringCchLenW(wchNewLineBuf,COUNTOF(wchNewLineBuf))),pWords[i]); p = StrEnd(p); } @@ -2774,7 +2774,7 @@ void EditAlignText(HWND hwnd,int nMode) SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iPos,0); iPos = (int)SendMessage(hwnd,SCI_GETLINEENDPOSITION,(WPARAM)iLine,0); SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)iPos,0); - SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(tchLineBuf),(LPARAM)tchLineBuf); + SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(tchLineBuf,COUNTOF(tchLineBuf)),(LPARAM)tchLineBuf); SendMessage(hwnd,SCI_SETLINEINDENTATION,(WPARAM)iLine,(LPARAM)iMinIndent); } @@ -2800,11 +2800,11 @@ void EditAlignText(HWND hwnd,int nMode) *p = 0; } for (i = 0; i < iWords; i++) { - StringCchCat(p,(COUNTOF(wchNewLineBuf) - StringCchLen(wchNewLineBuf)),pWords[i]); + StringCchCat(p,(COUNTOF(wchNewLineBuf) - StringCchLenW(wchNewLineBuf,COUNTOF(wchNewLineBuf))),pWords[i]); if (i < iWords - 1) - StringCchCat(p,(COUNTOF(wchNewLineBuf) - StringCchLen(wchNewLineBuf)),L" "); + StringCchCat(p,(COUNTOF(wchNewLineBuf) - StringCchLenW(wchNewLineBuf,COUNTOF(wchNewLineBuf))),L" "); if (nMode == ALIGN_CENTER && iWords > 1 && iOddSpaces > 0 && i + 1 >= iWords / 2) { - StringCchCat(p,(COUNTOF(wchNewLineBuf) - StringCchLen(wchNewLineBuf)),L" "); + StringCchCat(p,(COUNTOF(wchNewLineBuf) - StringCchLenW(wchNewLineBuf,COUNTOF(wchNewLineBuf))),L" "); iOddSpaces--; } p = StrEnd(p); @@ -2821,7 +2821,7 @@ void EditAlignText(HWND hwnd,int nMode) SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iPos,0); iPos = (int)SendMessage(hwnd,SCI_GETLINEENDPOSITION,(WPARAM)iLine,0); SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)iPos,0); - SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(tchLineBuf),(LPARAM)tchLineBuf); + SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(tchLineBuf,COUNTOF(tchLineBuf)),(LPARAM)tchLineBuf); if (nMode == ALIGN_LEFT) SendMessage(hwnd,SCI_SETLINEINDENTATION,(WPARAM)iLine,(LPARAM)iMinIndent); @@ -2875,34 +2875,34 @@ void EditEncloseSelection(HWND hwnd,LPCWSTR pwszOpen,LPCWSTR pwszClose) SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0); - if (StringCchLenA(mszOpen)) { + if (StringCchLenA(mszOpen,COUNTOF(mszOpen))) { SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iSelStart,0); SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)iSelStart,0); - SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(mszOpen),(LPARAM)mszOpen); + SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(mszOpen,COUNTOF(mszOpen)),(LPARAM)mszOpen); } - if (StringCchLenA(mszClose)) { - SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iSelEnd + StringCchLenA(mszOpen),0); - SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)iSelEnd + StringCchLenA(mszOpen),0); - SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(mszClose),(LPARAM)mszClose); + if (StringCchLenA(mszClose,COUNTOF(mszClose))) { + SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iSelEnd + StringCchLenA(mszOpen,COUNTOF(mszOpen)),0); + SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)iSelEnd + StringCchLenA(mszOpen,COUNTOF(mszOpen)),0); + SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(mszClose,COUNTOF(mszClose)),(LPARAM)mszClose); } SendMessage(hwnd,SCI_ENDUNDOACTION,0,0); // Fix selection if (iSelStart == iSelEnd) - SendMessage(hwnd,SCI_SETSEL,(WPARAM)iSelStart + StringCchLenA(mszOpen),(WPARAM)iSelStart + StringCchLenA(mszOpen)); + SendMessage(hwnd,SCI_SETSEL,(WPARAM)iSelStart + StringCchLenA(mszOpen,COUNTOF(mszOpen)),(WPARAM)iSelStart + StringCchLenA(mszOpen,COUNTOF(mszOpen))); else { int iCurPos = (int)SendMessage(hwnd,SCI_GETCURRENTPOS,0,0); int iAnchorPos = (int)SendMessage(hwnd,SCI_GETANCHOR,0,0); if (iCurPos < iAnchorPos) { - iCurPos = iSelStart + StringCchLenA(mszOpen); - iAnchorPos = iSelEnd + StringCchLenA(mszOpen); + iCurPos = iSelStart + StringCchLenA(mszOpen,COUNTOF(mszOpen)); + iAnchorPos = iSelEnd + StringCchLenA(mszOpen,COUNTOF(mszOpen)); } else { - iAnchorPos = iSelStart + StringCchLenA(mszOpen); - iCurPos = iSelEnd + StringCchLenA(mszOpen); + iAnchorPos = iSelStart + StringCchLenA(mszOpen,COUNTOF(mszOpen)); + iCurPos = iSelEnd + StringCchLenA(mszOpen,COUNTOF(mszOpen)); } SendMessage(hwnd,SCI_SETSEL,(WPARAM)iAnchorPos,(LPARAM)iCurPos); } @@ -2931,7 +2931,7 @@ void EditToggleLineComments(HWND hwnd,LPCWSTR pwszComment,BOOL bInsertAtStart) if (lstrlen(pwszComment)) WideCharToMultiByte(mbcp,0,pwszComment,-1,mszComment,COUNTOF(mszComment),NULL,NULL); - cchComment = StringCchLenA(mszComment); + cchComment = StringCchLenA(mszComment,COUNTOF(mszComment)); if (SC_SEL_RECTANGLE != SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0) && cchComment) { @@ -4081,17 +4081,17 @@ void EditSortLines(HWND hwnd,int iSortFlags) if (!bIsRectangular) { if (iAnchorPos > iCurPos) { iCurPos = iSelStart; - iAnchorPos = iSelStart + _StringCchLenNA(pmszResult,lenRes); + iAnchorPos = iSelStart + StringCchLenA(pmszResult,lenRes); } else { iAnchorPos = iSelStart; - iCurPos = iSelStart + _StringCchLenNA(pmszResult,lenRes); + iCurPos = iSelStart + StringCchLenA(pmszResult,lenRes); } } SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLineStart,0),0); SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLineEnd+1,0),0); - SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)_StringCchLenNA(pmszResult,lenRes),(LPARAM)pmszResult); + SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)StringCchLenA(pmszResult,lenRes),(LPARAM)pmszResult); SendMessage(hwnd,SCI_ENDUNDOACTION,0,0); LocalFree(pmszResult); @@ -4607,13 +4607,13 @@ INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wParam,LPARA if (!bSwitchedFindReplace) { // Save MRUs - if (StringCchLenA(lpefr->szFind)) { + if (StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) { if (GetDlgItemTextA2W(CP_UTF8,hwnd,IDC_FINDTEXT,lpefr->szFindUTF8,COUNTOF(lpefr->szFindUTF8))) { GetDlgItemText(hwnd,IDC_FINDTEXT,tch,COUNTOF(tch)); MRU_Add(mruFind,tch,0,0); } } - if (StringCchLenA(lpefr->szReplace)) { + if (StringCchLenA(lpefr->szReplace,COUNTOF(lpefr->szReplace))) { if (GetDlgItemTextA2W(CP_UTF8,hwnd,IDC_REPLACETEXT,lpefr->szReplaceUTF8,COUNTOF(lpefr->szReplaceUTF8))) { GetDlgItemText(hwnd,IDC_REPLACETEXT,tch,COUNTOF(tch)); MRU_Add(mruReplace,tch,0,0); @@ -4707,8 +4707,8 @@ INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wParam,LPARA case IDC_SWAPSTRG: { - WCHAR wszFind[1024] = { L'\0' }; - WCHAR wszRepl[1024] = { L'\0' }; + WCHAR wszFind[FNDRPL_BUFFER] = { L'\0' }; + WCHAR wszRepl[FNDRPL_BUFFER] = { L'\0' }; GetDlgItemTextW(hwnd, IDC_FINDTEXT, wszFind, COUNTOF(wszFind)); GetDlgItemTextW(hwnd, IDC_REPLACETEXT, wszRepl, COUNTOF(wszRepl)); SetDlgItemTextW(hwnd, IDC_FINDTEXT, wszRepl); @@ -4884,134 +4884,201 @@ void EscapeWildcards(char* szFind2, LPCEDITFINDREPLACE lpefr) } + +//============================================================================= +// +// EditFindInTarget() +// +int __fastcall EditFindInTarget(HWND hwnd, LPCSTR szFind, int length, int flags, int* start, int* end) +{ + SendMessage(hwnd, SCI_SETSEARCHFLAGS, flags, 0); + SendMessage(hwnd, SCI_SETTARGETRANGE, (*start), (*end)); + int iPos = (int)SendMessage(hwnd, SCI_SEARCHINTARGET, length, (LPARAM)szFind); + if (iPos >= 0) { + *start = (int)SendMessage(hwnd, SCI_GETTARGETSTART, 0, 0); + *end = (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0); + } + return iPos; +} + + + //============================================================================= // // EditFindNext() // -BOOL EditFindNext(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL fExtendSelection) -{ +BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { - struct Sci_TextToFind ttf; - int iPos; - int iSelPos, iSelAnchor; - char szFind2[FNDRPL_BUFFER]; + char szFind[FNDRPL_BUFFER]; BOOL bSuppressNotFound = FALSE; - if (!StringCchLenA(lpefr->szFind)) + if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) return /*EditFindReplaceDlg(hwnd,lpefr,FALSE)*/FALSE; - StringCchCopyNA(szFind2,COUNTOF(szFind2),lpefr->szFind,COUNTOF(lpefr->szFind)); + StringCchCopyNA(szFind, COUNTOF(szFind), lpefr->szFind, COUNTOF(lpefr->szFind)); if (lpefr->bTransformBS) - TransformBackslashes(szFind2,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); + TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); - if (StringCchLenA(szFind2) == 0) - { - InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); + int slen = StringCchLenA(szFind, COUNTOF(szFind)); + if (slen == 0) { + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); return FALSE; } - if( lpefr->bWildcardSearch ) EscapeWildcards( szFind2 , lpefr ); + if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); - iSelPos = (int)SendMessage(hwnd,SCI_GETCURRENTPOS,0,0); - iSelAnchor = (int)SendMessage(hwnd,SCI_GETANCHOR,0,0); + int iLength = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - ZeroMemory(&ttf,sizeof(ttf)); + int iSelPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); + int iSelAnchor = (int)SendMessage(hwnd, SCI_GETANCHOR, 0, 0); - ttf.chrg.cpMin = (int)SendMessage(hwnd,SCI_GETSELECTIONEND,0,0); - ttf.chrg.cpMax = (int)SendMessage(hwnd,SCI_GETLENGTH,0,0); - ttf.lpstrText = szFind2; + int start = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); + int end = iLength; - iPos = (int)SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf); + int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); - if (iPos == -1 && ttf.chrg.cpMin > 0 && !lpefr->bNoFindWrap && !fExtendSelection) { - if (IDOK == InfoBox(MBOKCANCEL,L"MsgFindWrap1",IDS_FIND_WRAPFW)) { - ttf.chrg.cpMin = 0; - iPos = (int)SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf); + if (iPos < 0 && start > 0 && !lpefr->bNoFindWrap && !fExtendSelection) { + if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { + end = start; start = 0; + iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); } else bSuppressNotFound = TRUE; } - if (iPos == -1) - { + if (iPos < 0) { // notfound if (!bSuppressNotFound) - InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); return FALSE; } if (!fExtendSelection) - EditSelectEx(hwnd,ttf.chrgText.cpMin,ttf.chrgText.cpMax); + EditSelectEx(hwnd, start, end); else - EditSelectEx(hwnd,min(iSelAnchor,iSelPos),ttf.chrgText.cpMax); + EditSelectEx(hwnd, min(iSelAnchor, iSelPos), end); return TRUE; } +#if 0 //============================================================================= // -// EditFindPrev() +// EditFindNext() // -BOOL EditFindPrev(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL fExtendSelection) -{ +BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { - struct Sci_TextToFind ttf; - int iPos; - int iSelPos, iSelAnchor; - int iLength; - char szFind2[FNDRPL_BUFFER]; + char szFind[FNDRPL_BUFFER]; BOOL bSuppressNotFound = FALSE; - if (!StringCchLenA(lpefr->szFind)) + if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) return /*EditFindReplaceDlg(hwnd,lpefr,FALSE)*/FALSE; - StringCchCopyNA(szFind2,COUNTOF(szFind2),lpefr->szFind,COUNTOF(lpefr->szFind)); + StringCchCopyNA(szFind, COUNTOF(szFind), lpefr->szFind, COUNTOF(lpefr->szFind)); if (lpefr->bTransformBS) - TransformBackslashes(szFind2,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); + TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); - if (StringCchLenA(szFind2) == 0) - { - InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); + if (StringCchLenA(szFind,COUNTOF(szFind)) == 0) { + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); return FALSE; } - if( lpefr->bWildcardSearch ) EscapeWildcards( szFind2 , lpefr ); + if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); - iSelPos = (int)SendMessage(hwnd,SCI_GETCURRENTPOS,0,0); - iSelAnchor = (int)SendMessage(hwnd,SCI_GETANCHOR,0,0); + int iLength = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - ZeroMemory(&ttf,sizeof(ttf)); + int iSelPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); + int iSelAnchor = (int)SendMessage(hwnd, SCI_GETANCHOR, 0, 0); - ttf.chrg.cpMin = max(0,(int)SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0)); - ttf.chrg.cpMax = 0; - ttf.lpstrText = szFind2; + int start = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); + int end = iLength; - iPos = (int)SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf); + int iPos = EditFindInTarget(hwnd, szFind, (int)(lpefr->fuFlags), &start, &end); - iLength = (int)SendMessage(hwnd,SCI_GETLENGTH,0,0); - if (iPos == -1 && ttf.chrg.cpMin < iLength && !lpefr->bNoFindWrap && !fExtendSelection) { - if (IDOK == InfoBox(MBOKCANCEL,L"MsgFindWrap2",IDS_FIND_WRAPRE)) { - ttf.chrg.cpMin = iLength; - iPos = (int)SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf); + if (iPos < 0 && start > 0 && !lpefr->bNoFindWrap && !fExtendSelection) { + if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { + end = start; start = 0; + iPos = EditFindInTarget(hwnd, szFind, (int)(lpefr->fuFlags), &start, &end); } else bSuppressNotFound = TRUE; } - if (iPos == -1) - { + if (iPos < 0) { // notfound if (!bSuppressNotFound) - InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); return FALSE; } if (!fExtendSelection) - EditSelectEx(hwnd,ttf.chrgText.cpMin,ttf.chrgText.cpMax); + EditSelectEx(hwnd, start, end); else - EditSelectEx(hwnd,max(iSelPos,iSelAnchor),ttf.chrgText.cpMin); + EditSelectEx(hwnd, min(iSelAnchor, iSelPos), end); + + return TRUE; + +} +#endif + + + +//============================================================================= +// +// EditFindPrev() +// +BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { + + char szFind[FNDRPL_BUFFER]; + BOOL bSuppressNotFound = FALSE; + + if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) + return /*EditFindReplaceDlg(hwnd,lpefr,FALSE)*/FALSE; + + StringCchCopyNA(szFind, COUNTOF(szFind), lpefr->szFind, COUNTOF(lpefr->szFind)); + if (lpefr->bTransformBS) + TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); + + int slen = StringCchLenA(szFind, COUNTOF(szFind)); + if (slen == 0) { + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); + return FALSE; + } + + if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); + + int iLength = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); + + int iSelPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); + int iSelAnchor = (int)SendMessage(hwnd, SCI_GETANCHOR, 0, 0); + + int start = max(0, (int)SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0)); + int end = 0; + + int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); + + if (iPos < 0 && start < iLength && !lpefr->bNoFindWrap && !fExtendSelection) { + if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap2", IDS_FIND_WRAPRE)) { + end = start; start = iLength; + iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); + } + else + bSuppressNotFound = TRUE; + } + + if (iPos < 0) { + // notfound + if (!bSuppressNotFound) + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); + return FALSE; + } + + if (!fExtendSelection) + EditSelectEx(hwnd, start, end); + else + EditSelectEx(hwnd, max(iSelPos, iSelAnchor), start); return TRUE; @@ -5022,118 +5089,109 @@ BOOL EditFindPrev(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL fExtendSelection) // // EditReplace() // -BOOL EditReplace(HWND hwnd,LPCEDITFINDREPLACE lpefr) -{ +BOOL EditReplace(HWND hwnd, LPCEDITFINDREPLACE lpefr) { - struct Sci_TextToFind ttf; - int iPos; - int iSelStart; - int iSelEnd; - int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; - char szFind2[FNDRPL_BUFFER]; - char *pszReplace2; + char szFind[FNDRPL_BUFFER]; + char *pszReplace; // replace text of arbitrary size BOOL bSuppressNotFound = FALSE; - if (!StringCchLenA(lpefr->szFind)) + + if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) return /*EditFindReplaceDlg(hwnd,lpefr,TRUE)*/FALSE; - StringCchCopyNA(szFind2,COUNTOF(szFind2),lpefr->szFind,COUNTOF(lpefr->szFind)); + StringCchCopyNA(szFind, COUNTOF(szFind), lpefr->szFind, COUNTOF(lpefr->szFind)); if (lpefr->bTransformBS) - TransformBackslashes(szFind2,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); + TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); - if (StringCchLenA(szFind2) == 0) - { - InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); + int slen = StringCchLenA(szFind, COUNTOF(szFind)); + if (slen == 0) { + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); return FALSE; } - if( lpefr->bWildcardSearch ) EscapeWildcards( szFind2 , lpefr ); + if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); - if (StringCchCompareNA(lpefr->szReplace,FNDRPL_BUFFER,"^c",-1) == 0) { + int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; + if (StringCchCompareNA(lpefr->szReplace, FNDRPL_BUFFER, "^c", -1) == 0) { iReplaceMsg = SCI_REPLACETARGET; - pszReplace2 = EditGetClipboardText(hwnd,TRUE,NULL,NULL); + pszReplace = EditGetClipboardText(hwnd, TRUE, NULL, NULL); } else { - //lstrcpyA(szReplace2,lpefr->szReplace); - pszReplace2 = StrDupA(lpefr->szReplace); - if (!pszReplace2) - pszReplace2 = StrDupA(""); + pszReplace = StrDupA(lpefr->szReplace); + if (!pszReplace) + pszReplace = StrDupA(""); if (lpefr->bTransformBS) - TransformBackslashes(pszReplace2,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); + TransformBackslashes(pszReplace, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); } - if (!pszReplace2) - return FALSE; // recoding canceled + if (!pszReplace) + return FALSE; // recoding of clipboard canceled - iSelStart = (int)SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0); - iSelEnd = (int)SendMessage(hwnd,SCI_GETSELECTIONEND,0,0); + int iSelStart = (int)SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0); + int iSelEnd = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); - ZeroMemory(&ttf,sizeof(ttf)); - ttf.chrg.cpMin = (int)SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0); // Start! - ttf.chrg.cpMax = (int)SendMessage(hwnd,SCI_GETLENGTH,0,0); - ttf.lpstrText = szFind2; + int start = iSelStart; + int end = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - iPos = (int)SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf); + int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); - if (iPos == -1 && ttf.chrg.cpMin > 0 && !lpefr->bNoFindWrap) { - if (IDOK == InfoBox(MBOKCANCEL,L"MsgFindWrap1",IDS_FIND_WRAPFW)) { - ttf.chrg.cpMin = 0; - iPos = (int)SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf); + if (iPos < 0 && start > 0 && !lpefr->bNoFindWrap) { + if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { + end = start; start = 0; + iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); } else bSuppressNotFound = TRUE; } - if (iPos == -1) - { + if (iPos < 0) { // notfound if (!bSuppressNotFound) - InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); - LocalFree(pszReplace2); + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); + LocalFree(pszReplace); return FALSE; } - if (iSelStart != ttf.chrgText.cpMin || iSelEnd != ttf.chrgText.cpMax) { - EditSelectEx(hwnd,ttf.chrgText.cpMin,ttf.chrgText.cpMax); - LocalFree(pszReplace2); + if (iSelStart != start || iSelEnd != end) { + EditSelectEx(hwnd, start, end); + LocalFree(pszReplace); return FALSE; } - SendMessage(hwnd,SCI_SETTARGETSTART,ttf.chrgText.cpMin,0); - SendMessage(hwnd,SCI_SETTARGETEND,ttf.chrgText.cpMax,0); - SendMessage(hwnd,iReplaceMsg,(WPARAM)-1,(LPARAM)pszReplace2); + SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); - ttf.chrg.cpMin = (int)SendMessage(hwnd,SCI_GETTARGETEND,0,0); - ttf.chrg.cpMax = (int)SendMessage(hwnd,SCI_GETLENGTH,0,0); + // === goto next find for next replacement === - iPos = (int)SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf); + start = (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0); + end = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); + + iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); bSuppressNotFound = FALSE; - if (iPos == -1 && ttf.chrg.cpMin > 0 && !lpefr->bNoFindWrap) { - if (IDOK == InfoBox(MBOKCANCEL,L"MsgFindWrap1",IDS_FIND_WRAPFW)) { - ttf.chrg.cpMin = 0; - iPos = (int)SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf); + if (iPos < 0 && start > 0 && !lpefr->bNoFindWrap) { + if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { + end = start; start = 0; + iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); } else bSuppressNotFound = TRUE; } - if (iPos != -1) - EditSelectEx(hwnd,ttf.chrgText.cpMin,ttf.chrgText.cpMax); - + if (iPos >= 0) { + EditSelectEx(hwnd, start, end); + } else { - EditSelectEx(hwnd, - (int)SendMessage(hwnd,SCI_GETTARGETEND,0,0), - (int)SendMessage(hwnd,SCI_GETTARGETEND,0,0)); + EditSelectEx(hwnd, end, end); if (!bSuppressNotFound) - InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); } - LocalFree(pszReplace2); + LocalFree(pszReplace); return TRUE; } + //============================================================================= // // CompleteWord() @@ -5184,7 +5242,7 @@ void CompleteWord(HWND hwnd, BOOL autoInsert) pRoot = LocalAlloc(LPTR,cnt+1); StringCchCopyNA(pRoot,cnt+1,pLine + iStartWordPos,cnt); LocalFree(pLine); - iRootLen = _StringCchLenNA(pRoot,cnt+1); + iRootLen = StringCchLenA(pRoot,cnt+1); iDocLen = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); @@ -5238,7 +5296,7 @@ void CompleteWord(HWND hwnd, BOOL autoInsert) } iNumWords++; - iWListSize += _StringCchLenNA(pWord,wordLength + 1) + 1; + iWListSize += StringCchLenA(pWord,wordLength + 1) + 1; } LocalFree(pWord); } @@ -5441,7 +5499,7 @@ BOOL EditReplaceAll(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo) BOOL bRegexStartOfLine; BOOL bRegexStartOrEndOfLine; - if (!StringCchLenA(lpefr->szFind)) + if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) return /*EditFindReplaceDlg(hwnd,lpefr,TRUE)*/FALSE; // Show wait cursor... @@ -5451,7 +5509,7 @@ BOOL EditReplaceAll(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo) if (lpefr->bTransformBS) TransformBackslashes(szFind2,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); - if (StringCchLenA(szFind2) == 0) + if (StringCchLenA(szFind2,COUNTOF(szFind2)) == 0) { InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); return FALSE; @@ -5572,7 +5630,7 @@ BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo return FALSE; } - if (!StringCchLenA(lpefr->szFind)) + if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) return /*EditFindReplaceDlg(hwnd,lpefr,TRUE)*/FALSE; // Show wait cursor... @@ -5582,7 +5640,7 @@ BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo if (lpefr->bTransformBS) TransformBackslashes(szFind2,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); - if (StringCchLenA(szFind2) == 0) + if (StringCchLenA(szFind2,COUNTOF(szFind2)) == 0) { InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); return FALSE; @@ -6195,7 +6253,7 @@ INT_PTR CALLBACK EditInsertTagDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM l BOOL bClear = TRUE; GetDlgItemTextW(hwnd,100,wchBuf,256); - if (StringCchLen(wchBuf) >= 3) { + if (StringCchLenW(wchBuf,COUNTOF(wchBuf)) >= 3) { if (wchBuf[0] == L'<') { @@ -6766,7 +6824,7 @@ BOOL FileVars_IsUTF8(LPFILEVARS lpfv) { // BOOL FileVars_IsNonUTF8(LPFILEVARS lpfv) { if (lpfv->mask & FV_ENCODING) { - if (StringCchLenA(lpfv->tchEncoding) && + if (StringCchLenA(lpfv->tchEncoding,COUNTOF(lpfv->tchEncoding)) && StringCchCompareINA(lpfv->tchEncoding,COUNTOF(lpfv->tchEncoding),"utf-8",-1) != 0 && StringCchCompareINA(lpfv->tchEncoding,COUNTOF(lpfv->tchEncoding),"utf8",-1) != 0) return(TRUE); diff --git a/src/Helpers.c b/src/Helpers.c index 3fbed2cad..2c4cd6247 100644 --- a/src/Helpers.c +++ b/src/Helpers.c @@ -94,19 +94,19 @@ int IniSectionGetString( if (p) { StringCchCopy(tch,COUNTOF(tch),lpName); StringCchCat(tch,COUNTOF(tch),L"="); - ich = StringCchLen(tch); + ich = StringCchLenW(tch,COUNTOF(tch)); while (*p) { if (StrCmpNI(p,tch,ich) == 0) { StringCchCopyN(lpReturnedString,cchReturnedString,p + ich,cchReturnedString); - return(StringCchLenN(lpReturnedString,cchReturnedString)); + return(StringCchLen(lpReturnedString,cchReturnedString)); } else p = StrEnd(p) + 1; } } StringCchCopyN(lpReturnedString,cchReturnedString,lpDefault,cchReturnedString); - return(StringCchLenN(lpReturnedString,cchReturnedString)); + return(StringCchLen(lpReturnedString,cchReturnedString)); } @@ -123,7 +123,7 @@ int IniSectionGetInt( if (p) { StringCchCopy(tch,COUNTOF(tch),lpName); StringCchCat(tch,COUNTOF(tch),L"="); - ich = StringCchLen(tch); + ich = StringCchLenW(tch,COUNTOF(tch)); while (*p) { if (StrCmpNI(p,tch,ich) == 0) { @@ -152,7 +152,7 @@ UINT IniSectionGetUInt( if (p) { StringCchCopy(tch,COUNTOF(tch),lpName); StringCchCat(tch,COUNTOF(tch),L"="); - ich = StringCchLen(tch); + ich = StringCchLenW(tch,COUNTOF(tch)); while (*p) { if (StrCmpNI(p, tch, ich) == 0) { @@ -494,7 +494,7 @@ BOOL SetWindowTitle(HWND hwnd,UINT uIDAppName,BOOL bIsElevated,UINT uIDUntitled, StringCchCat(szTitle,COUNTOF(szTitle),szExcrptQuot); } - else if (StringCchLenN(lpszFile,MAX_PATH)) + else if (StringCchLen(lpszFile,MAX_PATH)) { if (iFormat < 2 && !PathIsRoot(lpszFile)) { @@ -509,7 +509,7 @@ BOOL SetWindowTitle(HWND hwnd,UINT uIDAppName,BOOL bIsElevated,UINT uIDUntitled, StringCchCat(szTitle,COUNTOF(szTitle),szCachedDisplayName); if (iFormat == 1) { WCHAR tchPath[MAX_PATH] = { L'\0' }; - StringCchCopyN(tchPath,COUNTOF(tchPath),lpszFile,StringCchLenN(lpszFile,MAX_PATH)); + StringCchCopyN(tchPath,COUNTOF(tchPath),lpszFile,StringCchLen(lpszFile,MAX_PATH)); PathRemoveFileSpec(tchPath); StringCchCat(szTitle,COUNTOF(szTitle),L" ["); StringCchCat(szTitle,COUNTOF(szTitle),tchPath); @@ -1065,7 +1065,7 @@ int FormatString(LPWSTR lpOutput,int nOutput,UINT uIdFormat,...) LocalFree(p); - return StringCchLenN(lpOutput,nOutput); + return StringCchLen(lpOutput,nOutput); } @@ -1256,7 +1256,7 @@ BOOL PathGetLnkPath(LPCWSTR pszLnkFile,LPWSTR pszResPath,int cchResPath) } // This additional check seems reasonable - if (!StringCchLenN(pszResPath,cchResPath)) + if (!StringCchLen(pszResPath,cchResPath)) bSucceeded = FALSE; if (bSucceeded) { @@ -1329,7 +1329,7 @@ BOOL PathCreateDeskLnk(LPCWSTR pszDocument) BOOL bSucceeded = FALSE; BOOL fMustCopy; - if (!pszDocument || StringCchLenN(pszDocument,MAX_PATH) == 0) + if (!pszDocument || StringCchLen(pszDocument,MAX_PATH) == 0) return TRUE; // init strings @@ -1397,7 +1397,7 @@ BOOL PathCreateFavLnk(LPCWSTR pszName,LPCWSTR pszTarget,LPCWSTR pszDir) IShellLink *psl; BOOL bSucceeded = FALSE; - if (!pszName || StringCchLenN(pszName,MAX_PATH) == 0) + if (!pszName || StringCchLen(pszName,MAX_PATH) == 0) return TRUE; StringCchCopy(tchLnkFileName,COUNTOF(tchLnkFileName),pszDir); @@ -1653,14 +1653,14 @@ DWORD_PTR SHGetFileInfo2(LPCWSTR pszPath,DWORD dwFileAttributes, if (PathFileExists(pszPath)) { DWORD_PTR dw = SHGetFileInfo(pszPath,dwFileAttributes,psfi,cbFileInfo,uFlags); - if (StringCchLen(psfi->szDisplayName) < StringCchLenN(PathFindFileName(pszPath),MAX_PATH)) + if (StringCchLenW(psfi->szDisplayName,COUNTOF(psfi->szDisplayName)) < StringCchLen(PathFindFileName(pszPath),MAX_PATH)) StringCchCat(psfi->szDisplayName,COUNTOF(psfi->szDisplayName),PathFindExtension(pszPath)); return(dw); } else { DWORD_PTR dw = SHGetFileInfo(pszPath,FILE_ATTRIBUTE_NORMAL,psfi,cbFileInfo,uFlags|SHGFI_USEFILEATTRIBUTES); - if (StringCchLen(psfi->szDisplayName) < StringCchLenN(PathFindFileName(pszPath),MAX_PATH)) + if (StringCchLenW(psfi->szDisplayName,COUNTOF(psfi->szDisplayName)) < StringCchLen(PathFindFileName(pszPath),MAX_PATH)) StringCchCat(psfi->szDisplayName,COUNTOF(psfi->szDisplayName),PathFindExtension(pszPath)); return(dw); } @@ -1953,7 +1953,7 @@ int MRU_Enum(LPMRULIST pmru,int iIndex,LPWSTR pszItem,int cchItem) { return(-1); else { StringCchCopyN(pszItem,cchItem,pmru->pszItems[iIndex],cchItem); - return(StringCchLenN(pszItem,cchItem)); + return(StringCchLen(pszItem,cchItem)); } } } @@ -2207,7 +2207,7 @@ DLGTEMPLATE* LoadThemedDialogTemplate(LPCTSTR lpDialogTemplateID,HINSTANCE hInst else pTemplate->style |= DS_SHELLFONT; - cbNew = cbFontAttr + ((StringCchLen(wchFaceName) + 1) * sizeof(WCHAR)); + cbNew = cbFontAttr + ((StringCchLenW(wchFaceName,COUNTOF(wchFaceName)) + 1) * sizeof(WCHAR)); pbNew = (BYTE*)wchFaceName; pb = DialogTemplate_GetFontSizeField(pTemplate); diff --git a/src/Helpers.h b/src/Helpers.h index 330f4697a..3e68c0b66 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -285,51 +285,43 @@ WCHAR* _StrCutIW(WCHAR*,const WCHAR*); #endif //==== StrSafe lstrlen() ======================================================= -inline int _StringCchLenNA(LPCSTR s,size_t n) { size_t len; HRESULT hr = StringCchLengthA(s,n,&len); return (SUCCEEDED(hr) ? (int)len : 0); } -#define StringCchLenA(s) _StringCchLenNA((s),COUNTOF(s)) -inline int _StringCchLenNW(LPCWSTR s,size_t n) { size_t len; HRESULT hr = StringCchLengthW(s,n,&len); return (SUCCEEDED(hr) ? (int)len : 0); } -#define StringCchLenW(s) _StringCchLenNW((s),COUNTOF(s)) +inline int StringCchLenA(LPCSTR s,size_t n) { size_t len; HRESULT hr = StringCchLengthA(s,n,&len); return (SUCCEEDED(hr) ? (int)len : 0); } +inline int StringCchLenW(LPCWSTR s,size_t n) { size_t len; HRESULT hr = StringCchLengthW(s,n,&len); return (SUCCEEDED(hr) ? (int)len : 0); } #if defined(UNICODE) || defined(_UNICODE) -#define StringCchLen(s) _StringCchLenNW((s),COUNTOF(s)) -#define StringCchLenN(s,n) _StringCchLenNW((s),(n)) +#define StringCchLen(s,n) StringCchLenW((s),(n)) #else -#define StringCchLen(s) _StringCchLenNA((s),COUNTOF(s)) -#define StringCchLenN(s,n) _StringCchLenNA((s),(n)) +#define StringCchLen(s,n) StringCchLenA((s),(n)) #endif //==== StrSafe lstrcmp(),lstrcmpi() ============================================= inline int _StringCchCmpNA(PCNZCH s1,int l1,PCNZCH s2,int l2) { - return (CompareStringA(LOCALE_INVARIANT,0,s1,(l1 >= 0 ? _StringCchLenNA(s1,l1) : -1), - s2,(l2 >= 0 ? _StringCchLenNA(s2,l2) : -1)) - CSTR_EQUAL); + return (CompareStringA(LOCALE_INVARIANT,0,s1,(l1 >= 0 ? StringCchLenA(s1,l1) : -1), + s2,(l2 >= 0 ? StringCchLenA(s2,l2) : -1)) - CSTR_EQUAL); } -#define StringCchCompareA(s1,s2) _StringCchCmpNA((s1),COUNTOF(s1),(s2),COUNTOF(s2)) #define StringCchCompareNA(s1,l1,s2,l2) _StringCchCmpNA((s1),(l1),(s2),(l2)) #define StringCchCompareXA(s1,s2) _StringCchCmpNA((s1),-1,(s2),-1) inline int _StringCchCmpINA(PCNZCH s1,int l1,PCNZCH s2,int l2) { - return (CompareStringA(LOCALE_INVARIANT,NORM_IGNORECASE,s1,(l1 >= 0 ? _StringCchLenNA(s1,l1) : -1), - s2,(l2 >= 0 ? _StringCchLenNA(s2,l2) : -1)) - CSTR_EQUAL); + return (CompareStringA(LOCALE_INVARIANT,NORM_IGNORECASE,s1,(l1 >= 0 ? StringCchLenA(s1,l1) : -1), + s2,(l2 >= 0 ? StringCchLenA(s2,l2) : -1)) - CSTR_EQUAL); } -#define StringCchCompareIA(s1,s2) _StringCchCmpINA((s1),COUNTOF(s1),(s2),COUNTOF(s2)) #define StringCchCompareINA(s1,l1,s2,l2) _StringCchCmpINA((s1),(l1),(s2),(l2)) #define StringCchCompareIXA(s1,s2) _StringCchCmpINA((s1),-1,(s2),-1) inline int _StringCchCmpNW(PCNZWCH s1,int l1,PCNZWCH s2,int l2) { - return (CompareStringW(LOCALE_INVARIANT,0,s1,(l1 >= 0 ? _StringCchLenNW(s1,l1) : -1), - s2,(l2 >= 0 ? _StringCchLenNW(s2,l2) : -1)) - CSTR_EQUAL); + return (CompareStringW(LOCALE_INVARIANT,0,s1,(l1 >= 0 ? StringCchLenW(s1,l1) : -1), + s2,(l2 >= 0 ? StringCchLenW(s2,l2) : -1)) - CSTR_EQUAL); } -#define StringCchCompareW(s1,s2) _StringCchCmpNW((s1),COUNTOF(s1),(s2),COUNTOF(s2)) #define StringCchCompareNW(s1,l1,s2,l2) _StringCchCmpNW((s1),(l1),(s2),(l2)) #define StringCchCompareXW(s1,s2) _StringCchCmpNW((s1),-1,(s2),-1) inline int _StringCchCmpINW(PCNZWCH s1,int l1,PCNZWCH s2,int l2) { - return (CompareStringW(LOCALE_INVARIANT,NORM_IGNORECASE,s1,(l1 >= 0 ? _StringCchLenNW(s1,l1) : -1), - s2,(l2 >= 0 ? _StringCchLenNW(s2,l2) : -1)) - CSTR_EQUAL); + return (CompareStringW(LOCALE_INVARIANT,NORM_IGNORECASE,s1,(l1 >= 0 ? StringCchLenW(s1,l1) : -1), + s2,(l2 >= 0 ? StringCchLenW(s2,l2) : -1)) - CSTR_EQUAL); } -#define StringCchCompareIW(s1,s2) _StringCchCmpINW((s1),COUNTOF(s1),(s2),COUNTOF(s2)) #define StringCchCompareINW(s1,l1,s2,l2) _StringCchCmpINW((s1),(l1),(s2),(l2)) #define StringCchCompareIXW(s1,s2) _StringCchCmpINW((s1),-1,(s2),-1) diff --git a/src/Notepad3.c b/src/Notepad3.c index 5c45088ff..c792cb8fa 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -1022,7 +1022,7 @@ HWND InitInstance(HINSTANCE hInstance,LPSTR pszCmdLine,int nCmdShow) WCHAR tchUntitled[32] = { L'\0' }; WCHAR tchPageFmt[32] = { L'\0' }; - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { SHGetFileInfo2(szCurFile, 0, &shfi, sizeof(SHFILEINFO), SHGFI_DISPLAYNAME); pszTitle = shfi.szDisplayName; } @@ -1468,7 +1468,7 @@ void CreateBars(HWND hwnd,HINSTANCE hInstance) // Add normal Toolbar Bitmap hbmp = NULL; - if (StringCchLen(tchToolbarBitmap)) + if (StringCchLenW(tchToolbarBitmap,COUNTOF(tchToolbarBitmap))) { if (!SearchPath(NULL,tchToolbarBitmap,NULL,COUNTOF(szTmp),szTmp,NULL)) StringCchCopy(szTmp,COUNTOF(szTmp),tchToolbarBitmap); @@ -1492,7 +1492,7 @@ void CreateBars(HWND hwnd,HINSTANCE hInstance) // Optionally add hot Toolbar Bitmap hbmp = NULL; - if (StringCchLen(tchToolbarBitmapHot)) + if (StringCchLenW(tchToolbarBitmapHot,COUNTOF(tchToolbarBitmapHot))) { if (!SearchPath(NULL,tchToolbarBitmapHot,NULL,COUNTOF(szTmp),szTmp,NULL)) StringCchCopy(szTmp,COUNTOF(szTmp),tchToolbarBitmapHot); @@ -1510,7 +1510,7 @@ void CreateBars(HWND hwnd,HINSTANCE hInstance) // Optionally add disabled Toolbar Bitmap hbmp = NULL; - if (StringCchLen(tchToolbarBitmapDisabled)) + if (StringCchLenW(tchToolbarBitmapDisabled,COUNTOF(tchToolbarBitmapDisabled))) { if (!SearchPath(NULL,tchToolbarBitmapDisabled,NULL,COUNTOF(szTmp),szTmp,NULL)) StringCchCopy(szTmp,COUNTOF(szTmp),tchToolbarBitmapDisabled); @@ -1643,7 +1643,7 @@ void MsgEndSession(HWND hwnd, UINT umsg) // call SaveSettings() when hwndToolbar is still valid SaveSettings(FALSE); - if (StringCchLen(szIniFile) != 0) { + if (StringCchLenW(szIniFile,COUNTOF(szIniFile)) != 0) { // Cleanup unwanted MRU's if (!bSaveRecentFiles) { @@ -2126,7 +2126,7 @@ void MsgInitMenu(HWND hwnd,WPARAM wParam,LPARAM lParam) int i,i2; HMENU hmenu = (HMENU)wParam; - i = StringCchLen(szCurFile); + i = StringCchLenW(szCurFile,COUNTOF(szCurFile)); EnableCmd(hmenu,IDM_FILE_REVERT,i); EnableCmd(hmenu, CMD_RELOADASCIIASUTF8, i); EnableCmd(hmenu, CMD_RECODEANSI, i); @@ -2351,7 +2351,7 @@ void MsgInitMenu(HWND hwnd,WPARAM wParam,LPARAM lParam) CheckCmd(hmenu,IDM_VIEW_CHANGENOTIFY,iFileWatchingMode); - if (StringCchLen(szTitleExcerpt)) + if (StringCchLenW(szTitleExcerpt,COUNTOF(szTitleExcerpt))) i = IDM_VIEW_SHOWEXCERPT; else if (iPathNameFormat == 0) i = IDM_VIEW_SHOWFILENAMEONLY; @@ -2369,7 +2369,7 @@ void MsgInitMenu(HWND hwnd,WPARAM wParam,LPARAM lParam) i = IDM_VIEW_NOESCFUNC; CheckMenuRadioItem(hmenu,IDM_VIEW_NOESCFUNC,IDM_VIEW_ESCEXIT,i,MF_BYCOMMAND); - i = StringCchLen(szIniFile); + i = StringCchLenW(szIniFile,COUNTOF(szIniFile)); CheckCmd(hmenu,IDM_VIEW_SAVESETTINGS,bSaveSettings && i); EnableCmd(hmenu,IDM_VIEW_REUSEWINDOW,i); @@ -2380,7 +2380,7 @@ void MsgInitMenu(HWND hwnd,WPARAM wParam,LPARAM lParam) EnableCmd(hmenu,IDM_VIEW_NOSAVEFINDREPL,i); EnableCmd(hmenu,IDM_VIEW_SAVESETTINGS,bEnableSaveSettings && i); - i = (StringCchLen(szIniFile) > 0 || StringCchLen(szIniFile2) > 0); + i = (StringCchLenW(szIniFile,COUNTOF(szIniFile)) > 0 || StringCchLenW(szIniFile2,COUNTOF(szIniFile2)) > 0); EnableCmd(hmenu,IDM_VIEW_SAVESETTINGSNOW,bEnableSaveSettings && i); UNUSED(lParam); @@ -2465,7 +2465,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) //SendMessage(hwndEdit,SCI_SETREADONLY,bReadOnly,0); //UpdateToolbar(); //UpdateStatusbar(); - if (StringCchLen(szCurFile)) + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { DWORD dwFileAttributes = GetFileAttributes(szCurFile); if (dwFileAttributes != INVALID_FILE_ATTRIBUTES) { @@ -2514,10 +2514,10 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) } } - if (StringCchLen(tchParam) && StringCchLen(szCurFile)) + if (StringCchLenW(tchParam,COUNTOF(tchParam)) && StringCchLenW(szCurFile,COUNTOF(szCurFile))) StringCchCat(tchParam,COUNTOF(tchParam),L" "); - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { StringCchCopy(tchTemp,COUNTOF(tchTemp),szCurFile); PathQuoteSpaces(tchTemp); StringCchCat(tchParam,COUNTOF(tchParam),tchTemp); @@ -2561,7 +2561,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) StringCchCat(szParameters,COUNTOF(szParameters),tch); StringCchCat(szParameters,COUNTOF(szParameters),L" -f"); - if (StringCchLen(szIniFile)) { + if (StringCchLenW(szIniFile,COUNTOF(szIniFile))) { StringCchCat(szParameters,COUNTOF(szParameters),L" \""); StringCchCat(szParameters,COUNTOF(szParameters),szIniFile); StringCchCat(szParameters,COUNTOF(szParameters),L" \""); @@ -2586,7 +2586,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) StringCchPrintf(tch,COUNTOF(tch),L" -pos %i,%i,%i,%i,%i",wi.x,wi.y,wi.cx,wi.cy,wi.max); StringCchCat(szParameters,COUNTOF(szParameters),tch); - if (LOWORD(wParam) != IDM_FILE_NEWWINDOW2 && StringCchLen(szCurFile)) { + if (LOWORD(wParam) != IDM_FILE_NEWWINDOW2 && StringCchLenW(szCurFile,COUNTOF(szCurFile))) { StringCchCopy(szFileName,COUNTOF(szFileName),szCurFile); PathQuoteSpaces(szFileName); StringCchCat(szParameters,COUNTOF(szParameters),L" "); @@ -2612,13 +2612,13 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) { WCHAR wchDirectory[MAX_PATH] = { L'\0' }; - if (!StringCchLen(szCurFile)) + if (!StringCchLenW(szCurFile,COUNTOF(szCurFile))) break; if (bSaveBeforeRunningTools && !FileSave(FALSE,TRUE,FALSE,FALSE)) break; - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { StringCchCopy(wchDirectory,COUNTOF(wchDirectory),szCurFile); PathRemoveFileSpec(wchDirectory); } @@ -2671,7 +2671,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) WCHAR tchUntitled[32] = { L'\0' }; WCHAR tchPageFmt[32] = { L'\0' }; - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { SHGetFileInfo2(szCurFile,0,&shfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME); pszTitle = shfi.szDisplayName; } @@ -2690,7 +2690,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) case IDM_FILE_PROPERTIES: { - if (StringCchLen(szCurFile) == 0) + if (StringCchLenW(szCurFile,COUNTOF(szCurFile)) == 0) break; SHELLEXECUTEINFO sei; @@ -2707,7 +2707,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) case IDM_FILE_CREATELINK: { - if (!StringCchLen(szCurFile)) + if (!StringCchLenW(szCurFile,COUNTOF(szCurFile))) break; if (!PathCreateDeskLnk(szCurFile)) @@ -2741,7 +2741,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) case IDM_FILE_ADDTOFAV: - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { SHFILEINFO shfi; SHGetFileInfo2(szCurFile,0,&shfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME); AddToFavDlg(hwnd,shfi.szDisplayName,szCurFile); @@ -2806,7 +2806,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) if (EditSetNewEncoding(hwndEdit, iNewEncoding, (flagSetEncoding), - StringCchLen(szCurFile) == 0)) { + StringCchLenW(szCurFile,COUNTOF(szCurFile)) == 0)) { if (SendMessage(hwndEdit,SCI_GETLENGTH,0,0) == 0) { Encoding_Current(iNewEncoding); @@ -2827,7 +2827,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) case IDM_ENCODING_RECODE: { - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { WCHAR tchCurFile2[MAX_PATH] = { L'\0' }; @@ -3508,7 +3508,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) char mszBuf[MAX_PATH*3]; //int iSelStart; - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { if (LOWORD(wParam) == IDM_EDIT_INSERT_FILENAME) { SHGetFileInfo2(szCurFile,0,&shfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME); pszInsert = shfi.szDisplayName; @@ -4441,9 +4441,9 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) BOOL bCreateFailure = FALSE; - if (StringCchLen(szIniFile) == 0) { + if (StringCchLenW(szIniFile,COUNTOF(szIniFile)) == 0) { - if (StringCchLen(szIniFile2) > 0) { + if (StringCchLenW(szIniFile2,COUNTOF(szIniFile2)) > 0) { if (CreateIniFileEx(szIniFile2)) { StringCchCopy(szIniFile,COUNTOF(szIniFile),szIniFile2); StringCchCopy(szIniFile2,COUNTOF(szIniFile2),L""); @@ -4628,7 +4628,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) case CMD_RECODEDEFAULT: { WCHAR tchCurFile2[MAX_PATH] = { L'\0' }; - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { Encoding_Source(Encoding_MapUnicode(iDefaultEncoding)); StringCchCopy(tchCurFile2,COUNTOF(tchCurFile2),szCurFile); FileLoad(FALSE,FALSE,TRUE,TRUE,tchCurFile2); @@ -4640,7 +4640,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) case CMD_RECODEANSI: { WCHAR tchCurFile2[MAX_PATH] = { L'\0' }; - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { Encoding_Source(CPI_ANSI_DEFAULT); StringCchCopy(tchCurFile2,COUNTOF(tchCurFile2),szCurFile); FileLoad(FALSE,FALSE,TRUE,TRUE,tchCurFile2); @@ -4652,7 +4652,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) case CMD_RECODEOEM: { WCHAR tchCurFile2[MAX_PATH] = { L'\0' }; - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { Encoding_Source(CPI_OEM); StringCchCopy(tchCurFile2,COUNTOF(tchCurFile2),szCurFile); FileLoad(FALSE,FALSE,TRUE,TRUE,tchCurFile2); @@ -4665,7 +4665,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) { WCHAR tchCurFile2[MAX_PATH] = { L'\0' }; BOOL _bLoadASCIIasUTF8 = bLoadASCIIasUTF8; - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { bLoadASCIIasUTF8 = 1; StringCchCopy(tchCurFile2,COUNTOF(tchCurFile2),szCurFile); FileLoad(FALSE,FALSE,TRUE,FALSE,tchCurFile2); @@ -4678,7 +4678,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) case CMD_RELOADNOFILEVARS: { WCHAR tchCurFile2[MAX_PATH] = { L'\0' }; - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { int _fNoFileVariables = fNoFileVariables; BOOL _bNoEncodingTags = bNoEncodingTags; fNoFileVariables = 1; @@ -4737,7 +4737,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) StrTrim(wchFind,L" "); StrTrim(wchTemplate,L" "); - if (StringCchLen(wchFind) == 0 || StringCchLen(wchTemplate) == 0) + if (StringCchLenW(wchFind,COUNTOF(wchFind)) == 0 || StringCchLenW(wchTemplate,COUNTOF(wchTemplate)) == 0) break; GetLocalTime(&st); @@ -4801,7 +4801,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) lpsz = StrChrA(mszSelection,9); if (lpsz) *lpsz = '\0'; - if (StringCchLenA(mszSelection)) { + if (StringCchLenA(mszSelection,COUNTOF(mszSelection))) { WCHAR wszSelection[512] = { L'\0' }; UINT uCP = Encoding_SciGetCodePage(hwndEdit); @@ -4815,7 +4815,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) lpszArgs = GlobalAlloc(GPTR,GlobalSize(lpszCommand)); ExtractFirstArgument(lpszCommand,lpszCommand,lpszArgs,cmdsz); - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { StringCchCopy(wchDirectory,COUNTOF(wchDirectory),szCurFile); PathRemoveFileSpec(wchDirectory); } @@ -5019,7 +5019,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) WCHAR *pszCopy; WCHAR tchUntitled[32] = { L'\0' }; - if (StringCchLen(szCurFile)) + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) pszCopy = szCurFile; else { GetString(IDS_UNTITLED,tchUntitled,COUNTOF(tchUntitled)); @@ -5053,7 +5053,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) HANDLE hData; WCHAR *pData; EmptyClipboard(); - int len = StringCchLen(wszWinPos); + int len = StringCchLenW(wszWinPos,COUNTOF(wszWinPos)); hData = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(WCHAR) * (len+1)); pData = GlobalLock(hData); StringCchCopyN(pData,(len+1),wszWinPos,len); @@ -5072,7 +5072,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) case CMD_OPENINIFILE: - if (StringCchLen(szIniFile)) { + if (StringCchLenW(szIniFile,COUNTOF(szIniFile))) { CreateIniFile(); FileLoad(FALSE,FALSE,FALSE,FALSE,szIniFile); } @@ -5974,7 +5974,7 @@ void SaveSettings(BOOL bSaveSettingsNow) { WCHAR wchTmp[MAX_PATH] = { L'\0' }; - if (StringCchLen(szIniFile) == 0) + if (StringCchLenW(szIniFile,COUNTOF(szIniFile)) == 0) return; if (!bEnableSaveSettings) @@ -6196,7 +6196,7 @@ void ParseCommandLine() StringCchCopyN(g_wchAppUserModelID,COUNTOF(g_wchAppUserModelID), lp1 + CSTRLEN(L"appid="),len - CSTRLEN(L"appid=")); StrTrim(g_wchAppUserModelID,L" "); - if (StringCchLen(g_wchAppUserModelID) == 0) + if (StringCchLenW(g_wchAppUserModelID,COUNTOF(g_wchAppUserModelID)) == 0) StringCchCopy(g_wchAppUserModelID,COUNTOF(g_wchAppUserModelID),L"Notepad3"); } @@ -6576,7 +6576,7 @@ void LoadFlags() if (IniSectionGetInt(pIniSection,L"NoFileVariables",0)) fNoFileVariables = 1; - if (StringCchLen(g_wchAppUserModelID) == 0) { + if (StringCchLenW(g_wchAppUserModelID,COUNTOF(g_wchAppUserModelID)) == 0) { IniSectionGetString(pIniSection,L"ShellAppUserModelID",L"Notepad3", g_wchAppUserModelID,COUNTOF(g_wchAppUserModelID)); } @@ -6666,7 +6666,7 @@ int FindIniFile() { WCHAR tchModule[MAX_PATH] = { L'\0' }; GetModuleFileName(NULL,tchModule,COUNTOF(tchModule)); - if (StringCchLen(szIniFile)) { + if (StringCchLenW(szIniFile,COUNTOF(szIniFile))) { if (StringCchCompareIX(szIniFile,L"*?") == 0) return(0); else { @@ -6801,7 +6801,7 @@ void UpdateToolbar() if (!bShowToolbar) return; - EnableTool(IDT_FILE_ADDTOFAV,StringCchLen(szCurFile)); + EnableTool(IDT_FILE_ADDTOFAV,StringCchLenW(szCurFile,COUNTOF(szCurFile))); EnableTool(IDT_EDIT_UNDO,SendMessage(hwndEdit,SCI_CANUNDO,0,0) /*&& !bReadOnly*/); EnableTool(IDT_EDIT_REDO,SendMessage(hwndEdit,SCI_CANREDO,0,0) /*&& !bReadOnly*/); @@ -6982,7 +6982,7 @@ void UpdateLineNumberWidth() void UpdateSettingsCmds() { HMENU hmenu = GetSystemMenu(hwndMain, FALSE); - BOOL hasIniFile = (StringCchLen(szIniFile) > 0 || StringCchLen(szIniFile2) > 0); + BOOL hasIniFile = (StringCchLenW(szIniFile,COUNTOF(szIniFile)) > 0 || StringCchLenW(szIniFile2,COUNTOF(szIniFile2)) > 0); CheckCmd(hmenu, IDM_VIEW_SAVESETTINGS, bSaveSettings && bEnableSaveSettings); EnableCmd(hmenu, IDM_VIEW_SAVESETTINGS, hasIniFile && bEnableSaveSettings); EnableCmd(hmenu, IDM_VIEW_SAVESETTINGSNOW, hasIniFile && bEnableSaveSettings); @@ -7408,7 +7408,7 @@ BOOL FileLoad(BOOL bDontSave,BOOL bNew,BOOL bReload,BOOL bNoEncDetect,LPCWSTR lp } } // consistent settings file handling (if loaded in editor) - bEnableSaveSettings = (StringCchCompareI(szCurFile, szIniFile) == 0) ? FALSE : TRUE; + bEnableSaveSettings = (StringCchCompareINW(szCurFile, COUNTOF(szCurFile), szIniFile, COUNTOF(szIniFile)) == 0) ? FALSE : TRUE; UpdateSettingsCmds(); // Show warning: Unicode file loaded as ANSI @@ -7485,7 +7485,7 @@ BOOL FileSave(BOOL bSaveAlways,BOOL bAsk,BOOL bSaveAs,BOOL bSaveCopy) BOOL bCancelDataLoss = FALSE; BOOL bIsEmptyNewFile = FALSE; - if (StringCchLen(szCurFile) == 0) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile)) == 0) { int cchText = (int)SendMessage(hwndEdit,SCI_GETLENGTH,0,0); if (cchText == 0) bIsEmptyNewFile = TRUE; @@ -7511,7 +7511,7 @@ BOOL FileSave(BOOL bSaveAlways,BOOL bAsk,BOOL bSaveAs,BOOL bSaveCopy) { // File or "Untitled" ... WCHAR tch[MAX_PATH] = { L'\0' }; - if (StringCchLen(szCurFile)) + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) StringCchCopy(tch,COUNTOF(tch),szCurFile); else GetString(IDS_UNTITLED,tch,COUNTOF(tch)); @@ -7525,7 +7525,7 @@ BOOL FileSave(BOOL bSaveAlways,BOOL bAsk,BOOL bSaveAs,BOOL bSaveCopy) } // Read only... - if (!bSaveAs && !bSaveCopy && StringCchLen(szCurFile)) + if (!bSaveAs && !bSaveCopy && StringCchLenW(szCurFile,COUNTOF(szCurFile))) { DWORD dwFileAttributes = GetFileAttributes(szCurFile); if (dwFileAttributes != INVALID_FILE_ATTRIBUTES) @@ -7540,10 +7540,10 @@ BOOL FileSave(BOOL bSaveAlways,BOOL bAsk,BOOL bSaveAs,BOOL bSaveCopy) } // Save As... - if (bSaveAs || bSaveCopy || StringCchLen(szCurFile) == 0) + if (bSaveAs || bSaveCopy || StringCchLenW(szCurFile,COUNTOF(szCurFile)) == 0) { WCHAR tchInitialDir[MAX_PATH] = { L'\0' }; - if (bSaveCopy && StringCchLen(tchLastSaveCopyDir)) { + if (bSaveCopy && StringCchLenW(tchLastSaveCopyDir,COUNTOF(tchLastSaveCopyDir))) { StringCchCopy(tchInitialDir,COUNTOF(tchInitialDir),tchLastSaveCopyDir); StringCchCopy(tchFile,COUNTOF(tchFile),tchLastSaveCopyDir); PathCchAppend(tchFile,COUNTOF(tchFile),PathFindFileName(szCurFile)); @@ -7604,7 +7604,7 @@ BOOL FileSave(BOOL bSaveAlways,BOOL bAsk,BOOL bSaveAs,BOOL bSaveCopy) } else if (!bCancelDataLoss) { - if (StringCchLen(szCurFile) > 0) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile)) > 0) { StringCchCopy(tchFile,COUNTOF(tchFile),szCurFile); StringCchCopy(tchBase,COUNTOF(tchBase),szCurFile); PathStripPath(tchBase); @@ -7631,7 +7631,7 @@ BOOL FileSave(BOOL bSaveAlways,BOOL bAsk,BOOL bSaveAs,BOOL bSaveCopy) WININFO wi = GetMyWindowPlacement(hwndMain,NULL); StringCchPrintf(szArguments,COUNTOF(szArguments), L"/pos %i,%i,%i,%i,%i /tmpfbuf=\"%s\" %s",wi.x,wi.y,wi.cx,wi.cy,wi.max,szTempFileName,lpArgs); - if (StringCchLen(tchFile)) { + if (StringCchLenW(tchFile,COUNTOF(tchFile))) { if (!StrStrI(szArguments,tchBase)) { StringCchPrintf(szArguments,COUNTOF(szArguments),L"%s \"%s\"",szArguments,tchFile); } @@ -7680,11 +7680,11 @@ BOOL OpenFileDlg(HWND hwnd,LPWSTR lpstrFile,int cchFile,LPCWSTR lpstrInitialDir) Style_GetOpenDlgFilterStr(szFilter,COUNTOF(szFilter)); if (!lpstrInitialDir) { - if (StringCchLen(szCurFile)) { + if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { StringCchCopy(tchInitialDir,COUNTOF(tchInitialDir),szCurFile); PathRemoveFileSpec(tchInitialDir); } - else if (StringCchLen(tchDefaultDir)) { + else if (StringCchLenW(tchDefaultDir,COUNTOF(tchDefaultDir))) { ExpandEnvironmentStrings(tchDefaultDir,tchInitialDir,COUNTOF(tchInitialDir)); if (PathIsRelative(tchInitialDir)) { WCHAR tchModule[MAX_PATH] = { L'\0' }; @@ -7708,7 +7708,7 @@ BOOL OpenFileDlg(HWND hwnd,LPWSTR lpstrFile,int cchFile,LPCWSTR lpstrInitialDir) ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | /* OFN_NOCHANGEDIR |*/ OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST | OFN_SHAREAWARE /*| OFN_NODEREFERENCELINKS*/; - ofn.lpstrDefExt = (StringCchLen(tchDefaultExtension)) ? tchDefaultExtension : NULL; + ofn.lpstrDefExt = (StringCchLenW(tchDefaultExtension,COUNTOF(tchDefaultExtension))) ? tchDefaultExtension : NULL; if (GetOpenFileName(&ofn)) { StringCchCopyN(lpstrFile,cchFile,szFile,COUNTOF(szFile)); @@ -7737,11 +7737,11 @@ BOOL SaveFileDlg(HWND hwnd,LPWSTR lpstrFile,int cchFile,LPCWSTR lpstrInitialDir) if (lstrlen(lpstrInitialDir)) StringCchCopy(tchInitialDir,COUNTOF(tchInitialDir),lpstrInitialDir); - else if (StringCchLen(szCurFile)) { + else if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { StringCchCopy(tchInitialDir,COUNTOF(tchInitialDir),szCurFile); PathRemoveFileSpec(tchInitialDir); } - else if (StringCchLen(tchDefaultDir)) { + else if (StringCchLenW(tchDefaultDir,COUNTOF(tchDefaultDir))) { ExpandEnvironmentStrings(tchDefaultDir,tchInitialDir,COUNTOF(tchInitialDir)); if (PathIsRelative(tchInitialDir)) { WCHAR tchModule[MAX_PATH] = { L'\0' }; @@ -7764,7 +7764,7 @@ BOOL SaveFileDlg(HWND hwnd,LPWSTR lpstrFile,int cchFile,LPCWSTR lpstrInitialDir) ofn.Flags = OFN_HIDEREADONLY /*| OFN_NOCHANGEDIR*/ | /*OFN_NODEREFERENCELINKS |*/ OFN_OVERWRITEPROMPT | OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST; - ofn.lpstrDefExt = (StringCchLen(tchDefaultExtension)) ? tchDefaultExtension : NULL; + ofn.lpstrDefExt = (StringCchLenW(tchDefaultExtension,COUNTOF(tchDefaultExtension))) ? tchDefaultExtension : NULL; if (GetSaveFileName(&ofn)) { StringCchCopyN(lpstrFile,cchFile,szNewFile,COUNTOF(szNewFile)); @@ -7791,7 +7791,7 @@ BOOL CALLBACK EnumWndProc(HWND hwnd,LPARAM lParam) if (GetClassName(hwnd,szClassName,COUNTOF(szClassName))) - if (StringCchCompareI(szClassName,wchWndClass) == 0) { + if (StringCchCompareINW(szClassName,COUNTOF(szClassName),wchWndClass,COUNTOF(wchWndClass)) == 0) { DWORD dwReuseLock = GetDlgItemInt(hwnd,IDC_REUSELOCK,NULL,FALSE); if (GetTickCount() - dwReuseLock >= REUSEWINDOWLOCKTIMEOUT) { @@ -7812,7 +7812,7 @@ BOOL CALLBACK EnumWndProc2(HWND hwnd,LPARAM lParam) if (GetClassName(hwnd,szClassName,COUNTOF(szClassName))) - if (StringCchCompareI(szClassName,wchWndClass) == 0) { + if (StringCchCompareINW(szClassName,COUNTOF(szClassName),wchWndClass,COUNTOF(wchWndClass)) == 0) { DWORD dwReuseLock = GetDlgItemInt(hwnd,IDC_REUSELOCK,NULL,FALSE); if (GetTickCount() - dwReuseLock >= REUSEWINDOWLOCKTIMEOUT) { @@ -7991,7 +7991,7 @@ BOOL ActivatePrevInst() if (lpSchemeArg) cb += (lstrlen(lpSchemeArg) + 1) * sizeof(WCHAR); - cchTitleExcerpt = StringCchLen(szTitleExcerpt); + cchTitleExcerpt = StringCchLenW(szTitleExcerpt,COUNTOF(szTitleExcerpt)); if (cchTitleExcerpt) cb += (cchTitleExcerpt + 1) * sizeof(WCHAR); @@ -8139,7 +8139,7 @@ BOOL RelaunchElevated(LPWSTR lpArgs) { StringCchCopy(szArguments,COUNTOF(szArguments),szArgs); } else { - if (StringCchLen(szIniFile) > 0) + if (StringCchLenW(szIniFile,COUNTOF(szIniFile)) > 0) StringCchPrintf(szArguments,COUNTOF(szArguments),L"/f \"%s\" %s",szIniFile,szArgs); else StringCchCopy(szArguments,COUNTOF(szArguments),szArgs); @@ -8264,12 +8264,12 @@ void SetNotifyIconTitle(HWND hwnd) nid.uID = 0; nid.uFlags = NIF_TIP; - if (StringCchLen(szTitleExcerpt)) { + if (StringCchLenW(szTitleExcerpt,COUNTOF(szTitleExcerpt))) { GetString(IDS_TITLEEXCERPT,tchFormat,COUNTOF(tchFormat)); StringCchPrintf(tchTitle,COUNTOF(tchTitle),tchFormat,szTitleExcerpt); } - else if (StringCchLen(szCurFile)) { + else if (StringCchLenW(szCurFile,COUNTOF(szCurFile))) { SHGetFileInfo2(szCurFile,0,&shfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME); PathCompactPathEx(tchTitle,shfi.szDisplayName,COUNTOF(tchTitle)-4,0); } @@ -8299,7 +8299,7 @@ void InstallFileWatching(LPCWSTR lpszFile) HANDLE hFind; // Terminate - if (!iFileWatchingMode || !lpszFile || StringCchLenN(lpszFile,MAX_PATH) == 0) + if (!iFileWatchingMode || !lpszFile || StringCchLen(lpszFile,MAX_PATH) == 0) { if (bRunningWatch) { diff --git a/src/Print.cpp b/src/Print.cpp index c5f2a0d32..a7f6245a3 100644 --- a/src/Print.cpp +++ b/src/Print.cpp @@ -375,10 +375,10 @@ extern "C" BOOL EditPrint(HWND hwnd,LPCWSTR pszDocTitle,LPCWSTR pszPageFormat) { SIZE sizeInfo; SelectObject(hdc,fontFooter); - GetTextExtentPoint32(hdc,dateString,StringCchLen(dateString),&sizeInfo); + GetTextExtentPoint32(hdc,dateString,StringCchLenW(dateString,COUNTOF(dateString)),&sizeInfo); ExtTextOut(hdc, frPrint.rc.right - 5 - sizeInfo.cx, frPrint.rc.top - headerLineHeight / 2, /*ETO_OPAQUE*/0, &rcw, dateString, - StringCchLen(dateString), NULL); + StringCchLenW(dateString,COUNTOF(dateString)), NULL); } if (iPrintHeader < 3) @@ -409,10 +409,10 @@ extern "C" BOOL EditPrint(HWND hwnd,LPCWSTR pszDocTitle,LPCWSTR pszPageFormat) if (iPrintFooter == 0) { SIZE sizeFooter; - GetTextExtentPoint32(hdc,pageString,StringCchLen(pageString),&sizeFooter); + GetTextExtentPoint32(hdc,pageString,StringCchLenW(pageString,COUNTOF(pageString)),&sizeFooter); ExtTextOut(hdc, frPrint.rc.right - 5 - sizeFooter.cx, frPrint.rc.bottom + footerLineHeight / 2, /*ETO_OPAQUE*/0, &rcw, pageString, - StringCchLen(pageString), NULL); + StringCchLenW(pageString,COUNTOF(pageString)), NULL); SetTextAlign(hdc, ta); pen = ::CreatePen(0, 1, RGB(0,0,0)); diff --git a/src/Styles.c b/src/Styles.c index 5059cd509..e40b3db20 100644 --- a/src/Styles.c +++ b/src/Styles.c @@ -3176,7 +3176,7 @@ void Style_SetLexer(HWND hwnd, PEDITLEXER pLexNew) { } if (StrStr(lexDefault.Styles[STY_CARET + iIdx].szValue,L"noblink")) { SendMessage(hwnd,SCI_SETCARETPERIOD,(WPARAM)0,0); - if (StringCchLen(wchCaretStyle)) + if (StringCchLenW(wchCaretStyle,COUNTOF(wchCaretStyle))) StringCchCat(wchCaretStyle,COUNTOF(wchCaretStyle),L"; "); StringCchCat(wchCaretStyle,COUNTOF(wchCaretStyle),L"noblink"); } @@ -3192,7 +3192,7 @@ void Style_SetLexer(HWND hwnd, PEDITLEXER pLexNew) { (int)GetRValue(rgb), (int)GetGValue(rgb), (int)GetBValue(rgb)); - if (StringCchLen(wchCaretStyle)) + if (StringCchLenW(wchCaretStyle,COUNTOF(wchCaretStyle))) StringCchCat(wchCaretStyle,COUNTOF(wchCaretStyle),L"; "); StringCchCat(wchCaretStyle,COUNTOF(wchCaretStyle),wch); } @@ -3624,7 +3624,7 @@ void Style_SetLexerFromFile(HWND hwnd,LPCWSTR lpszFile) } if (!bFound && bAutoSelect && /* bAutoSelect == FALSE skips lexer search */ - (lpszFile && StringCchLenN(lpszFile,MAX_PATH) > 0 && *lpszExt)) { + (lpszFile && StringCchLen(lpszFile,MAX_PATH) > 0 && *lpszExt)) { if (*lpszExt == L'.') ++lpszExt; @@ -3833,7 +3833,7 @@ extern WCHAR tchFileDlgFilters[5*1024]; BOOL Style_GetOpenDlgFilterStr(LPWSTR lpszFilter,int cchFilter) { - if (StringCchLen(tchFileDlgFilters) == 0) + if (StringCchLenW(tchFileDlgFilters,COUNTOF(tchFileDlgFilters)) == 0) GetString(IDS_FILTER_ALL,lpszFilter,cchFilter); else { StringCchCopyN(lpszFilter,cchFilter,tchFileDlgFilters,cchFilter - 2); @@ -4123,7 +4123,7 @@ BOOL Style_SelectFont(HWND hwnd,LPWSTR lpszStyle,int cchStyle,BOOL bDefaultStyle if (HIBYTE(GetKeyState(VK_SHIFT))) cf.Flags |= CF_FIXEDPITCHONLY; - if (!ChooseFont(&cf) || !StringCchLen(lf.lfFaceName)) + if (!ChooseFont(&cf) || !StringCchLenW(lf.lfFaceName,COUNTOF(lf.lfFaceName))) return FALSE; // Map back to lpszStyle @@ -4227,21 +4227,21 @@ BOOL Style_SelectColor(HWND hwnd,BOOL bFore,LPWSTR lpszStyle,int cchStyle) } if (Style_StrGetFontQuality(lpszStyle,tch,COUNTOF(tch))) { - if (StringCchLen(szNewStyle)) + if (StringCchLenW(szNewStyle,COUNTOF(szNewStyle))) StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"; "); StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"smoothing:"); StringCchCat(szNewStyle,COUNTOF(szNewStyle),tch); } if (Style_StrGetCharSet(lpszStyle,&iValue)) { - if (StringCchLen(szNewStyle)) + if (StringCchLenW(szNewStyle, COUNTOF(szNewStyle))) StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"; "); StringCchPrintf(tch,COUNTOF(tch),L"charset:%i",iValue); StringCchCat(szNewStyle,COUNTOF(szNewStyle),tch); } if (Style_StrGetSizeStr(lpszStyle,tch,COUNTOF(tch))) { - if (StringCchLen(szNewStyle)) + if (StringCchLenW(szNewStyle, COUNTOF(szNewStyle))) StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"; "); StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"size:"); StringCchCat(szNewStyle,COUNTOF(szNewStyle),tch); @@ -4249,26 +4249,26 @@ BOOL Style_SelectColor(HWND hwnd,BOOL bFore,LPWSTR lpszStyle,int cchStyle) if (StrStrI(lpszStyle,L"bold")) { - if (StringCchLen(szNewStyle)) + if (StringCchLenW(szNewStyle, COUNTOF(szNewStyle))) StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"; "); StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"bold"); } if (StrStrI(lpszStyle,L"italic")) { - if (StringCchLen(szNewStyle)) + if (StringCchLenW(szNewStyle, COUNTOF(szNewStyle))) StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"; "); StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"italic"); } if (StrStrI(lpszStyle,L"underline")) { - if (StringCchLen(szNewStyle)) + if (StringCchLenW(szNewStyle, COUNTOF(szNewStyle))) StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"; "); StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"underline"); } if (bFore) { - if (StringCchLen(szNewStyle)) + if (StringCchLenW(szNewStyle, COUNTOF(szNewStyle))) StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"; "); StringCchPrintf(tch,COUNTOF(tch),L"fore:#%02X%02X%02X", (int)GetRValue(iRGBResult), @@ -4286,7 +4286,7 @@ BOOL Style_SelectColor(HWND hwnd,BOOL bFore,LPWSTR lpszStyle,int cchStyle) } else { - if (StringCchLen(szNewStyle)) + if (StringCchLenW(szNewStyle, COUNTOF(szNewStyle))) StringCchCat(szNewStyle,COUNTOF(szNewStyle),L"; "); if (Style_StrGetColor(TRUE,lpszStyle,&iValue)) { @@ -4448,7 +4448,7 @@ int Style_GetLexerIconId(PEDITLEXER plex) WCHAR pszFile[MAX_PATH + BUFZIZE_STYLE_EXTENTIONS]; WCHAR *pszExtensions; - if (StringCchLen(plex->szExtensions)) + if (StringCchLenW(plex->szExtensions,COUNTOF(plex->szExtensions))) pszExtensions = plex->szExtensions; else pszExtensions = plex->pszDefExt; @@ -4460,7 +4460,7 @@ int Style_GetLexerIconId(PEDITLEXER plex) if (p) { *p = L'\0'; } // check for ; at beginning - if (StringCchLenN(pszFile, COUNTOF(pszFile)) < 3) + if (StringCchLen(pszFile, COUNTOF(pszFile)) < 3) StringCchCat(pszFile, COUNTOF(pszFile),L"txt"); SHFILEINFO shfi; @@ -5119,7 +5119,7 @@ void Style_ConfigDlg(HWND hwnd) else { fStylesModified = TRUE; - if (StringCchLen(szIniFile) == 0 && !fWarnedNoIniFile) { + if (StringCchLenW(szIniFile,COUNTOF(szIniFile)) == 0 && !fWarnedNoIniFile) { MsgBox(MBWARN,IDS_SETTINGSNOTSAVED); fWarnedNoIniFile = TRUE; } From b4491b6d8e8f6a5a584c0a8a490e0c25d747a3f6 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Fri, 27 Oct 2017 20:45:34 +0200 Subject: [PATCH 02/11] + intermediate step --- src/Edit.c | 497 +++++++++++++++++++---------------------------------- 1 file changed, 178 insertions(+), 319 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index 39fc591a1..1ff0bcd3c 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -4902,7 +4902,6 @@ int __fastcall EditFindInTarget(HWND hwnd, LPCSTR szFind, int length, int flags, } - //============================================================================= // // EditFindNext() @@ -4924,20 +4923,34 @@ BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); return FALSE; } - if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); - int iLength = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); + int iDocLength = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); int iSelPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); int iSelAnchor = (int)SendMessage(hwnd, SCI_GETANCHOR, 0, 0); int start = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); - int end = iLength; + int end = iDocLength; + + BOOL bRegexStartOfLine = (lpefr->fuFlags & SCFIND_REGEXP) && (szFind[0] == '^'); + if (bRegexStartOfLine) { + int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, (WPARAM)start, 0); + int ilPos = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); // begining of current line + if (ilPos != start) + start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)(iLine + 1), 0); // begining of next line + if (start >= end) { + if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { + end = start; start = 0; + } + else + bSuppressNotFound = TRUE; + } + } int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); - if (iPos < 0 && start > 0 && !lpefr->bNoFindWrap && !fExtendSelection) { + if ((iPos < 0) && (start > 0) && !lpefr->bNoFindWrap && !fExtendSelection && !bSuppressNotFound) { if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { end = start; start = 0; iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); @@ -4963,68 +4976,6 @@ BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { } -#if 0 -//============================================================================= -// -// EditFindNext() -// -BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { - - char szFind[FNDRPL_BUFFER]; - BOOL bSuppressNotFound = FALSE; - - if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) - return /*EditFindReplaceDlg(hwnd,lpefr,FALSE)*/FALSE; - - StringCchCopyNA(szFind, COUNTOF(szFind), lpefr->szFind, COUNTOF(lpefr->szFind)); - if (lpefr->bTransformBS) - TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); - - if (StringCchLenA(szFind,COUNTOF(szFind)) == 0) { - InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); - return FALSE; - } - - if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); - - int iLength = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - - int iSelPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); - int iSelAnchor = (int)SendMessage(hwnd, SCI_GETANCHOR, 0, 0); - - int start = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); - int end = iLength; - - int iPos = EditFindInTarget(hwnd, szFind, (int)(lpefr->fuFlags), &start, &end); - - if (iPos < 0 && start > 0 && !lpefr->bNoFindWrap && !fExtendSelection) { - if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { - end = start; start = 0; - iPos = EditFindInTarget(hwnd, szFind, (int)(lpefr->fuFlags), &start, &end); - } - else - bSuppressNotFound = TRUE; - } - - if (iPos < 0) { - // notfound - if (!bSuppressNotFound) - InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); - return FALSE; - } - - if (!fExtendSelection) - EditSelectEx(hwnd, start, end); - else - EditSelectEx(hwnd, min(iSelAnchor, iSelPos), end); - - return TRUE; - -} -#endif - - - //============================================================================= // // EditFindPrev() @@ -5046,10 +4997,9 @@ BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); return FALSE; } - if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); - int iLength = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); + int iDocLength = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); int iSelPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); int iSelAnchor = (int)SendMessage(hwnd, SCI_GETANCHOR, 0, 0); @@ -5057,11 +5007,26 @@ BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { int start = max(0, (int)SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0)); int end = 0; + BOOL bRegexStartOfLine = (lpefr->fuFlags & SCFIND_REGEXP) && (szFind[0] == '^'); + if (bRegexStartOfLine) { + int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, (WPARAM)start, 0); + int ilPos = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); // begining of current line + if (ilPos != start) + start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)(iLine + 1), 0); // begining of previous line + //if (end >= start) { + // if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { + // end = start; start = iDocLength; + // } + // else + // bSuppressNotFound = TRUE; + //} + } + int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); - if (iPos < 0 && start < iLength && !lpefr->bNoFindWrap && !fExtendSelection) { + if ((iPos < 0) && (start < iDocLength) && !lpefr->bNoFindWrap && !fExtendSelection && !bSuppressNotFound) { if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap2", IDS_FIND_WRAPRE)) { - end = start; start = iLength; + end = start; start = iDocLength; iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); } else @@ -5091,26 +5056,10 @@ BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { // BOOL EditReplace(HWND hwnd, LPCEDITFINDREPLACE lpefr) { - char szFind[FNDRPL_BUFFER]; - char *pszReplace; // replace text of arbitrary size - BOOL bSuppressNotFound = FALSE; - - - if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) - return /*EditFindReplaceDlg(hwnd,lpefr,TRUE)*/FALSE; - - StringCchCopyNA(szFind, COUNTOF(szFind), lpefr->szFind, COUNTOF(lpefr->szFind)); - if (lpefr->bTransformBS) - TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); - - int slen = StringCchLenA(szFind, COUNTOF(szFind)); - if (slen == 0) { - InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); - return FALSE; - } - - if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); + if ((BOOL)SendMessage(hwnd, SCI_GETSELECTIONEMPTY, 0, 0)) + return EditFindNext(hwnd, lpefr, FALSE); + char* pszReplace; // replace text of arbitrary size int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; if (StringCchCompareNA(lpefr->szReplace, FNDRPL_BUFFER, "^c", -1) == 0) { iReplaceMsg = SCI_REPLACETARGET; @@ -5127,68 +5076,13 @@ BOOL EditReplace(HWND hwnd, LPCEDITFINDREPLACE lpefr) { if (!pszReplace) return FALSE; // recoding of clipboard canceled - int iSelStart = (int)SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0); - int iSelEnd = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); - - int start = iSelStart; - int end = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - - int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); - - if (iPos < 0 && start > 0 && !lpefr->bNoFindWrap) { - if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { - end = start; start = 0; - iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); - } - else - bSuppressNotFound = TRUE; - } - - if (iPos < 0) { - // notfound - if (!bSuppressNotFound) - InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); - LocalFree(pszReplace); - return FALSE; - } - - if (iSelStart != start || iSelEnd != end) { - EditSelectEx(hwnd, start, end); - LocalFree(pszReplace); - return FALSE; - } + SendMessage(hwnd, SCI_TARGETFROMSELECTION, 0, 0); SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); - // === goto next find for next replacement === - - start = (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0); - end = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - - iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); - - bSuppressNotFound = FALSE; - if (iPos < 0 && start > 0 && !lpefr->bNoFindWrap) { - if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { - end = start; start = 0; - iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); - } - else - bSuppressNotFound = TRUE; - } - - if (iPos >= 0) { - EditSelectEx(hwnd, start, end); - } - else { - EditSelectEx(hwnd, end, end); - if (!bSuppressNotFound) - InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); - } - LocalFree(pszReplace); - return TRUE; + return EditFindNext(hwnd, lpefr, FALSE); } @@ -5210,20 +5104,12 @@ void CompleteWord(HWND hwnd, BOOL autoInsert) int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iCurrentPos, 0); int iCurrentLinePos = iCurrentPos - (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); int iStartWordPos = iCurrentLinePos; - char *pLine; - char *pRoot; - char *pWord; - int iNumWords = 0; - int iRootLen = 0; - int iDocLen; - int iPosFind; struct Sci_TextRange tr = { { 0, -1 }, NULL }; - struct Sci_TextToFind ft = {{0, 0}, 0, {0, 0}}; BOOL bWordAllNumbers = TRUE; struct WLIST* lListHead = NULL; int iWListSize = 0; - pLine = LocalAlloc(LPTR, (int)SendMessage(hwnd, SCI_GETLINE, (WPARAM)iLine, 0) + 1); + char* pLine = LocalAlloc(LPTR, (int)SendMessage(hwnd, SCI_GETLINE, (WPARAM)iLine, 0) + 1); SendMessage(hwnd, SCI_GETLINE, (WPARAM)iLine, (LPARAM)pLine); while (iStartWordPos > 0 && !StrChrIA(NON_WORD, pLine[iStartWordPos - 1])) { @@ -5239,27 +5125,29 @@ void CompleteWord(HWND hwnd, BOOL autoInsert) } int cnt = iCurrentLinePos - iStartWordPos; - pRoot = LocalAlloc(LPTR,cnt+1); + char* pRoot = LocalAlloc(LPTR,cnt+1); StringCchCopyNA(pRoot,cnt+1,pLine + iStartWordPos,cnt); LocalFree(pLine); - iRootLen = StringCchLenA(pRoot,cnt+1); - iDocLen = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); + int iRootLen = StringCchLenA(pRoot,cnt+1); + int iDocLen = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - ft.lpstrText = pRoot; - ft.chrg.cpMax = iDocLen; + int start = 0; + int end = iDocLen; - iPosFind = (int)SendMessage(hwnd, SCI_FINDTEXT, SCFIND_WORDSTART, (LPARAM)&ft); + int iPosFind = EditFindInTarget(hwnd, pRoot, iRootLen, SCFIND_WORDSTART, &start, &end); - while (iPosFind >= 0 && iPosFind < iDocLen) { - int wordLength; + int iNumWords = 0; + char* pWord = NULL; + while (iPosFind >= 0 && iPosFind < iDocLen) + { int wordEnd = iPosFind + iRootLen; if (iPosFind != iCurrentPos - iRootLen) { while (wordEnd < iDocLen && !StrChrIA(NON_WORD, (char)SendMessage(hwnd, SCI_GETCHARAT, (WPARAM)wordEnd, 0))) wordEnd++; - wordLength = wordEnd - iPosFind; + int wordLength = wordEnd - iPosFind; if (wordLength > iRootLen) { struct WLIST* p = lListHead; struct WLIST* t = NULL; @@ -5301,8 +5189,8 @@ void CompleteWord(HWND hwnd, BOOL autoInsert) LocalFree(pWord); } } - ft.chrg.cpMin = wordEnd; - iPosFind = (int)SendMessage(hwnd, SCI_FINDTEXT, SCFIND_WORDSTART, (LPARAM)&ft); + start = wordEnd; end = iDocLen; + iPosFind = EditFindInTarget(hwnd, pRoot, iRootLen, SCFIND_WORDSTART, &start, &end); } if (iNumWords > 0) { @@ -5400,44 +5288,33 @@ void EditMatchBrace(HWND hwnd) // void EditMarkAll(HWND hwnd, BOOL bMarkOccurrencesMatchCase, BOOL bMarkOccurrencesMatchWords) { - struct Sci_TextToFind ttf; - int iPos; - char *pszText; - int iTextLen; - int iSelStart; - int iSelEnd; - int iSelLength; - int iSelCount; + iMarkOccurrencesCount = -1; // -1 ! // feature is off if (!iMarkOccurrences) { - iMarkOccurrencesCount = -1; UpdateStatusbar(); return; } - - iTextLen = (int)SendMessage(hwnd,SCI_GETLENGTH,0,0); + int iTextLen = (int)SendMessage(hwnd,SCI_GETLENGTH,0,0); // get current selection - iSelStart = (int)SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0); - iSelEnd = (int)SendMessage(hwnd,SCI_GETSELECTIONEND,0,0); - iSelLength = (int)SendMessage(hwnd,SCI_GETSELTEXT,0,0); - iSelCount = iSelEnd - iSelStart; + int iSelStart = (int)SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0); + int iSelEnd = (int)SendMessage(hwnd,SCI_GETSELECTIONEND,0,0); + int iSelCount = iSelEnd - iSelStart; // clear existing marker indicators SendMessage(hwnd, SCI_SETINDICATORCURRENT, INDIC_NP3_MARK_OCCURANCE, 0); SendMessage(hwnd, SCI_INDICATORCLEARRANGE, 0, iTextLen); - iMarkOccurrencesCount = -1; - + // if nothing selected or multiple lines are selected exit if ((iSelCount == 0) || (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iSelStart, 0) != (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iSelEnd, 0)) return; - - pszText = LocalAlloc(LPTR,iSelLength); + int iSelLength = (int)SendMessage(hwnd, SCI_GETSELTEXT, 0, (LPARAM)NULL) - 1; + char* pszText = LocalAlloc(LPTR,iSelLength+1); (int)SendMessage(hwnd,SCI_GETSELTEXT,0,(LPARAM)pszText); @@ -5457,29 +5334,30 @@ void EditMarkAll(HWND hwnd, BOOL bMarkOccurrencesMatchCase, BOOL bMarkOccurrence } } - ZeroMemory(&ttf,sizeof(ttf)); + int flags = (bMarkOccurrencesMatchCase ? SCFIND_MATCHCASE : 0); + flags |= (bMarkOccurrencesMatchWords ? SCFIND_WHOLEWORD : 0); + + int iPos = 0; + int start = 0; + int end = iTextLen; - ttf.chrg.cpMin = 0; - ttf.chrg.cpMax = iTextLen; - ttf.lpstrText = pszText; - - iMarkOccurrencesCount = 0; - while ((iPos = (int)SendMessage(hwnd, SCI_FINDTEXT, - (bMarkOccurrencesMatchCase ? SCFIND_MATCHCASE : 0) | (bMarkOccurrencesMatchWords ? SCFIND_WHOLEWORD : 0), - (LPARAM)&ttf)) != -1 - && (++iMarkOccurrencesCount < iMarkOccurrencesMaxCount)) + while (++iMarkOccurrencesCount < iMarkOccurrencesMaxCount) { + iPos = EditFindInTarget(hwnd, pszText, iSelLength, flags, &start, &end); + + if (iPos < 0) + break; // not found + // mark this match SendMessage(hwnd, SCI_INDICATORFILLRANGE, iPos, iSelCount); - ttf.chrg.cpMin = ttf.chrgText.cpMin + iSelCount; - if (ttf.chrg.cpMin == ttf.chrg.cpMax) + start = end + 1; end = iTextLen; + + if (start >= end) break; } + LocalFree(pszText); - UpdateStatusbar(); - - return; } @@ -5489,101 +5367,91 @@ void EditMarkAll(HWND hwnd, BOOL bMarkOccurrencesMatchCase, BOOL bMarkOccurrence // BOOL EditReplaceAll(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo) { - - struct Sci_TextToFind ttf; - int iPos; - int iCount = 0; - int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; - char szFind2[FNDRPL_BUFFER]; - char *pszReplace2; - BOOL bRegexStartOfLine; - BOOL bRegexStartOrEndOfLine; - if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) return /*EditFindReplaceDlg(hwnd,lpefr,TRUE)*/FALSE; // Show wait cursor... BeginWaitCursor(); - StringCchCopyNA(szFind2,COUNTOF(szFind2),lpefr->szFind,COUNTOF(lpefr->szFind)); + char szFind[FNDRPL_BUFFER]; + StringCchCopyNA(szFind,COUNTOF(szFind),lpefr->szFind,COUNTOF(lpefr->szFind)); if (lpefr->bTransformBS) - TransformBackslashes(szFind2,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); + TransformBackslashes(szFind,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); - if (StringCchLenA(szFind2,COUNTOF(szFind2)) == 0) + int slen = StringCchLenA(szFind, COUNTOF(szFind)); + if (slen == 0) { InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); return FALSE; } + if( lpefr->bWildcardSearch ) EscapeWildcards( szFind , lpefr ); - if( lpefr->bWildcardSearch ) EscapeWildcards( szFind2 , lpefr ); + BOOL bRegexStartOfLine = (lpefr->fuFlags & SCFIND_REGEXP) && (szFind[0] == '^'); - bRegexStartOfLine = - (szFind2[0] == '^'); - bRegexStartOrEndOfLine = - (lpefr->fuFlags & SCFIND_REGEXP && - (!StringCchCompareNA(szFind2,FNDRPL_BUFFER,"$",-1) || - !StringCchCompareNA(szFind2,FNDRPL_BUFFER,"^",-1) || - !StringCchCompareNA(szFind2,FNDRPL_BUFFER,"^$",-1))); + BOOL bRegexStartOrEndOfLine = + ((lpefr->fuFlags & SCFIND_REGEXP) && + (!StringCchCompareNA(szFind,FNDRPL_BUFFER,"$",-1) || + !StringCchCompareNA(szFind,FNDRPL_BUFFER,"^",-1) || + !StringCchCompareNA(szFind,FNDRPL_BUFFER,"^$",-1))); + char* pszReplace = NULL; + int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; if (StringCchCompareNA(lpefr->szReplace,FNDRPL_BUFFER,"^c",-1) == 0) { iReplaceMsg = SCI_REPLACETARGET; - pszReplace2 = EditGetClipboardText(hwnd,TRUE,NULL,NULL); + pszReplace = EditGetClipboardText(hwnd,TRUE,NULL,NULL); } else { - //lstrcpyA(szReplace2,lpefr->szReplace); - pszReplace2 = StrDupA(lpefr->szReplace); - if (!pszReplace2) - pszReplace2 = StrDupA(""); + pszReplace = StrDupA(lpefr->szReplace); + if (!pszReplace) + pszReplace = StrDupA(""); if (lpefr->bTransformBS) - TransformBackslashes(pszReplace2,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); + TransformBackslashes(pszReplace,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); } - if (!pszReplace2) + if (!pszReplace) return FALSE; // recoding canceled - ZeroMemory(&ttf,sizeof(ttf)); - ttf.chrg.cpMin = 0; - ttf.chrg.cpMax = (int)SendMessage(hwnd,SCI_GETLENGTH,0,0); - ttf.lpstrText = szFind2; + int iPos = 0; + int iCount = 0; + int start = 0; + int end = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0);; - while ((iPos = (int)SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf)) != -1) + while ((iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end)) >= 0) { - int iReplacedLen; - //char ch; - - if (iCount == 0 && bRegexStartOrEndOfLine) { + if ((iCount == 0) && bRegexStartOrEndOfLine) { if (0 == SendMessage(hwnd,SCI_GETLINEENDPOSITION,0,0)) { iPos = 0; - ttf.chrgText.cpMin = 0; - ttf.chrgText.cpMax = 0; + start = 0; + end = 0; } } if (++iCount == 1) SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0); - SendMessage(hwnd,SCI_SETTARGETSTART,ttf.chrgText.cpMin,0); - SendMessage(hwnd,SCI_SETTARGETEND,ttf.chrgText.cpMax,0); - iReplacedLen = (int)SendMessage(hwnd,iReplaceMsg,(WPARAM)-1,(LPARAM)pszReplace2); + SendMessage(hwnd,SCI_SETTARGETSTART,start,0); + SendMessage(hwnd,SCI_SETTARGETEND,end,0); + int iReplacedLen = (int)SendMessage(hwnd,iReplaceMsg,(WPARAM)-1,(LPARAM)pszReplace); - ttf.chrg.cpMin = ttf.chrgText.cpMin + iReplacedLen; - ttf.chrg.cpMax = (int)SendMessage(hwnd,SCI_GETLENGTH,0,0); + start += iReplacedLen; + end = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - if (ttf.chrg.cpMin == ttf.chrg.cpMax) + if (start == end) break; - //ch = (char)SendMessage(hwnd,SCI_GETCHARAT,SendMessage(hwnd,SCI_GETTARGETEND,0,0),0); + //char ch = (char)SendMessage(hwnd,SCI_GETCHARAT,SendMessage(hwnd,SCI_GETTARGETEND,0,0),0); if (/*ch == '\r' || ch == '\n' || iReplacedLen == 0 || */ - ttf.chrgText.cpMin == ttf.chrgText.cpMax && - !(bRegexStartOrEndOfLine && iReplacedLen > 0)) - ttf.chrg.cpMin = (int)SendMessage(hwnd,SCI_POSITIONAFTER,ttf.chrg.cpMin,0); + (start == end) && !(bRegexStartOrEndOfLine && (iReplacedLen > 0))) + start = (int)SendMessage(hwnd,SCI_POSITIONAFTER,start,0); + if (bRegexStartOfLine) { - int iLine = (int)SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)ttf.chrg.cpMin,0); - int ilPos = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine,0); - if (ilPos == ttf.chrg.cpMin) - ttf.chrg.cpMin = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine+1,0); - if (ttf.chrg.cpMin == ttf.chrg.cpMax) + int iLine = (int)SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)start,0); + int ilPos = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine,0); + if (ilPos == start) + start = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine+1,0); + + if (start == end) break; } } @@ -5601,9 +5469,8 @@ BOOL EditReplaceAll(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo) InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); } - LocalFree(pszReplace2); + LocalFree(pszReplace); return TRUE; - } @@ -5613,109 +5480,101 @@ BOOL EditReplaceAll(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo) // BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo) { - - struct Sci_TextToFind ttf; - int iPos; - int iCount = 0; - int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; - BOOL fCancel = FALSE; - char szFind2[FNDRPL_BUFFER]; - char *pszReplace2; - BOOL bRegexStartOfLine; - BOOL bRegexStartOrEndOfLine; - - if (SC_SEL_RECTANGLE == SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0)) - { - MsgBox(MBWARN,IDS_SELRECT); - return FALSE; - } - if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) return /*EditFindReplaceDlg(hwnd,lpefr,TRUE)*/FALSE; + if (SC_SEL_RECTANGLE == SendMessage(hwnd, SCI_GETSELECTIONMODE, 0, 0)) { + MsgBox(MBWARN, IDS_SELRECT); + return FALSE; + } + // Show wait cursor... BeginWaitCursor(); + int token = BeginSelUndoAction(); - StringCchCopyNA(szFind2,COUNTOF(szFind2),lpefr->szFind,COUNTOF(lpefr->szFind)); + char szFind[FNDRPL_BUFFER]; + StringCchCopyNA(szFind,COUNTOF(szFind),lpefr->szFind,COUNTOF(lpefr->szFind)); if (lpefr->bTransformBS) - TransformBackslashes(szFind2,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); + TransformBackslashes(szFind,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); - if (StringCchLenA(szFind2,COUNTOF(szFind2)) == 0) + int slen = StringCchLenA(szFind, COUNTOF(szFind)); + if (slen == 0) { InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); return FALSE; } - if( lpefr->bWildcardSearch ) EscapeWildcards( szFind2 , lpefr ); + if( lpefr->bWildcardSearch ) EscapeWildcards( szFind , lpefr ); - bRegexStartOfLine = (szFind2[0] == '^'); - bRegexStartOrEndOfLine = (lpefr->fuFlags & SCFIND_REGEXP && - (!StringCchCompareNA(szFind2,FNDRPL_BUFFER,"$",-1) || - !StringCchCompareNA(szFind2,FNDRPL_BUFFER,"^",-1) || - !StringCchCompareNA(szFind2,FNDRPL_BUFFER,"^$",-1))); + BOOL bRegexStartOfLine = (szFind[0] == '^'); + BOOL bRegexStartOrEndOfLine = ((lpefr->fuFlags & SCFIND_REGEXP) && + (!StringCchCompareNA(szFind,FNDRPL_BUFFER,"$",-1) || + !StringCchCompareNA(szFind,FNDRPL_BUFFER,"^",-1) || + !StringCchCompareNA(szFind,FNDRPL_BUFFER,"^$",-1))); + char* pszReplace = NULL; + int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; if (StringCchCompareNA(lpefr->szReplace,FNDRPL_BUFFER,"^c",-1) == 0) { iReplaceMsg = SCI_REPLACETARGET; - pszReplace2 = EditGetClipboardText(hwnd,TRUE,NULL,NULL); + pszReplace = EditGetClipboardText(hwnd,TRUE,NULL,NULL); } else { //lstrcpyA(szReplace2,lpefr->szReplace); - pszReplace2 = StrDupA(lpefr->szReplace); - if (!pszReplace2) - pszReplace2 = StrDupA(""); + pszReplace = StrDupA(lpefr->szReplace); + if (!pszReplace) + pszReplace = StrDupA(""); if (lpefr->bTransformBS) - TransformBackslashes(pszReplace2,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); + TransformBackslashes(pszReplace,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); } - if (!pszReplace2) + if (!pszReplace) return FALSE; // recoding canceled - ZeroMemory(&ttf,sizeof(ttf)); - ttf.chrg.cpMin = (int)SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0); - ttf.chrg.cpMax = (int)SendMessage(hwnd,SCI_GETLENGTH,0,0); - ttf.lpstrText = szFind2; - while ((iPos = (int)SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf)) != -1 && !fCancel) + int iPos; + int iCount = 0; + BOOL fCancel = FALSE; + int start = (int)SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0); + int end = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); + + while ((iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end)) >= 0 && !fCancel) { - if (ttf.chrgText.cpMin >= SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0) && - ttf.chrgText.cpMax <= SendMessage(hwnd,SCI_GETSELECTIONEND,0,0)) + if (start >= SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0) && + end <= SendMessage(hwnd,SCI_GETSELECTIONEND,0,0)) { - int iReplacedLen; - //char ch; - - if (ttf.chrg.cpMin == 0 && iCount == 0 && bRegexStartOrEndOfLine) { + if ((start == 0) && (iCount == 0) && bRegexStartOrEndOfLine) { if (0 == SendMessage(hwnd,SCI_GETLINEENDPOSITION,0,0)) { iPos = 0; - ttf.chrgText.cpMin = 0; - ttf.chrgText.cpMax = 0; + start = 0; + end = 0; } } if (++iCount == 1) SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0); - SendMessage(hwnd,SCI_SETTARGETSTART,ttf.chrgText.cpMin,0); - SendMessage(hwnd,SCI_SETTARGETEND,ttf.chrgText.cpMax,0); - iReplacedLen = (int)SendMessage(hwnd,iReplaceMsg,(WPARAM)-1,(LPARAM)pszReplace2); + SendMessage(hwnd, SCI_SETTARGETRANGE, start, end); + int iReplacedLen = (int)SendMessage(hwnd,iReplaceMsg,(WPARAM)-1,(LPARAM)pszReplace); - ttf.chrg.cpMin = ttf.chrgText.cpMin + iReplacedLen; - ttf.chrg.cpMax = (int)SendMessage(hwnd,SCI_GETLENGTH,0,0); + start += iReplacedLen; + end = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0) + (iCount * iReplacedLen); - if (ttf.chrg.cpMin == ttf.chrg.cpMax) + if (start == end) fCancel = TRUE; - //ch = (char)SendMessage(hwnd,SCI_GETCHARAT,SendMessage(hwnd,SCI_GETTARGETEND,0,0),0); + //char ch = (char)SendMessage(hwnd,SCI_GETCHARAT,SendMessage(hwnd,SCI_GETTARGETEND,0,0),0); if (/*ch == '\r' || ch == '\n' || iReplacedLen == 0 || */ - ttf.chrgText.cpMin == ttf.chrgText.cpMax && - !(bRegexStartOrEndOfLine && iReplacedLen > 0)) - ttf.chrg.cpMin = (int)SendMessage(hwnd,SCI_POSITIONAFTER,ttf.chrg.cpMin,0); + (start == end) && !(bRegexStartOrEndOfLine && (iReplacedLen > 0))) + start = (int)SendMessage(hwnd,SCI_POSITIONAFTER,start,0); + if (bRegexStartOfLine) { - int iLine = (int)SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)ttf.chrg.cpMin,0); + int iLine = (int)SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)start,0); int ilPos = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine,0); - if (ilPos == ttf.chrg.cpMin) - ttf.chrg.cpMin = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine+1,0); - if (ttf.chrg.cpMin == ttf.chrg.cpMax) + if (ilPos == start) + start = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine+1,0); + + if (start == end) break; } } @@ -5727,8 +5586,7 @@ BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo if (iCount) { - if (SendMessage(hwnd,SCI_GETSELECTIONEND,0,0) < - SendMessage(hwnd,SCI_GETTARGETEND,0,0)) { + if (SendMessage(hwnd,SCI_GETSELECTIONEND,0,0) < SendMessage(hwnd,SCI_GETTARGETEND,0,0)) { int iAnchorPos = (int)SendMessage(hwnd,SCI_GETANCHOR,0,0); int iCurrentPos = (int)SendMessage(hwnd,SCI_GETCURRENTPOS,0,0); @@ -5745,6 +5603,7 @@ BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo } // Remove wait cursor + EndSelUndoAction(token); EndWaitCursor(); if (bShowInfo) { @@ -5754,7 +5613,7 @@ BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); } - LocalFree(pszReplace2); + LocalFree(pszReplace); return TRUE; } From eb9210c241acacf5d8def38259e57460fd0f94de Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sat, 28 Oct 2017 01:21:49 +0200 Subject: [PATCH 03/11] + refactoring of "Replace All" methods --- src/Edit.c | 714 ++++++++++++++++++++++---------------------------- src/Edit.h | 1 + src/Helpers.h | 2 + 3 files changed, 321 insertions(+), 396 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index 1ff0bcd3c..d4e335bad 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -5086,201 +5086,6 @@ BOOL EditReplace(HWND hwnd, LPCEDITFINDREPLACE lpefr) { } -//============================================================================= -// -// CompleteWord() -// Auto-complete words (by Aleksandar Lekov) -// -struct WLIST { - char* word; - struct WLIST* next; -}; - -void CompleteWord(HWND hwnd, BOOL autoInsert) -{ - const char* NON_WORD = bAccelWordNavigation ? DelimCharsAccel : DelimChars; - - int iCurrentPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); - int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iCurrentPos, 0); - int iCurrentLinePos = iCurrentPos - (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); - int iStartWordPos = iCurrentLinePos; - struct Sci_TextRange tr = { { 0, -1 }, NULL }; - BOOL bWordAllNumbers = TRUE; - struct WLIST* lListHead = NULL; - int iWListSize = 0; - - char* pLine = LocalAlloc(LPTR, (int)SendMessage(hwnd, SCI_GETLINE, (WPARAM)iLine, 0) + 1); - SendMessage(hwnd, SCI_GETLINE, (WPARAM)iLine, (LPARAM)pLine); - - while (iStartWordPos > 0 && !StrChrIA(NON_WORD, pLine[iStartWordPos - 1])) { - iStartWordPos--; - if (pLine[iStartWordPos] < '0' || pLine[iStartWordPos] > '9') { - bWordAllNumbers = FALSE; - } - } - - if (iStartWordPos == iCurrentLinePos || bWordAllNumbers || iCurrentLinePos - iStartWordPos < 2) { - LocalFree(pLine); - return; - } - - int cnt = iCurrentLinePos - iStartWordPos; - char* pRoot = LocalAlloc(LPTR,cnt+1); - StringCchCopyNA(pRoot,cnt+1,pLine + iStartWordPos,cnt); - LocalFree(pLine); - - int iRootLen = StringCchLenA(pRoot,cnt+1); - int iDocLen = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - - int start = 0; - int end = iDocLen; - - int iPosFind = EditFindInTarget(hwnd, pRoot, iRootLen, SCFIND_WORDSTART, &start, &end); - - int iNumWords = 0; - char* pWord = NULL; - while (iPosFind >= 0 && iPosFind < iDocLen) - { - int wordEnd = iPosFind + iRootLen; - - if (iPosFind != iCurrentPos - iRootLen) { - while (wordEnd < iDocLen && !StrChrIA(NON_WORD, (char)SendMessage(hwnd, SCI_GETCHARAT, (WPARAM)wordEnd, 0))) - wordEnd++; - - int wordLength = wordEnd - iPosFind; - if (wordLength > iRootLen) { - struct WLIST* p = lListHead; - struct WLIST* t = NULL; - //int lastCmp = 0; - BOOL found = FALSE; - - pWord = LocalAlloc(LPTR,wordLength + 1); - - tr.lpstrText = pWord; - tr.chrg.cpMin = iPosFind; - tr.chrg.cpMax = wordEnd; - SendMessage(hwnd, SCI_GETTEXTRANGE, 0, (LPARAM)&tr); - - while(p) { - int cmp = StringCchCompareNA(pWord,wordLength + 1, p->word,-1); - if (cmp == 0) { - found = TRUE; - break; - } else if (cmp < 0) { - break; - } - t = p; - p = p->next; - } - if (!found) { - struct WLIST* el = (struct WLIST*)LocalAlloc(LPTR, sizeof(struct WLIST)); - el->word = LocalAlloc(LPTR,wordLength + 1); - StringCchCopyA(el->word,wordLength + 1,pWord); - el->next = p; - if (t) { - t->next = el; - } else { - lListHead = el; - } - - iNumWords++; - iWListSize += StringCchLenA(pWord,wordLength + 1) + 1; - } - LocalFree(pWord); - } - } - start = wordEnd; end = iDocLen; - iPosFind = EditFindInTarget(hwnd, pRoot, iRootLen, SCFIND_WORDSTART, &start, &end); - } - - if (iNumWords > 0) { - char *pList; - struct WLIST* p = lListHead; - struct WLIST* t; - - pList = LocalAlloc(LPTR, iWListSize + 1); - while (p) { - StringCchCatA(pList,iWListSize + 1," "); - StringCchCatA(pList,iWListSize + 1,p->word); - LocalFree(p->word); - t = p; - p = p->next; - LocalFree(t); - } - - SendMessage(hwnd, SCI_AUTOCSETIGNORECASE, 1, 0); - SendMessage(hwnd, SCI_AUTOCSETSEPARATOR, ' ', 0); - SendMessage(hwnd, SCI_AUTOCSETFILLUPS, 0, (LPARAM)"\t\n\r"); - SendMessage(hwnd, SCI_AUTOCSETCHOOSESINGLE, autoInsert, 0); - SendMessage(hwnd, SCI_AUTOCSHOW, iRootLen, (LPARAM)(pList + 1)); - LocalFree(pList); - } - - LocalFree(pRoot); -} - - -BOOL __fastcall EditHighlightIfBrace(HWND hwnd, int iPos) -{ - if (iPos < 0) { - // clear indicator - SendMessage(hwnd, SCI_BRACEBADLIGHT, (WPARAM)INVALID_POSITION, 0); - SendMessage(hwnd, SCI_SETHIGHLIGHTGUIDE, 0, 0); - if (!bUseOldStyleBraceMatching) - SendMessage(hwnd, SCI_BRACEBADLIGHTINDICATOR, 0, INDIC_NP3_BAD_BRACE); - return TRUE; - } - char c = (char)SendMessage(hwnd, SCI_GETCHARAT, iPos, 0); - if (StrChrA("()[]{}", c)) { - int iBrace2 = (int)SendMessage(hwnd, SCI_BRACEMATCH, iPos, 0); - if (iBrace2 != -1) { - int col1 = (int)SendMessage(hwnd, SCI_GETCOLUMN, iPos, 0); - int col2 = (int)SendMessage(hwnd, SCI_GETCOLUMN, iBrace2, 0); - SendMessage(hwnd, SCI_BRACEHIGHLIGHT, iPos, iBrace2); - SendMessage(hwnd, SCI_SETHIGHLIGHTGUIDE, min(col1, col2), 0); - if (!bUseOldStyleBraceMatching) - SendMessage(hwnd, SCI_BRACEHIGHLIGHTINDICATOR, 1, INDIC_NP3_MATCH_BRACE); - } - else { - SendMessage(hwnd, SCI_BRACEBADLIGHT, iPos, 0); - SendMessage(hwnd, SCI_SETHIGHLIGHTGUIDE, 0, 0); - if (!bUseOldStyleBraceMatching) - SendMessage(hwnd, SCI_BRACEBADLIGHTINDICATOR, 1, INDIC_NP3_BAD_BRACE); - } - return TRUE; - } - return FALSE; -} - - - -//============================================================================= -// -// EditMatchBrace() -// -void EditMatchBrace(HWND hwnd) -{ - int iEndStyled = (int)SendMessage(hwnd, SCI_GETENDSTYLED, 0, 0); - if (iEndStyled < (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0)) { - int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iEndStyled, 0); - int iEndStyled2 = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, iLine, 0); - SendMessage(hwnd, SCI_COLOURISE, iEndStyled2, -1); - } - - int iPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); - - if (!EditHighlightIfBrace(hwnd, iPos)) { - // try one before - iPos = (int)SendMessage(hwnd, SCI_POSITIONBEFORE, iPos, 0); - if (!EditHighlightIfBrace(hwnd, iPos)) { - // clear mark - EditHighlightIfBrace(hwnd, -1); - } - } -} - - - //============================================================================= // // EditMarkAll() @@ -5361,6 +5166,125 @@ void EditMarkAll(HWND hwnd, BOOL bMarkOccurrencesMatchCase, BOOL bMarkOccurrence } + +//============================================================================= +// +// EditReplaceAllInRange() +// +int EditReplaceAllInRange(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bShowInfo, int iStartPos, int iEndPos) +{ + BeginWaitCursor(); + + if (iStartPos > iEndPos) + swapi(iStartPos, iEndPos); + + int iDiffToDocEnd = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0) - iEndPos; + + char szFind[FNDRPL_BUFFER]; + StringCchCopyNA(szFind, COUNTOF(szFind), lpefr->szFind, COUNTOF(lpefr->szFind)); + if (lpefr->bTransformBS) + TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); + + int slen = StringCchLenA(szFind, COUNTOF(szFind)); + if (slen == 0) { + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); + return 0; + } + + if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); + + BOOL bRegexStartOfLine = (lpefr->fuFlags & SCFIND_REGEXP) && (szFind[0] == '^'); + + BOOL bRegexStartOrEndOfLine = ((lpefr->fuFlags & SCFIND_REGEXP) && + (!StringCchCompareNA(szFind, FNDRPL_BUFFER, "$", -1) || + !StringCchCompareNA(szFind, FNDRPL_BUFFER, "^", -1) || + !StringCchCompareNA(szFind, FNDRPL_BUFFER, "^$", -1))); + + char* pszReplace = NULL; + int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; + if (StringCchCompareNA(lpefr->szReplace, FNDRPL_BUFFER, "^c", -1) == 0) { + iReplaceMsg = SCI_REPLACETARGET; + pszReplace = EditGetClipboardText(hwnd, TRUE, NULL, NULL); + } + else { + pszReplace = StrDupA(lpefr->szReplace); + if (!pszReplace) + pszReplace = StrDupA(""); + if (lpefr->bTransformBS) + TransformBackslashes(pszReplace, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); + } + + if (!pszReplace) + return -1; // recoding canceled + + int iPos; + int iCount = 0; + BOOL fCancel = FALSE; + int start = iStartPos; + int end = iEndPos; + while ((iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end)) >= 0 && !fCancel) + { + if ((start >= iStartPos) && (end <= iEndPos)) + { + if ((start == 0) && (iCount == 0) && bRegexStartOrEndOfLine) { + if (0 == SendMessage(hwnd, SCI_GETLINEENDPOSITION, 0, 0)) { + iPos = 0; + start = 0; + end = 0; + } + } + + if (++iCount == 1) + SendMessage(hwnd, SCI_BEGINUNDOACTION, 0, 0); + + SendMessage(hwnd, SCI_SETTARGETRANGE, start, end); + int iReplacedLen = (int)SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); + + start += iReplacedLen; + iEndPos = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0) - iDiffToDocEnd; + end = iEndPos; + + if (start >= end) + fCancel = TRUE; + + //char ch = (char)SendMessage(hwnd,SCI_GETCHARAT,SendMessage(hwnd,SCI_GETTARGETEND,0,0),0); + + if (/*ch == '\r' || ch == '\n' || iReplacedLen == 0 || */ + (start == end) && !(bRegexStartOrEndOfLine && (iReplacedLen > 0))) + start = (int)SendMessage(hwnd, SCI_POSITIONAFTER, start, 0); + + if (bRegexStartOfLine) { + int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, (WPARAM)start, 0); + int ilPos = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); + if (ilPos == start) + start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine + 1, 0); + + if (start == end) + break; + } + } + else + // gone across range, cancel + fCancel = TRUE; + } + + if (iCount) + SendMessage(hwnd, SCI_ENDUNDOACTION, 0, 0); + + EndWaitCursor(); + + if (bShowInfo) { + if (iCount > 0) + InfoBox(0, L"MsgReplaceCount", IDS_REPLCOUNT, iCount); + else + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); + } + + LocalFree(pszReplace); + return iCount; +} + + //============================================================================= // // EditReplaceAll() @@ -5370,107 +5294,12 @@ BOOL EditReplaceAll(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo) if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) return /*EditFindReplaceDlg(hwnd,lpefr,TRUE)*/FALSE; - // Show wait cursor... - BeginWaitCursor(); - - char szFind[FNDRPL_BUFFER]; - StringCchCopyNA(szFind,COUNTOF(szFind),lpefr->szFind,COUNTOF(lpefr->szFind)); - if (lpefr->bTransformBS) - TransformBackslashes(szFind,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); - - int slen = StringCchLenA(szFind, COUNTOF(szFind)); - if (slen == 0) - { - InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); - return FALSE; - } - if( lpefr->bWildcardSearch ) EscapeWildcards( szFind , lpefr ); - - BOOL bRegexStartOfLine = (lpefr->fuFlags & SCFIND_REGEXP) && (szFind[0] == '^'); - - BOOL bRegexStartOrEndOfLine = - ((lpefr->fuFlags & SCFIND_REGEXP) && - (!StringCchCompareNA(szFind,FNDRPL_BUFFER,"$",-1) || - !StringCchCompareNA(szFind,FNDRPL_BUFFER,"^",-1) || - !StringCchCompareNA(szFind,FNDRPL_BUFFER,"^$",-1))); - - char* pszReplace = NULL; - int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; - if (StringCchCompareNA(lpefr->szReplace,FNDRPL_BUFFER,"^c",-1) == 0) { - iReplaceMsg = SCI_REPLACETARGET; - pszReplace = EditGetClipboardText(hwnd,TRUE,NULL,NULL); - } - else { - pszReplace = StrDupA(lpefr->szReplace); - if (!pszReplace) - pszReplace = StrDupA(""); - if (lpefr->bTransformBS) - TransformBackslashes(pszReplace,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); - } - - if (!pszReplace) - return FALSE; // recoding canceled - - int iPos = 0; - int iCount = 0; int start = 0; - int end = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0);; + int end = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - while ((iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end)) >= 0) - { - if ((iCount == 0) && bRegexStartOrEndOfLine) { - if (0 == SendMessage(hwnd,SCI_GETLINEENDPOSITION,0,0)) { - iPos = 0; - start = 0; - end = 0; - } - } + int iCount = EditReplaceAllInRange(hwnd, lpefr, bShowInfo, start, end); - if (++iCount == 1) - SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0); - - SendMessage(hwnd,SCI_SETTARGETSTART,start,0); - SendMessage(hwnd,SCI_SETTARGETEND,end,0); - int iReplacedLen = (int)SendMessage(hwnd,iReplaceMsg,(WPARAM)-1,(LPARAM)pszReplace); - - start += iReplacedLen; - end = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - - if (start == end) - break; - - //char ch = (char)SendMessage(hwnd,SCI_GETCHARAT,SendMessage(hwnd,SCI_GETTARGETEND,0,0),0); - - if (/*ch == '\r' || ch == '\n' || iReplacedLen == 0 || */ - (start == end) && !(bRegexStartOrEndOfLine && (iReplacedLen > 0))) - start = (int)SendMessage(hwnd,SCI_POSITIONAFTER,start,0); - - if (bRegexStartOfLine) { - int iLine = (int)SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)start,0); - int ilPos = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine,0); - if (ilPos == start) - start = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine+1,0); - - if (start == end) - break; - } - } - - if (iCount) - SendMessage(hwnd,SCI_ENDUNDOACTION,0,0); - - // Remove wait cursor - EndWaitCursor(); - - if (bShowInfo) { - if (iCount > 0) - InfoBox(0,L"MsgReplaceCount",IDS_REPLCOUNT,iCount); - else - InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); - } - - LocalFree(pszReplace); - return TRUE; + return (iCount > 0) ? TRUE : FALSE; } @@ -5487,104 +5316,14 @@ BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo MsgBox(MBWARN, IDS_SELRECT); return FALSE; } - - // Show wait cursor... - BeginWaitCursor(); int token = BeginSelUndoAction(); - char szFind[FNDRPL_BUFFER]; - StringCchCopyNA(szFind,COUNTOF(szFind),lpefr->szFind,COUNTOF(lpefr->szFind)); - if (lpefr->bTransformBS) - TransformBackslashes(szFind,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); - - int slen = StringCchLenA(szFind, COUNTOF(szFind)); - if (slen == 0) - { - InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); - return FALSE; - } - - if( lpefr->bWildcardSearch ) EscapeWildcards( szFind , lpefr ); - - BOOL bRegexStartOfLine = (szFind[0] == '^'); - BOOL bRegexStartOrEndOfLine = ((lpefr->fuFlags & SCFIND_REGEXP) && - (!StringCchCompareNA(szFind,FNDRPL_BUFFER,"$",-1) || - !StringCchCompareNA(szFind,FNDRPL_BUFFER,"^",-1) || - !StringCchCompareNA(szFind,FNDRPL_BUFFER,"^$",-1))); - - char* pszReplace = NULL; - int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; - if (StringCchCompareNA(lpefr->szReplace,FNDRPL_BUFFER,"^c",-1) == 0) { - iReplaceMsg = SCI_REPLACETARGET; - pszReplace = EditGetClipboardText(hwnd,TRUE,NULL,NULL); - } - else { - //lstrcpyA(szReplace2,lpefr->szReplace); - pszReplace = StrDupA(lpefr->szReplace); - if (!pszReplace) - pszReplace = StrDupA(""); - if (lpefr->bTransformBS) - TransformBackslashes(pszReplace,(lpefr->fuFlags & SCFIND_REGEXP),Encoding_SciGetCodePage(hwnd)); - } - - if (!pszReplace) - return FALSE; // recoding canceled - - - int iPos; - int iCount = 0; - BOOL fCancel = FALSE; int start = (int)SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0); int end = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); - while ((iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end)) >= 0 && !fCancel) - { - if (start >= SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0) && - end <= SendMessage(hwnd,SCI_GETSELECTIONEND,0,0)) - { - if ((start == 0) && (iCount == 0) && bRegexStartOrEndOfLine) { - if (0 == SendMessage(hwnd,SCI_GETLINEENDPOSITION,0,0)) { - iPos = 0; - start = 0; - end = 0; - } - } + int iCount = EditReplaceAllInRange(hwnd, lpefr, bShowInfo, start, end); - if (++iCount == 1) - SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0); - - SendMessage(hwnd, SCI_SETTARGETRANGE, start, end); - int iReplacedLen = (int)SendMessage(hwnd,iReplaceMsg,(WPARAM)-1,(LPARAM)pszReplace); - - start += iReplacedLen; - end = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0) + (iCount * iReplacedLen); - - if (start == end) - fCancel = TRUE; - - //char ch = (char)SendMessage(hwnd,SCI_GETCHARAT,SendMessage(hwnd,SCI_GETTARGETEND,0,0),0); - - if (/*ch == '\r' || ch == '\n' || iReplacedLen == 0 || */ - (start == end) && !(bRegexStartOrEndOfLine && (iReplacedLen > 0))) - start = (int)SendMessage(hwnd,SCI_POSITIONAFTER,start,0); - - if (bRegexStartOfLine) { - int iLine = (int)SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)start,0); - int ilPos = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine,0); - if (ilPos == start) - start = (int)SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine+1,0); - - if (start == end) - break; - } - } - - else - // gone across selection, cancel - fCancel = TRUE; - } - - if (iCount) { + if (iCount > 0) { if (SendMessage(hwnd,SCI_GETSELECTIONEND,0,0) < SendMessage(hwnd,SCI_GETTARGETEND,0,0)) { @@ -5598,27 +5337,210 @@ BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo EditSelectEx(hwnd,iAnchorPos,iCurrentPos); } - - SendMessage(hwnd,SCI_ENDUNDOACTION,0,0); } - // Remove wait cursor EndSelUndoAction(token); - EndWaitCursor(); + return (iCount > 0) ? TRUE : FALSE; +} - if (bShowInfo) { - if (iCount > 0) - InfoBox(0,L"MsgReplaceCount",IDS_REPLCOUNT,iCount); - else - InfoBox(0,L"MsgNotFound",IDS_NOTFOUND); + +//============================================================================= +// +// CompleteWord() +// Auto-complete words (by Aleksandar Lekov) +// +struct WLIST { + char* word; + struct WLIST* next; +}; + +void CompleteWord(HWND hwnd, BOOL autoInsert) { + const char* NON_WORD = bAccelWordNavigation ? DelimCharsAccel : DelimChars; + + int iCurrentPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); + int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iCurrentPos, 0); + int iCurrentLinePos = iCurrentPos - (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); + int iStartWordPos = iCurrentLinePos; + struct Sci_TextRange tr = { { 0, -1 }, NULL }; + BOOL bWordAllNumbers = TRUE; + struct WLIST* lListHead = NULL; + int iWListSize = 0; + + char* pLine = LocalAlloc(LPTR, (int)SendMessage(hwnd, SCI_GETLINE, (WPARAM)iLine, 0) + 1); + SendMessage(hwnd, SCI_GETLINE, (WPARAM)iLine, (LPARAM)pLine); + + while (iStartWordPos > 0 && !StrChrIA(NON_WORD, pLine[iStartWordPos - 1])) { + iStartWordPos--; + if (pLine[iStartWordPos] < '0' || pLine[iStartWordPos] > '9') { + bWordAllNumbers = FALSE; + } } - LocalFree(pszReplace); - return TRUE; + if (iStartWordPos == iCurrentLinePos || bWordAllNumbers || iCurrentLinePos - iStartWordPos < 2) { + LocalFree(pLine); + return; + } + int cnt = iCurrentLinePos - iStartWordPos; + char* pRoot = LocalAlloc(LPTR, cnt + 1); + StringCchCopyNA(pRoot, cnt + 1, pLine + iStartWordPos, cnt); + LocalFree(pLine); + + int iRootLen = StringCchLenA(pRoot, cnt + 1); + int iDocLen = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); + + int start = 0; + int end = iDocLen; + + int iPosFind = EditFindInTarget(hwnd, pRoot, iRootLen, SCFIND_WORDSTART, &start, &end); + + int iNumWords = 0; + char* pWord = NULL; + while (iPosFind >= 0 && iPosFind < iDocLen) { + int wordEnd = iPosFind + iRootLen; + + if (iPosFind != iCurrentPos - iRootLen) { + while (wordEnd < iDocLen && !StrChrIA(NON_WORD, (char)SendMessage(hwnd, SCI_GETCHARAT, (WPARAM)wordEnd, 0))) + wordEnd++; + + int wordLength = wordEnd - iPosFind; + if (wordLength > iRootLen) { + struct WLIST* p = lListHead; + struct WLIST* t = NULL; + //int lastCmp = 0; + BOOL found = FALSE; + + pWord = LocalAlloc(LPTR, wordLength + 1); + + tr.lpstrText = pWord; + tr.chrg.cpMin = iPosFind; + tr.chrg.cpMax = wordEnd; + SendMessage(hwnd, SCI_GETTEXTRANGE, 0, (LPARAM)&tr); + + while (p) { + int cmp = StringCchCompareNA(pWord, wordLength + 1, p->word, -1); + if (cmp == 0) { + found = TRUE; + break; + } + else if (cmp < 0) { + break; + } + t = p; + p = p->next; + } + if (!found) { + struct WLIST* el = (struct WLIST*)LocalAlloc(LPTR, sizeof(struct WLIST)); + el->word = LocalAlloc(LPTR, wordLength + 1); + StringCchCopyA(el->word, wordLength + 1, pWord); + el->next = p; + if (t) { + t->next = el; + } + else { + lListHead = el; + } + + iNumWords++; + iWListSize += StringCchLenA(pWord, wordLength + 1) + 1; + } + LocalFree(pWord); + } + } + start = wordEnd; end = iDocLen; + iPosFind = EditFindInTarget(hwnd, pRoot, iRootLen, SCFIND_WORDSTART, &start, &end); + } + + if (iNumWords > 0) { + char *pList; + struct WLIST* p = lListHead; + struct WLIST* t; + + pList = LocalAlloc(LPTR, iWListSize + 1); + while (p) { + StringCchCatA(pList, iWListSize + 1, " "); + StringCchCatA(pList, iWListSize + 1, p->word); + LocalFree(p->word); + t = p; + p = p->next; + LocalFree(t); + } + + SendMessage(hwnd, SCI_AUTOCSETIGNORECASE, 1, 0); + SendMessage(hwnd, SCI_AUTOCSETSEPARATOR, ' ', 0); + SendMessage(hwnd, SCI_AUTOCSETFILLUPS, 0, (LPARAM)"\t\n\r"); + SendMessage(hwnd, SCI_AUTOCSETCHOOSESINGLE, autoInsert, 0); + SendMessage(hwnd, SCI_AUTOCSHOW, iRootLen, (LPARAM)(pList + 1)); + LocalFree(pList); + } + + LocalFree(pRoot); } +//============================================================================= +// +// EditHighlightIfBrace() +// +BOOL __fastcall EditHighlightIfBrace(HWND hwnd, int iPos) { + if (iPos < 0) { + // clear indicator + SendMessage(hwnd, SCI_BRACEBADLIGHT, (WPARAM)INVALID_POSITION, 0); + SendMessage(hwnd, SCI_SETHIGHLIGHTGUIDE, 0, 0); + if (!bUseOldStyleBraceMatching) + SendMessage(hwnd, SCI_BRACEBADLIGHTINDICATOR, 0, INDIC_NP3_BAD_BRACE); + return TRUE; + } + char c = (char)SendMessage(hwnd, SCI_GETCHARAT, iPos, 0); + if (StrChrA("()[]{}", c)) { + int iBrace2 = (int)SendMessage(hwnd, SCI_BRACEMATCH, iPos, 0); + if (iBrace2 != -1) { + int col1 = (int)SendMessage(hwnd, SCI_GETCOLUMN, iPos, 0); + int col2 = (int)SendMessage(hwnd, SCI_GETCOLUMN, iBrace2, 0); + SendMessage(hwnd, SCI_BRACEHIGHLIGHT, iPos, iBrace2); + SendMessage(hwnd, SCI_SETHIGHLIGHTGUIDE, min(col1, col2), 0); + if (!bUseOldStyleBraceMatching) + SendMessage(hwnd, SCI_BRACEHIGHLIGHTINDICATOR, 1, INDIC_NP3_MATCH_BRACE); + } + else { + SendMessage(hwnd, SCI_BRACEBADLIGHT, iPos, 0); + SendMessage(hwnd, SCI_SETHIGHLIGHTGUIDE, 0, 0); + if (!bUseOldStyleBraceMatching) + SendMessage(hwnd, SCI_BRACEBADLIGHTINDICATOR, 1, INDIC_NP3_BAD_BRACE); + } + return TRUE; + } + return FALSE; +} + + + +//============================================================================= +// +// EditMatchBrace() +// +void EditMatchBrace(HWND hwnd) { + int iEndStyled = (int)SendMessage(hwnd, SCI_GETENDSTYLED, 0, 0); + if (iEndStyled < (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0)) { + int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iEndStyled, 0); + int iEndStyled2 = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, iLine, 0); + SendMessage(hwnd, SCI_COLOURISE, iEndStyled2, -1); + } + + int iPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); + + if (!EditHighlightIfBrace(hwnd, iPos)) { + // try one before + iPos = (int)SendMessage(hwnd, SCI_POSITIONBEFORE, iPos, 0); + if (!EditHighlightIfBrace(hwnd, iPos)) { + // clear mark + EditHighlightIfBrace(hwnd, -1); + } + } +} + + + //============================================================================= // // EditLinenumDlgProc() diff --git a/src/Edit.h b/src/Edit.h index 5b48fba87..2b4677981 100644 --- a/src/Edit.h +++ b/src/Edit.h @@ -103,6 +103,7 @@ HWND EditFindReplaceDlg(HWND,LPCEDITFINDREPLACE,BOOL); BOOL EditFindNext(HWND,LPCEDITFINDREPLACE,BOOL); BOOL EditFindPrev(HWND,LPCEDITFINDREPLACE,BOOL); BOOL EditReplace(HWND,LPCEDITFINDREPLACE); +int EditReplaceAllInRange(HWND,LPCEDITFINDREPLACE,BOOL,int,int); BOOL EditReplaceAll(HWND,LPCEDITFINDREPLACE,BOOL); BOOL EditReplaceAllInSelection(HWND,LPCEDITFINDREPLACE,BOOL); BOOL EditLinenumDlg(HWND); diff --git a/src/Helpers.h b/src/Helpers.h index 3e68c0b66..392d1e7e2 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -32,6 +32,8 @@ extern WCHAR szIniFile[MAX_PATH]; +__inline void swapi(int a, int b) { int t = a; a = b; b = t; } + #define IniGetString(lpSection,lpName,lpDefault,lpReturnedStr,nSize) \ GetPrivateProfileString(lpSection,lpName,(lpDefault),(lpReturnedStr),(nSize),szIniFile) #define IniGetInt(lpSection,lpName,nDefault) \ From cce20566f84fde6e5528676b764138a11dead99b Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sat, 28 Oct 2017 02:07:04 +0200 Subject: [PATCH 04/11] + move position after replacement (EditReplace()) --- src/Edit.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index d4e335bad..856cbe01e 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -5077,11 +5077,14 @@ BOOL EditReplace(HWND hwnd, LPCEDITFINDREPLACE lpefr) { return FALSE; // recoding of clipboard canceled SendMessage(hwnd, SCI_TARGETFROMSELECTION, 0, 0); - SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); - + LocalFree(pszReplace); + // move behind replacement + int after = (int)SendMessage(hwnd, SCI_POSITIONAFTER, (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0), 0); + SendMessage(hwnd, SCI_SETSEL, after, after); + return EditFindNext(hwnd, lpefr, FALSE); } From 990d826570551941a5be81dbb2351c5bf945009c Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sat, 28 Oct 2017 14:01:01 +0200 Subject: [PATCH 05/11] + fix problem with regex line start and replacements at line end --- src/Edit.c | 360 +++++++++++++++++++++++++---------------------------- 1 file changed, 169 insertions(+), 191 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index 856cbe01e..aa1a64fa7 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -4902,6 +4902,23 @@ int __fastcall EditFindInTarget(HWND hwnd, LPCSTR szFind, int length, int flags, } +//============================================================================= +// +// EditRegexCorrectLineStart() +// +void __fastcall EditRegexCorrectLineStart(HWND hwnd, LPSTR szFind, int* start) +{ + //char* pRegexStOfLn = (char*)StrStrA(szFind, "^"); + if (szFind[0] == '^') { + int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, (WPARAM)*start, 0); + int ilPos = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); // begining of current line + // start search at next line, if not already at begin of line + if (ilPos != *start) { + *start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)(iLine + 1), 0); // begining of next line + } + } +} + //============================================================================= // // EditFindNext() @@ -4933,19 +4950,15 @@ BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { int start = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); int end = iDocLength; - BOOL bRegexStartOfLine = (lpefr->fuFlags & SCFIND_REGEXP) && (szFind[0] == '^'); - if (bRegexStartOfLine) { - int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, (WPARAM)start, 0); - int ilPos = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); // begining of current line - if (ilPos != start) - start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)(iLine + 1), 0); // begining of next line - if (start >= end) { - if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { - end = start; start = 0; - } - else - bSuppressNotFound = TRUE; + if (lpefr->fuFlags & SCFIND_REGEXP) { + EditRegexCorrectLineStart(hwnd, szFind, &start); + } + if (start >= end) { + if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { + end = start; start = 0; } + else + bSuppressNotFound = TRUE; } int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); @@ -5007,19 +5020,15 @@ BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { int start = max(0, (int)SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0)); int end = 0; - BOOL bRegexStartOfLine = (lpefr->fuFlags & SCFIND_REGEXP) && (szFind[0] == '^'); - if (bRegexStartOfLine) { - int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, (WPARAM)start, 0); - int ilPos = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); // begining of current line - if (ilPos != start) - start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)(iLine + 1), 0); // begining of previous line - //if (end >= start) { - // if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { - // end = start; start = iDocLength; - // } - // else - // bSuppressNotFound = TRUE; - //} + if (lpefr->fuFlags & SCFIND_REGEXP) { + EditRegexCorrectLineStart(hwnd, szFind, &start); + } + if (start <= end) { + if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { + end = start; start = iDocLength; + } + else + bSuppressNotFound = TRUE; } int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); @@ -5046,7 +5055,29 @@ BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { EditSelectEx(hwnd, max(iSelPos, iSelAnchor), start); return TRUE; +} + +//============================================================================= +// +// EditGetReplaceString() +// +char* __fastcall EditGetReplaceString(HWND hwnd, LPCEDITFINDREPLACE lpefr, int* iReplaceMsg) +{ + char* pszReplace = NULL; // replace text of arbitrary size + *iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; + if (StringCchCompareNA(lpefr->szReplace, FNDRPL_BUFFER, "^c", -1) == 0) { + *iReplaceMsg = SCI_REPLACETARGET; + pszReplace = EditGetClipboardText(hwnd, TRUE, NULL, NULL); + } + else { + pszReplace = StrDupA(lpefr->szReplace); + if (!pszReplace) + pszReplace = StrDupA(""); + if (lpefr->bTransformBS) + TransformBackslashes(pszReplace, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); + } + return pszReplace; } @@ -5059,117 +5090,25 @@ BOOL EditReplace(HWND hwnd, LPCEDITFINDREPLACE lpefr) { if ((BOOL)SendMessage(hwnd, SCI_GETSELECTIONEMPTY, 0, 0)) return EditFindNext(hwnd, lpefr, FALSE); - char* pszReplace; // replace text of arbitrary size - int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; - if (StringCchCompareNA(lpefr->szReplace, FNDRPL_BUFFER, "^c", -1) == 0) { - iReplaceMsg = SCI_REPLACETARGET; - pszReplace = EditGetClipboardText(hwnd, TRUE, NULL, NULL); - } - else { - pszReplace = StrDupA(lpefr->szReplace); - if (!pszReplace) - pszReplace = StrDupA(""); - if (lpefr->bTransformBS) - TransformBackslashes(pszReplace, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); - } - + int iReplaceMsg = SCI_REPLACETARGET; + char* pszReplace = EditGetReplaceString(hwnd, lpefr, &iReplaceMsg); if (!pszReplace) return FALSE; // recoding of clipboard canceled + // w/o selection, replacement string is put into current position SendMessage(hwnd, SCI_TARGETFROMSELECTION, 0, 0); SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); LocalFree(pszReplace); - - // move behind replacement - int after = (int)SendMessage(hwnd, SCI_POSITIONAFTER, (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0), 0); + + // move caret behind replacement + int after = (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0); SendMessage(hwnd, SCI_SETSEL, after, after); return EditFindNext(hwnd, lpefr, FALSE); } -//============================================================================= -// -// EditMarkAll() -// Mark all occurrences of the text currently selected (by Aleksandar Lekov) -// -void EditMarkAll(HWND hwnd, BOOL bMarkOccurrencesMatchCase, BOOL bMarkOccurrencesMatchWords) -{ - iMarkOccurrencesCount = -1; // -1 ! - - // feature is off - if (!iMarkOccurrences) { - UpdateStatusbar(); - return; - } - - int iTextLen = (int)SendMessage(hwnd,SCI_GETLENGTH,0,0); - - // get current selection - int iSelStart = (int)SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0); - int iSelEnd = (int)SendMessage(hwnd,SCI_GETSELECTIONEND,0,0); - int iSelCount = iSelEnd - iSelStart; - - // clear existing marker indicators - SendMessage(hwnd, SCI_SETINDICATORCURRENT, INDIC_NP3_MARK_OCCURANCE, 0); - SendMessage(hwnd, SCI_INDICATORCLEARRANGE, 0, iTextLen); - - // if nothing selected or multiple lines are selected exit - if ((iSelCount == 0) || - (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iSelStart, 0) != - (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iSelEnd, 0)) - return; - - int iSelLength = (int)SendMessage(hwnd, SCI_GETSELTEXT, 0, (LPARAM)NULL) - 1; - char* pszText = LocalAlloc(LPTR,iSelLength+1); - (int)SendMessage(hwnd,SCI_GETSELTEXT,0,(LPARAM)pszText); - - - // exit if selection is not a word and Match whole words only is enabled - if (bMarkOccurrencesMatchWords) - { - int iSelStart2 = 0; - const char* delims = (bAccelWordNavigation ? DelimCharsAccel : DelimChars); - while ((iSelStart2 <= iSelCount) && pszText[iSelStart2]) - { - if (StrChrIA(delims,pszText[iSelStart2])) - { - LocalFree(pszText); - return; - } - iSelStart2++; - } - } - - int flags = (bMarkOccurrencesMatchCase ? SCFIND_MATCHCASE : 0); - flags |= (bMarkOccurrencesMatchWords ? SCFIND_WHOLEWORD : 0); - - int iPos = 0; - int start = 0; - int end = iTextLen; - - while (++iMarkOccurrencesCount < iMarkOccurrencesMaxCount) - { - iPos = EditFindInTarget(hwnd, pszText, iSelLength, flags, &start, &end); - - if (iPos < 0) - break; // not found - - // mark this match - SendMessage(hwnd, SCI_INDICATORFILLRANGE, iPos, iSelCount); - start = end + 1; end = iTextLen; - - if (start >= end) - break; - } - - LocalFree(pszText); - UpdateStatusbar(); -} - - - //============================================================================= // // EditReplaceAllInRange() @@ -5196,81 +5135,46 @@ int EditReplaceAllInRange(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bShowInfo, i if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); - BOOL bRegexStartOfLine = (lpefr->fuFlags & SCFIND_REGEXP) && (szFind[0] == '^'); - - BOOL bRegexStartOrEndOfLine = ((lpefr->fuFlags & SCFIND_REGEXP) && - (!StringCchCompareNA(szFind, FNDRPL_BUFFER, "$", -1) || - !StringCchCompareNA(szFind, FNDRPL_BUFFER, "^", -1) || - !StringCchCompareNA(szFind, FNDRPL_BUFFER, "^$", -1))); - - char* pszReplace = NULL; - int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; - if (StringCchCompareNA(lpefr->szReplace, FNDRPL_BUFFER, "^c", -1) == 0) { - iReplaceMsg = SCI_REPLACETARGET; - pszReplace = EditGetClipboardText(hwnd, TRUE, NULL, NULL); - } - else { - pszReplace = StrDupA(lpefr->szReplace); - if (!pszReplace) - pszReplace = StrDupA(""); - if (lpefr->bTransformBS) - TransformBackslashes(pszReplace, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); - } - + int iReplaceMsg = SCI_REPLACETARGET; + char* pszReplace = EditGetReplaceString(hwnd, lpefr, &iReplaceMsg); if (!pszReplace) - return -1; // recoding canceled + return -1; // recoding of clipboard canceled + + int start = iStartPos; + int end = iEndPos; + + if (lpefr->fuFlags & SCFIND_REGEXP) { + EditRegexCorrectLineStart(hwnd, szFind, &start); + } int iPos; int iCount = 0; - BOOL fCancel = FALSE; - int start = iStartPos; - int end = iEndPos; - while ((iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end)) >= 0 && !fCancel) + while ((start < end) && ((iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end)) >= 0)) { - if ((start >= iStartPos) && (end <= iEndPos)) - { - if ((start == 0) && (iCount == 0) && bRegexStartOrEndOfLine) { - if (0 == SendMessage(hwnd, SCI_GETLINEENDPOSITION, 0, 0)) { - iPos = 0; - start = 0; - end = 0; - } - } - - if (++iCount == 1) - SendMessage(hwnd, SCI_BEGINUNDOACTION, 0, 0); - - SendMessage(hwnd, SCI_SETTARGETRANGE, start, end); - int iReplacedLen = (int)SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); - - start += iReplacedLen; - iEndPos = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0) - iDiffToDocEnd; - end = iEndPos; - - if (start >= end) - fCancel = TRUE; - - //char ch = (char)SendMessage(hwnd,SCI_GETCHARAT,SendMessage(hwnd,SCI_GETTARGETEND,0,0),0); - - if (/*ch == '\r' || ch == '\n' || iReplacedLen == 0 || */ - (start == end) && !(bRegexStartOrEndOfLine && (iReplacedLen > 0))) - start = (int)SendMessage(hwnd, SCI_POSITIONAFTER, start, 0); - - if (bRegexStartOfLine) { - int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, (WPARAM)start, 0); - int ilPos = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); - if (ilPos == start) - start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine + 1, 0); - - if (start == end) - break; - } + if (end > iEndPos) { + // found, but replace target end is beyond selection + break; // while + } + + if (++iCount == 1) + SendMessage(hwnd, SCI_BEGINUNDOACTION, 0, 0); + + // replace + int iReplLen = (int)SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); + + // move caret behind replacement; target region maybe extended by replacement + iEndPos = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0) - iDiffToDocEnd; + start += iReplLen; // == (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0); ? + end = iEndPos; + + // correction for regex + if (lpefr->fuFlags & SCFIND_REGEXP) { + EditRegexCorrectLineStart(hwnd, szFind, &start); } - else - // gone across range, cancel - fCancel = TRUE; } + LocalFree(pszReplace); + if (iCount) SendMessage(hwnd, SCI_ENDUNDOACTION, 0, 0); @@ -5283,7 +5187,6 @@ int EditReplaceAllInRange(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bShowInfo, i InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); } - LocalFree(pszReplace); return iCount; } @@ -5347,6 +5250,81 @@ BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo } +//============================================================================= +// +// EditMarkAll() +// Mark all occurrences of the text currently selected (by Aleksandar Lekov) +// +void EditMarkAll(HWND hwnd, BOOL bMarkOccurrencesMatchCase, BOOL bMarkOccurrencesMatchWords) +{ + iMarkOccurrencesCount = -1; // -1 ! + + if (!iMarkOccurrences) { // feature is off + UpdateStatusbar(); + return; + } + + int iTextLen = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); + + // get current selection + int iSelStart = (int)SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0); + int iSelEnd = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); + int iSelCount = iSelEnd - iSelStart; + + // clear existing marker indicators + SendMessage(hwnd, SCI_SETINDICATORCURRENT, INDIC_NP3_MARK_OCCURANCE, 0); + SendMessage(hwnd, SCI_INDICATORCLEARRANGE, 0, iTextLen); + + // if nothing selected or multiple lines are selected exit + if ((iSelCount == 0) || + (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iSelStart, 0) != + (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iSelEnd, 0)) + return; + + int iSelLength = (int)SendMessage(hwnd, SCI_GETSELTEXT, 0, (LPARAM)NULL) - 1; + char* pszText = LocalAlloc(LPTR, iSelLength + 1); + (int)SendMessage(hwnd, SCI_GETSELTEXT, 0, (LPARAM)pszText); + + + // exit if selection is not a word and Match whole words only is enabled + if (bMarkOccurrencesMatchWords) { + int iSelStart2 = 0; + const char* delims = (bAccelWordNavigation ? DelimCharsAccel : DelimChars); + while ((iSelStart2 <= iSelCount) && pszText[iSelStart2]) { + if (StrChrIA(delims, pszText[iSelStart2])) { + LocalFree(pszText); + return; + } + iSelStart2++; + } + } + + int flags = (bMarkOccurrencesMatchCase ? SCFIND_MATCHCASE : 0); + flags |= (bMarkOccurrencesMatchWords ? SCFIND_WHOLEWORD : 0); + + int iPos = 0; + int start = 0; + int end = iTextLen; + + while (++iMarkOccurrencesCount < iMarkOccurrencesMaxCount) { + iPos = EditFindInTarget(hwnd, pszText, iSelLength, flags, &start, &end); + + if (iPos < 0) + break; // not found + + // mark this match + SendMessage(hwnd, SCI_INDICATORFILLRANGE, iPos, iSelCount); + start = end + 1; end = iTextLen; + + if (start >= end) + break; + } + + LocalFree(pszText); + UpdateStatusbar(); +} + + //============================================================================= // // CompleteWord() From b23e5db63d46b141207449ebd10d8aff47aa9876 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sat, 28 Oct 2017 14:44:44 +0200 Subject: [PATCH 06/11] + enhanc comments by useful web links --- scintilla/deelx/deelx64.h | 8 ++++++-- src/Edit.c | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/scintilla/deelx/deelx64.h b/scintilla/deelx/deelx64.h index a63a33648..dab7bfccc 100644 --- a/scintilla/deelx/deelx64.h +++ b/scintilla/deelx/deelx64.h @@ -10,10 +10,14 @@ // Author: Ê·ÊÙΰ (sswater shi) // sswater@gmail.com // -// $Revision $ -// // + adaption for 64-bit usage: "basetsd : INT_PTR" replaces int-pointer arithmetic and buffer indexes // + Cppcheck cleanup +// +// Good Overview: +// https://www.regular-expressions.info/ +// + + #ifndef __DEELX_REGEXP64__H__ #define __DEELX_REGEXP64__H__ diff --git a/src/Edit.c b/src/Edit.c index aa1a64fa7..d7fa03eb9 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -5087,6 +5087,9 @@ char* __fastcall EditGetReplaceString(HWND hwnd, LPCEDITFINDREPLACE lpefr, int* // BOOL EditReplace(HWND hwnd, LPCEDITFINDREPLACE lpefr) { + // reject to replace zero-length matches -> EditPaste() + // see also: https://www.regular-expressions.info/zerolength.html + // if ((BOOL)SendMessage(hwnd, SCI_GETSELECTIONEMPTY, 0, 0)) return EditFindNext(hwnd, lpefr, FALSE); From 88d75d8929cf7d741fa8b0c418708525e938fd44 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sat, 28 Oct 2017 16:10:33 +0200 Subject: [PATCH 07/11] + fixing bug regarding find "zero-length matches" --- src/Edit.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index d7fa03eb9..d6e3572bd 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -4891,12 +4891,31 @@ void EscapeWildcards(char* szFind2, LPCEDITFINDREPLACE lpefr) // int __fastcall EditFindInTarget(HWND hwnd, LPCSTR szFind, int length, int flags, int* start, int* end) { + int tbeg = *start; + int tend = *end; + int iPos = -1; SendMessage(hwnd, SCI_SETSEARCHFLAGS, flags, 0); - SendMessage(hwnd, SCI_SETTARGETRANGE, (*start), (*end)); - int iPos = (int)SendMessage(hwnd, SCI_SEARCHINTARGET, length, (LPARAM)szFind); - if (iPos >= 0) { - *start = (int)SendMessage(hwnd, SCI_GETTARGETSTART, 0, 0); - *end = (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0); + while (TRUE) { + SendMessage(hwnd, SCI_SETTARGETRANGE, tbeg, tend); + iPos = (int)SendMessage(hwnd, SCI_SEARCHINTARGET, length, (LPARAM)szFind); + if (iPos < 0) { + break; // not found in range + } + else { + // found: get range + tbeg = (int)SendMessage(hwnd, SCI_GETTARGETSTART, 0, 0); + tend = (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0); + if (tbeg == tend) { + // zero-length match : search next + tbeg = (*start < *end) ? tbeg + 1 : tbeg - 1; + tend = *end; + } + else { // found: OK + *start = tbeg; + *end = tend; + break; + } + } } return iPos; } @@ -5155,7 +5174,7 @@ int EditReplaceAllInRange(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bShowInfo, i while ((start < end) && ((iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end)) >= 0)) { if (end > iEndPos) { - // found, but replace target end is beyond selection + // not found or replace target end is beyond selection break; // while } @@ -5315,7 +5334,7 @@ void EditMarkAll(HWND hwnd, BOOL bMarkOccurrencesMatchCase, BOOL bMarkOccurrence if (iPos < 0) break; // not found - // mark this match + // mark this match SendMessage(hwnd, SCI_INDICATORFILLRANGE, iPos, iSelCount); start = end + 1; end = iTextLen; From ad5cba8716b5f0e54b6d81e11d4c9c8be85f84aa Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sun, 29 Oct 2017 01:07:14 +0200 Subject: [PATCH 08/11] + fix: RegEx start anchor adjustment --- src/Edit.c | 64 ++++++++++++++++++++---------------------------------- 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index d6e3572bd..2c212b8b4 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -4889,52 +4889,36 @@ void EscapeWildcards(char* szFind2, LPCEDITFINDREPLACE lpefr) // // EditFindInTarget() // -int __fastcall EditFindInTarget(HWND hwnd, LPCSTR szFind, int length, int flags, int* start, int* end) +int __fastcall EditFindInTarget(HWND hwnd, LPCSTR szFind, int length, int flags, int* start, int* end) { - int tbeg = *start; - int tend = *end; - int iPos = -1; SendMessage(hwnd, SCI_SETSEARCHFLAGS, flags, 0); - while (TRUE) { - SendMessage(hwnd, SCI_SETTARGETRANGE, tbeg, tend); - iPos = (int)SendMessage(hwnd, SCI_SEARCHINTARGET, length, (LPARAM)szFind); - if (iPos < 0) { - break; // not found in range - } - else { - // found: get range - tbeg = (int)SendMessage(hwnd, SCI_GETTARGETSTART, 0, 0); - tend = (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0); - if (tbeg == tend) { - // zero-length match : search next - tbeg = (*start < *end) ? tbeg + 1 : tbeg - 1; - tend = *end; - } - else { // found: OK - *start = tbeg; - *end = tend; - break; - } - } + SendMessage(hwnd, SCI_SETTARGETRANGE, *start, *end); + int iPos = (int)SendMessage(hwnd, SCI_SEARCHINTARGET, length, (LPARAM)szFind); + if (iPos >= 0) { // found in range + *start = (int)SendMessage(hwnd, SCI_GETTARGETSTART, 0, 0); + *end = (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0); } return iPos; } + //============================================================================= // -// EditRegexCorrectLineStart() +// EditSetRegexStartAnchor() // -void __fastcall EditRegexCorrectLineStart(HWND hwnd, LPSTR szFind, int* start) +void __fastcall EditSetRegexStartAnchor(HWND hwnd, LPSTR szFind, int* start, BOOL bFindNext) { - //char* pRegexStOfLn = (char*)StrStrA(szFind, "^"); if (szFind[0] == '^') { - int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, (WPARAM)*start, 0); - int ilPos = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); // begining of current line - // start search at next line, if not already at begin of line - if (ilPos != *start) { - *start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)(iLine + 1), 0); // begining of next line - } + int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, *start, 0); + if (bFindNext) + *start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (iLine + 1), 0); // begining of next line + } + else if (szFind[0] == '$') { + int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, *start, 0); + int iLnEnd = (int)SendMessage(hwnd, SCI_GETLINEENDPOSITION, iLine, 0); + if (bFindNext && (iLnEnd == *start)) + *start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (iLine + 1), 0); // begining of next line } } @@ -4970,7 +4954,7 @@ BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { int end = iDocLength; if (lpefr->fuFlags & SCFIND_REGEXP) { - EditRegexCorrectLineStart(hwnd, szFind, &start); + EditSetRegexStartAnchor(hwnd, szFind, &start, TRUE); } if (start >= end) { if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { @@ -5040,7 +5024,7 @@ BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { int end = 0; if (lpefr->fuFlags & SCFIND_REGEXP) { - EditRegexCorrectLineStart(hwnd, szFind, &start); + EditSetRegexStartAnchor(hwnd, szFind, &start, FALSE); } if (start <= end) { if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { @@ -5109,8 +5093,8 @@ BOOL EditReplace(HWND hwnd, LPCEDITFINDREPLACE lpefr) { // reject to replace zero-length matches -> EditPaste() // see also: https://www.regular-expressions.info/zerolength.html // - if ((BOOL)SendMessage(hwnd, SCI_GETSELECTIONEMPTY, 0, 0)) - return EditFindNext(hwnd, lpefr, FALSE); + //if ((BOOL)SendMessage(hwnd, SCI_GETSELECTIONEMPTY, 0, 0)) + // return EditFindNext(hwnd, lpefr, FALSE); int iReplaceMsg = SCI_REPLACETARGET; char* pszReplace = EditGetReplaceString(hwnd, lpefr, &iReplaceMsg); @@ -5166,7 +5150,7 @@ int EditReplaceAllInRange(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bShowInfo, i int end = iEndPos; if (lpefr->fuFlags & SCFIND_REGEXP) { - EditRegexCorrectLineStart(hwnd, szFind, &start); + EditSetRegexStartAnchor(hwnd, szFind, &start, TRUE); } int iPos; @@ -5191,7 +5175,7 @@ int EditReplaceAllInRange(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bShowInfo, i // correction for regex if (lpefr->fuFlags & SCFIND_REGEXP) { - EditRegexCorrectLineStart(hwnd, szFind, &start); + EditSetRegexStartAnchor(hwnd, szFind, &start, TRUE); } } From 3e5dcfd2a808b47754c2b3447c696fbb0f65f199 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sun, 29 Oct 2017 19:00:57 +0100 Subject: [PATCH 09/11] + fix: more issues found regarding zero-length matches using regex anchors, including infinite loops on replace all --- src/Edit.c | 236 ++++++++++++++++++++++++++--------------------------- 1 file changed, 115 insertions(+), 121 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index 2c212b8b4..ff3e93f0b 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -4884,7 +4884,6 @@ void EscapeWildcards(char* szFind2, LPCEDITFINDREPLACE lpefr) } - //============================================================================= // // EditFindInTarget() @@ -4894,7 +4893,8 @@ int __fastcall EditFindInTarget(HWND hwnd, LPCSTR szFind, int length, int flags, SendMessage(hwnd, SCI_SETSEARCHFLAGS, flags, 0); SendMessage(hwnd, SCI_SETTARGETRANGE, *start, *end); int iPos = (int)SendMessage(hwnd, SCI_SEARCHINTARGET, length, (LPARAM)szFind); - if (iPos >= 0) { // found in range + if (iPos >= 0) { + // found in range, set begin and end of finding *start = (int)SendMessage(hwnd, SCI_GETTARGETSTART, 0, 0); *end = (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0); } @@ -4902,59 +4902,82 @@ int __fastcall EditFindInTarget(HWND hwnd, LPCSTR szFind, int length, int flags, } - //============================================================================= // // EditSetRegexStartAnchor() +// beware of zero-length-matches (regex) ! +// see also : https://www.regular-expressions.info/zerolength.html // -void __fastcall EditSetRegexStartAnchor(HWND hwnd, LPSTR szFind, int* start, BOOL bFindNext) +void __fastcall EditRegexAdaptAnchors(HWND hwnd, LPSTR szFind, int* start, BOOL bFindNext) { - if (szFind[0] == '^') { + int len = StringCchLenA(szFind, FNDRPL_BUFFER); + int nx = 1; + char* pBeg = (char*)StrChrA(szFind, '^'); + BOOL esc1 = ((pBeg > szFind) && (*(--pBeg) == '\\')); + if (pBeg && !esc1) { int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, *start, 0); - if (bFindNext) - *start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (iLine + 1), 0); // begining of next line + int iLnBeg = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, iLine, 0); + int iLnEnd = (int)SendMessage(hwnd, SCI_GETLINEENDPOSITION, iLine, 0); + if (bFindNext && ((iLnBeg != *start) || (iLnEnd == *start) || (len == 1))) + *start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (iLine + nx--), 0); } - else if (szFind[0] == '$') { + char* pEnd = (char*)StrChrA(szFind, '$'); + BOOL esc2 = ((pEnd > szFind) && (*(--pEnd) == '\\')); + if (pEnd && !esc2) { int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, *start, 0); int iLnEnd = (int)SendMessage(hwnd, SCI_GETLINEENDPOSITION, iLine, 0); if (bFindNext && (iLnEnd == *start)) - *start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (iLine + 1), 0); // begining of next line + *start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (iLine + nx), 0); } } + +//============================================================================= +// +// EditGetFindStrg() +// +int __fastcall EditGetFindStrg(HWND hwnd, LPCEDITFINDREPLACE lpefr, LPSTR szFind, int cchCnt) +{ + if (!StringCchLenA(lpefr->szFind, COUNTOF(lpefr->szFind))) + return 0; + + StringCchCopyA(szFind, cchCnt, lpefr->szFind); + + if (lpefr->bTransformBS) + TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); + + int slen = StringCchLenA(szFind, COUNTOF(szFind)); + + if (slen == 0) + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); + else + if (lpefr->bWildcardSearch) + EscapeWildcards(szFind, lpefr); + + return slen; +} + + //============================================================================= // // EditFindNext() // -BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { +BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bExtendSelection) { char szFind[FNDRPL_BUFFER]; BOOL bSuppressNotFound = FALSE; - if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) - return /*EditFindReplaceDlg(hwnd,lpefr,FALSE)*/FALSE; - - StringCchCopyNA(szFind, COUNTOF(szFind), lpefr->szFind, COUNTOF(lpefr->szFind)); - if (lpefr->bTransformBS) - TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); - - int slen = StringCchLenA(szFind, COUNTOF(szFind)); - if (slen == 0) { - InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); + int slen = EditGetFindStrg(hwnd, lpefr, szFind, COUNTOF(szFind)); + if (slen <= 0) return FALSE; - } - if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); int iDocLength = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - int iSelPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); - int iSelAnchor = (int)SendMessage(hwnd, SCI_GETANCHOR, 0, 0); - int start = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); int end = iDocLength; if (lpefr->fuFlags & SCFIND_REGEXP) { - EditSetRegexStartAnchor(hwnd, szFind, &start, TRUE); + EditRegexAdaptAnchors(hwnd, szFind, &start, TRUE); } if (start >= end) { if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { @@ -4966,7 +4989,7 @@ BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); - if ((iPos < 0) && (start > 0) && !lpefr->bNoFindWrap && !fExtendSelection && !bSuppressNotFound) { + if ((iPos < 0) && (start > 0) && !lpefr->bNoFindWrap && !bExtendSelection && !bSuppressNotFound) { if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { end = start; start = 0; iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); @@ -4976,19 +4999,20 @@ BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { } if (iPos < 0) { - // notfound if (!bSuppressNotFound) InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); return FALSE; } - if (!fExtendSelection) - EditSelectEx(hwnd, start, end); - else + if (bExtendSelection) { + int iSelPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); + int iSelAnchor = (int)SendMessage(hwnd, SCI_GETANCHOR, 0, 0); EditSelectEx(hwnd, min(iSelAnchor, iSelPos), end); - + } + else { + EditSelectEx(hwnd, start, end); + } return TRUE; - } @@ -4996,39 +5020,26 @@ BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { // // EditFindPrev() // -BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { +BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bExtendSelection) { char szFind[FNDRPL_BUFFER]; BOOL bSuppressNotFound = FALSE; - if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) - return /*EditFindReplaceDlg(hwnd,lpefr,FALSE)*/FALSE; - - StringCchCopyNA(szFind, COUNTOF(szFind), lpefr->szFind, COUNTOF(lpefr->szFind)); - if (lpefr->bTransformBS) - TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); - - int slen = StringCchLenA(szFind, COUNTOF(szFind)); - if (slen == 0) { - InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); + int slen = EditGetFindStrg(hwnd, lpefr, szFind, COUNTOF(szFind)); + if (slen <= 0) return FALSE; - } - if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); int iDocLength = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); - int iSelPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); - int iSelAnchor = (int)SendMessage(hwnd, SCI_GETANCHOR, 0, 0); - int start = max(0, (int)SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0)); int end = 0; if (lpefr->fuFlags & SCFIND_REGEXP) { - EditSetRegexStartAnchor(hwnd, szFind, &start, FALSE); + EditRegexAdaptAnchors(hwnd, szFind, &start, FALSE); } if (start <= end) { if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { - end = start; start = iDocLength; + end = start; end = iDocLength; } else bSuppressNotFound = TRUE; @@ -5036,7 +5047,7 @@ BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); - if ((iPos < 0) && (start < iDocLength) && !lpefr->bNoFindWrap && !fExtendSelection && !bSuppressNotFound) { + if ((iPos < 0) && (start < iDocLength) && !lpefr->bNoFindWrap && !bExtendSelection && !bSuppressNotFound) { if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap2", IDS_FIND_WRAPRE)) { end = start; start = iDocLength; iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); @@ -5046,17 +5057,19 @@ BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL fExtendSelection) { } if (iPos < 0) { - // notfound if (!bSuppressNotFound) InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); return FALSE; } - if (!fExtendSelection) - EditSelectEx(hwnd, start, end); - else + if (bExtendSelection) { + int iSelPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); + int iSelAnchor = (int)SendMessage(hwnd, SCI_GETANCHOR, 0, 0); EditSelectEx(hwnd, max(iSelPos, iSelAnchor), start); - + } + else { + EditSelectEx(hwnd, start, end); + } return TRUE; } @@ -5090,12 +5103,6 @@ char* __fastcall EditGetReplaceString(HWND hwnd, LPCEDITFINDREPLACE lpefr, int* // BOOL EditReplace(HWND hwnd, LPCEDITFINDREPLACE lpefr) { - // reject to replace zero-length matches -> EditPaste() - // see also: https://www.regular-expressions.info/zerolength.html - // - //if ((BOOL)SendMessage(hwnd, SCI_GETSELECTIONEMPTY, 0, 0)) - // return EditFindNext(hwnd, lpefr, FALSE); - int iReplaceMsg = SCI_REPLACETARGET; char* pszReplace = EditGetReplaceString(hwnd, lpefr, &iReplaceMsg); if (!pszReplace) @@ -5121,71 +5128,59 @@ BOOL EditReplace(HWND hwnd, LPCEDITFINDREPLACE lpefr) { // int EditReplaceAllInRange(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bShowInfo, int iStartPos, int iEndPos) { - BeginWaitCursor(); + char szFind[FNDRPL_BUFFER]; if (iStartPos > iEndPos) swapi(iStartPos, iEndPos); - int iDiffToDocEnd = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0) - iEndPos; - - char szFind[FNDRPL_BUFFER]; - StringCchCopyNA(szFind, COUNTOF(szFind), lpefr->szFind, COUNTOF(lpefr->szFind)); - if (lpefr->bTransformBS) - TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); - - int slen = StringCchLenA(szFind, COUNTOF(szFind)); - if (slen == 0) { - InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); + int slen = EditGetFindStrg(hwnd, lpefr, szFind, COUNTOF(szFind)); + if (slen <= 0) return 0; - } - - if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); int iReplaceMsg = SCI_REPLACETARGET; char* pszReplace = EditGetReplaceString(hwnd, lpefr, &iReplaceMsg); if (!pszReplace) return -1; // recoding of clipboard canceled + int iDiffToDocEnd = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0) - iEndPos; + + BeginWaitCursor(); + + int iPos = 0; + int iCount = 0; int start = iStartPos; int end = iEndPos; - - if (lpefr->fuFlags & SCFIND_REGEXP) { - EditSetRegexStartAnchor(hwnd, szFind, &start, TRUE); - } - - int iPos; - int iCount = 0; - while ((start < end) && ((iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end)) >= 0)) + while ((start < end) && (iPos >= 0)) { - if (end > iEndPos) { - // not found or replace target end is beyond selection - break; // while - } + iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); - if (++iCount == 1) - SendMessage(hwnd, SCI_BEGINUNDOACTION, 0, 0); + if ((iPos >= 0) && (end <= iEndPos)) { - // replace - int iReplLen = (int)SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); + if (++iCount == 1) + SendMessage(hwnd, SCI_BEGINUNDOACTION, 0, 0); - // move caret behind replacement; target region maybe extended by replacement - iEndPos = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0) - iDiffToDocEnd; - start += iReplLen; // == (int)SendMessage(hwnd, SCI_GETTARGETEND, 0, 0); ? - end = iEndPos; + // replace + int iReplLen = (int)SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); - // correction for regex - if (lpefr->fuFlags & SCFIND_REGEXP) { - EditSetRegexStartAnchor(hwnd, szFind, &start, TRUE); + // move start behind replacement; target region maybe extended by replacement + iEndPos = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0) - iDiffToDocEnd; + start += iReplLen; + end = iEndPos; + + // correction for regex + if (lpefr->fuFlags & SCFIND_REGEXP) { + EditRegexAdaptAnchors(hwnd, szFind, &start, TRUE); + } } } + EndWaitCursor(); + LocalFree(pszReplace); if (iCount) SendMessage(hwnd, SCI_ENDUNDOACTION, 0, 0); - EndWaitCursor(); - if (bShowInfo) { if (iCount > 0) InfoBox(0, L"MsgReplaceCount", IDS_REPLCOUNT, iCount); @@ -5203,14 +5198,15 @@ int EditReplaceAllInRange(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bShowInfo, i // BOOL EditReplaceAll(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo) { - if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) - return /*EditFindReplaceDlg(hwnd,lpefr,TRUE)*/FALSE; - int start = 0; int end = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); + int token = BeginSelUndoAction(); + int iCount = EditReplaceAllInRange(hwnd, lpefr, bShowInfo, start, end); + EndSelUndoAction(token); + return (iCount > 0) ? TRUE : FALSE; } @@ -5221,13 +5217,11 @@ BOOL EditReplaceAll(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo) // BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo) { - if (!StringCchLenA(lpefr->szFind,COUNTOF(lpefr->szFind))) - return /*EditFindReplaceDlg(hwnd,lpefr,TRUE)*/FALSE; - if (SC_SEL_RECTANGLE == SendMessage(hwnd, SCI_GETSELECTIONMODE, 0, 0)) { MsgBox(MBWARN, IDS_SELRECT); return FALSE; } + int token = BeginSelUndoAction(); int start = (int)SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0); @@ -5235,24 +5229,25 @@ BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo int iCount = EditReplaceAllInRange(hwnd, lpefr, bShowInfo, start, end); - if (iCount > 0) { + EndSelUndoAction(token); - if (SendMessage(hwnd,SCI_GETSELECTIONEND,0,0) < SendMessage(hwnd,SCI_GETTARGETEND,0,0)) { + if (iCount <= 0) + return FALSE; - int iAnchorPos = (int)SendMessage(hwnd,SCI_GETANCHOR,0,0); - int iCurrentPos = (int)SendMessage(hwnd,SCI_GETCURRENTPOS,0,0); + if (SendMessage(hwnd,SCI_GETSELECTIONEND,0,0) < SendMessage(hwnd,SCI_GETTARGETEND,0,0)) { - if (iAnchorPos > iCurrentPos) - iAnchorPos = (int)SendMessage(hwnd,SCI_GETTARGETEND,0,0); - else - iCurrentPos = (int)SendMessage(hwnd,SCI_GETTARGETEND,0,0); + int iAnchorPos = (int)SendMessage(hwnd,SCI_GETANCHOR,0,0); + int iCurrentPos = (int)SendMessage(hwnd,SCI_GETCURRENTPOS,0,0); - EditSelectEx(hwnd,iAnchorPos,iCurrentPos); - } + if (iAnchorPos > iCurrentPos) + iAnchorPos = (int)SendMessage(hwnd,SCI_GETTARGETEND,0,0); + else + iCurrentPos = (int)SendMessage(hwnd,SCI_GETTARGETEND,0,0); + + EditSelectEx(hwnd,iAnchorPos,iCurrentPos); } - EndSelUndoAction(token); - return (iCount > 0) ? TRUE : FALSE; + return TRUE; } @@ -5540,7 +5535,6 @@ INT_PTR CALLBACK EditLinenumDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lPa case WM_INITDIALOG: { - int iCurLine = (int)SendMessage(hwndEdit,SCI_LINEFROMPOSITION, SendMessage(hwndEdit,SCI_GETCURRENTPOS,0,0),0)+1; From 6d42cfdc93e8d79b10a71a827e8fbee6646f91eb Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sun, 29 Oct 2017 19:18:20 +0100 Subject: [PATCH 10/11] + fix: break criteria for "replace all in range" --- src/Edit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Edit.c b/src/Edit.c index ff3e93f0b..60c1063d9 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -5150,7 +5150,8 @@ int EditReplaceAllInRange(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bShowInfo, i int iCount = 0; int start = iStartPos; int end = iEndPos; - while ((start < end) && (iPos >= 0)) + + while ((iPos >= 0) && (start < end) && (end <= iEndPos)) { iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); From da36884310e4c788b93f28ae0fc109e134bfb5a0 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Mon, 30 Oct 2017 10:12:37 +0100 Subject: [PATCH 11/11] + fix: bug in getting string length from dialog box readout --- src/Edit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Edit.c b/src/Edit.c index 60c1063d9..aa7ac009c 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -4946,7 +4946,7 @@ int __fastcall EditGetFindStrg(HWND hwnd, LPCEDITFINDREPLACE lpefr, LPSTR szFind if (lpefr->bTransformBS) TransformBackslashes(szFind, (lpefr->fuFlags & SCFIND_REGEXP), Encoding_SciGetCodePage(hwnd)); - int slen = StringCchLenA(szFind, COUNTOF(szFind)); + int slen = StringCchLenA(szFind, FNDRPL_BUFFER); if (slen == 0) InfoBox(0, L"MsgNotFound", IDS_NOTFOUND);