summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcommon/library.cpp22
-rw-r--r--common/str.cpp130
-rw-r--r--common/str.h249
-rw-r--r--win/Piecebar.cpp25
4 files changed, 280 insertions, 146 deletions
diff --git a/common/library.cpp b/common/library.cpp
index 6542c90..c1e495c 100755
--- a/common/library.cpp
+++ b/common/library.cpp
@@ -515,27 +515,7 @@ bool PiecesLibrary::PieceInCategory(PieceInfo* Info, const String& CategoryKeywo
String Keywords = CategoryKeywords;
Keywords.MakeLower();
- const char* p = Keywords;
-
- while (*p)
- {
- const char* k = p;
-
- while (*k && (*k != ',') && (*k != ';'))
- k++;
-
- String Search = Keywords.Mid(p - (const char*)Keywords, k - p);
-
- if (PieceName.Find(Search) != -1)
- return true;
-
- if (*k)
- p = k + 1;
- else
- break;
- }
-
- return false;
+ return PieceName.Match(Keywords);
}
int PiecesLibrary::GetFirstCategory(PieceInfo* Info) const
diff --git a/common/str.cpp b/common/str.cpp
index ee1b35c..d7b59dd 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -180,6 +180,136 @@ String& String::Right (int count) const
// =============================================================================
// Other functions
+// Evaluates the contents of the string against a boolean expression.
+// For example: (^Car | %Animal) & !Parrot
+// Will return true for any strings that have the Car word or
+// begin with Animal and do not have the word Parrot.
+bool String::Match(const String& Expression) const
+{
+ // Check if we need to split the test expression.
+ const char* p = Expression;
+
+ while (*p)
+ {
+ if (*p == '!')
+ {
+ return !Match(String(p + 1));
+ }
+ else if (*p == '(')
+ {
+ const char* Start = p;
+ int c = 0;
+
+ // Skip what's inside the parenthesis.
+ do
+ {
+ if (*p == '(')
+ c++;
+ else if (*p == ')')
+ c--;
+ else if (*p == 0)
+ return false; // Mismatched parenthesis.
+
+ p++;
+ }
+ while (c);
+
+ if (*p == 0)
+ break;
+ }
+ else if ((*p == '|') || (*p == '&'))
+ {
+ String Left, Right;
+
+ Left = Expression.Left((p - Expression) - 1);
+ Right = Expression.Right(Expression.GetLength() - (p - Expression) - 1);
+
+ if (*p == '|')
+ return Match(Left) || Match(Right);
+ else
+ return Match(Left) && Match(Right);
+ }
+
+ p++;
+ }
+
+ if (Expression.Find('(') != -1)
+ {
+ p = Expression;
+ while (*p)
+ {
+ if (*p == '(')
+ {
+ const char* Start = p;
+ int c = 0;
+
+ // Extract what's inside the parenthesis.
+ do
+ {
+ if (*p == '(')
+ c++;
+ else if (*p == ')')
+ c--;
+ else if (*p == 0)
+ return false; // Mismatched parenthesis.
+
+ p++;
+ }
+ while (c);
+
+ String Expr = Expression.Mid(Start - Expression + 1, p - Start - 2);
+ return Match(Expr);
+ }
+
+ p++;
+ }
+ }
+
+ // Testing a simple case.
+ String Search = Expression;
+ Search.TrimRight();
+ Search.TrimLeft();
+
+ const char* Word = Search;
+
+ // Check for modifiers.
+ bool WholeWord = 0;
+ bool Begin = 0;
+
+ for (;;)
+ {
+ if (Word[0] == '^')
+ WholeWord = true;
+ else if (Word[0] == '%')
+ Begin = true;
+ else
+ break;
+
+ Word++;
+ }
+
+ int Result = Find(Word);
+
+ if (Result == -1)
+ return false;
+
+ if (Begin && (Result != 0))
+ return false;
+
+ if (WholeWord)
+ {
+ char End = GetAt(Result + strlen(Word));
+
+ if ((End != 0) && (End != ' '))
+ return false;
+
+ if ((Result != 0) && (GetAt(Result-1) != ' '))
+ return false;
+ }
+
+ return true;
+}
+
int String::CompareNoCase (const char *string) const
{
char c1, c2, *ch = m_pData;
diff --git a/common/str.h b/common/str.h
index 23e6f1a..658a16e 100644
--- a/common/str.h
+++ b/common/str.h
@@ -5,152 +5,153 @@
class String
{
- public:
- String ();
- String (const String& src)
- { m_pData = NULL; *this = src; }
- String (const char* str)
- { m_pData = NULL; *this = str; }
- ~String ();
-
- int GetLength () const
- { return strlen (m_pData); }
- bool IsEmpty () const
- { return m_pData[0] == '\0'; }
- void Empty ()
- { m_pData[0] = '\0'; }
-
- char GetAt (int index) const
- { return m_pData[index]; }
- char operator[] (int index) const
- { return m_pData[index]; }
- void SetAt (int index, char ch)
- { m_pData[index] = ch; }
- operator char* () const
- { return m_pData; }
- operator const char* () const
- { return m_pData; }
-
- // Operators
- const String& operator= (const String& src);
- const String& operator= (char ch);
- const String& operator= (const char *src);
- const String& operator+= (const String& string);
- const String& operator+= (char ch);
- const String& operator+= (const char *src);
-
- // Comparison
- int Compare (const char *string) const
- { return strcmp (m_pData, string); }
- int CompareNoCase (const char *string) const;
- int CompareNoCase (const char *string, int count) const;
-
- // simple sub-string extraction
- String& Mid (int first, int count) const;
- String& Mid (int first) const
- { return Mid (first, GetLength () - first); }
- String& Left (int count) const;
- String& Right (int count) const;
-
- // upper/lower/reverse conversion
- void MakeUpper ();
- void MakeLower ();
- void MakeReverse ();
-
- // trimming whitespace (either side)
- void TrimRight ();
- void TrimLeft ();
-
- // searching (return starting index, or -1 if not found)
- // look for a single character match
- int Find (char ch) const
- {
- char *pf = strchr (m_pData, ch);
- return (pf) ? (pf - m_pData) : -1;
- }
- int ReverseFind (char ch) const
- {
- char *pf = strrchr (m_pData, ch);
- return (pf) ? (pf - m_pData) : -1;
- }
- int FindOneOf (const char *set) const
- {
- char *pf = strpbrk (m_pData, set);
- return (pf) ? (pf - m_pData) : -1;
- }
-
- // look for a specific sub-string
- int Find (const char *str) const
- {
- char *pf = strstr (m_pData, str);
- return (pf) ? (pf - m_pData) : -1;
- }
-
- char* GetBuffer (int len)
- {
- if (len > (int)strlen (m_pData))
- {
- char *tmp = new char[len+1];
- strcpy (tmp, m_pData);
- delete []m_pData;
- m_pData = tmp;
- }
- return m_pData;
- }
- void ReleaseBuffer (int len = -1)
- {
- if (len == -1)
- len = strlen (m_pData);
- m_pData[len] = '\0';
- }
-
- protected:
- char* m_pData;
+public:
+ String();
+ String(const String& src)
+ { m_pData = NULL; *this = src; }
+ String(const char* str)
+ { m_pData = NULL; *this = str; }
+ ~String();
+
+ int GetLength() const
+ { return strlen(m_pData); }
+ bool IsEmpty() const
+ { return m_pData[0] == '\0'; }
+ void Empty()
+ { m_pData[0] = '\0'; }
+
+ char GetAt(int index) const
+ { return m_pData[index]; }
+ char operator[](int index) const
+ { return m_pData[index]; }
+ void SetAt(int index, char ch)
+ { m_pData[index] = ch; }
+ operator char*() const
+ { return m_pData; }
+ operator const char*() const
+ { return m_pData; }
+
+ // Operators
+ const String& operator=(const String& src);
+ const String& operator=(char ch);
+ const String& operator=(const char *src);
+ const String& operator+=(const String& string);
+ const String& operator+=(char ch);
+ const String& operator+=(const char *src);
+
+ // Comparison
+ int Compare(const char *string) const
+ { return strcmp(m_pData, string); }
+ int CompareNoCase(const char *string) const;
+ int CompareNoCase(const char *string, int count) const;
+ bool Match(const String& Expression) const;
+
+ // simple sub-string extraction
+ String& Mid(int first, int count) const;
+ String& Mid(int first) const
+ { return Mid(first, GetLength() - first); }
+ String& Left(int count) const;
+ String& Right(int count) const;
+
+ // upper/lower/reverse conversion
+ void MakeUpper();
+ void MakeLower();
+ void MakeReverse();
+
+ // trimming whitespace (either side)
+ void TrimRight();
+ void TrimLeft();
+
+ // searching (return starting index, or -1 if not found)
+ // look for a single character match
+ int Find(char ch) const
+ {
+ char *pf = strchr(m_pData, ch);
+ return (pf) ? (pf - m_pData) : -1;
+ }
+ int ReverseFind(char ch) const
+ {
+ char *pf = strrchr(m_pData, ch);
+ return (pf) ? (pf - m_pData) : -1;
+ }
+ int FindOneOf(const char *set) const
+ {
+ char *pf = strpbrk(m_pData, set);
+ return (pf) ? (pf - m_pData) : -1;
+ }
+
+ // look for a specific sub-string
+ int Find(const char *str) const
+ {
+ char *pf = strstr(m_pData, str);
+ return (pf) ? (pf - m_pData) : -1;
+ }
+
+ char* GetBuffer(int len)
+ {
+ if (len > (int)strlen(m_pData))
+ {
+ char *tmp = new char[len+1];
+ strcpy(tmp, m_pData);
+ delete []m_pData;
+ m_pData = tmp;
+ }
+ return m_pData;
+ }
+ void ReleaseBuffer(int len = -1)
+ {
+ if (len == -1)
+ len = strlen(m_pData);
+ m_pData[len] = '\0';
+ }
+
+protected:
+ char* m_pData;
};
// Concatenation operators
-String& operator+ (const String& string1, const String& string2);
-String& operator+ (const String& string, char ch);
-String& operator+ (char ch, const String& string);
-String& operator+ (const String& string1, const char *string2);
-String& operator+ (const char *string1, const String& string2);
+String& operator+(const String& string1, const String& string2);
+String& operator+(const String& string, char ch);
+String& operator+(char ch, const String& string);
+String& operator+(const String& string1, const char *string2);
+String& operator+(const char *string1, const String& string2);
// Comparison operators
-inline bool operator== (const String& s1, const String& s2)
+inline bool operator==(const String& s1, const String& s2)
{ return s1.Compare(s2) == 0; }
-inline bool operator== (const String& s1, const char *s2)
+inline bool operator==(const String& s1, const char *s2)
{ return s1.Compare(s2) == 0; }
-inline bool operator== (const char *s1, const String& s2)
+inline bool operator==(const char *s1, const String& s2)
{ return s2.Compare(s1) == 0; }
-inline bool operator!= (const String& s1, const String& s2)
+inline bool operator!=(const String& s1, const String& s2)
{ return s1.Compare(s2) != 0; }
-inline bool operator!= (const String& s1, const char *s2)
+inline bool operator!=(const String& s1, const char *s2)
{ return s1.Compare(s2) != 0; }
-inline bool operator!= (const char *s1, const String& s2)
+inline bool operator!=(const char *s1, const String& s2)
{ return s2.Compare(s1) != 0; }
-inline bool operator< (const String& s1, const String& s2)
+inline bool operator<(const String& s1, const String& s2)
{ return s1.Compare(s2) < 0; }
-inline bool operator< (const String& s1, const char *s2)
+inline bool operator<(const String& s1, const char *s2)
{ return s1.Compare(s2) < 0; }
-inline bool operator< (const char *s1, const String& s2)
+inline bool operator<(const char *s1, const String& s2)
{ return s2.Compare(s1) > 0; }
-inline bool operator> (const String& s1, const String& s2)
+inline bool operator>(const String& s1, const String& s2)
{ return s1.Compare(s2) > 0; }
-inline bool operator> (const String& s1, const char *s2)
+inline bool operator>(const String& s1, const char *s2)
{ return s1.Compare(s2) > 0; }
-inline bool operator> (const char *s1, const String& s2)
+inline bool operator>(const char *s1, const String& s2)
{ return s2.Compare(s1) < 0; }
-inline bool operator<= (const String& s1, const String& s2)
+inline bool operator<=(const String& s1, const String& s2)
{ return s1.Compare(s2) <= 0; }
-inline bool operator<= (const String& s1, const char *s2)
+inline bool operator<=(const String& s1, const char *s2)
{ return s1.Compare(s2) <= 0; }
-inline bool operator<= (const char *s1, const String& s2)
+inline bool operator<=(const char *s1, const String& s2)
{ return s2.Compare(s1) >= 0; }
-inline bool operator>= (const String& s1, const String& s2)
+inline bool operator>=(const String& s1, const String& s2)
{ return s1.Compare(s2) >= 0; }
-inline bool operator>= (const String& s1, const char *s2)
+inline bool operator>=(const String& s1, const char *s2)
{ return s1.Compare(s2) >= 0; }
-inline bool operator>= (const char *s1, const String& s2)
+inline bool operator>=(const char *s1, const String& s2)
{ return s2.Compare(s1) <= 0; }
#endif // _STR_H_
diff --git a/win/Piecebar.cpp b/win/Piecebar.cpp
index 0b7d154..3ec1cdb 100644
--- a/win/Piecebar.cpp
+++ b/win/Piecebar.cpp
@@ -1067,12 +1067,30 @@ BOOL CPiecesBar::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
PieceInfo* Parent = (PieceInfo*)Notify->itemNew.lParam;
+ HTREEITEM CategoryItem = m_PiecesTree.GetParentItem(Notify->itemNew.hItem);
+ CString CategoryName = m_PiecesTree.GetItemText(CategoryItem);
+ int CategoryIndex = Lib->FindCategoryIndex((const char*)CategoryName);
+
PtrArray<PieceInfo> Pieces;
Lib->GetPatternedPieces(Parent, Pieces);
Pieces.Sort(PiecesSortFunc, NULL);
HTREEITEM ParentItem = Notify->itemNew.hItem;
+ // Remove all children (for some reason TVE_COLLAPSERESET isn't always working).
+ if (m_PiecesTree.ItemHasChildren(ParentItem))
+ {
+ HTREEITEM NextItem;
+ HTREEITEM ChildItem = m_PiecesTree.GetChildItem(ParentItem);
+
+ while (ChildItem != NULL)
+ {
+ NextItem = m_PiecesTree.GetNextItem(ChildItem, TVGN_NEXT);
+ m_PiecesTree.DeleteItem(ChildItem);
+ ChildItem = NextItem;
+ }
+ }
+
for (int i = 0; i < Pieces.GetSize(); i++)
{
PieceInfo* Info = Pieces[i];
@@ -1080,6 +1098,12 @@ BOOL CPiecesBar::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
if (!m_bSubParts && Info->IsSubPiece())
continue;
+ if (CategoryIndex != -1)
+ {
+ if (!Lib->PieceInCategory(Info, Lib->GetCategoryKeywords(CategoryIndex)))
+ continue;
+ }
+
// If both descriptions begin with the same text, only show the difference.
if (!strncmp(Info->m_strDescription, Parent->m_strDescription, strlen(Parent->m_strDescription)))
m_PiecesTree.InsertItem(TVIF_PARAM|TVIF_TEXT, Info->m_strDescription + strlen(Parent->m_strDescription) + 1, 0, 0, 0, 0, (LPARAM)Info, ParentItem, TVI_LAST);
@@ -1090,7 +1114,6 @@ BOOL CPiecesBar::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
}
else if (Notify->action == TVE_COLLAPSE)
{
- // Remove all children.
m_PiecesTree.Expand(Notify->itemNew.hItem, TVE_COLLAPSE | TVE_COLLAPSERESET);
}
}