summaryrefslogtreecommitdiff
path: root/stringlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'stringlist.c')
-rw-r--r--stringlist.c2012
1 files changed, 1006 insertions, 1006 deletions
diff --git a/stringlist.c b/stringlist.c
index e1d6de5..c7012e4 100644
--- a/stringlist.c
+++ b/stringlist.c
@@ -1,1007 +1,1007 @@
-/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko Herkenrath
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-
-// -- Includes
-#include "common.h"
-
-// -- Macros
-#define SLAlloc(s) mir_alloc(s)
-#define SLReAlloc(p, s) mir_realloc((p), (s))
-#define SLFree(p) mir_free(p)
-//#define SLAlloc(s) HeapAlloc(GetProcessHeap(), 0, (s))
-//#define SLReAlloc(p, s) HeapReAlloc(GetProcessHeap(), 0, (p), (s))
-//#define SLFree(p) HeapFree(GetProcessHeap(), 0, (p))
-
-
-// -----------------------------------------
-
-
-BOOL SLAssignToListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox)
-{
- BOOL bReturn = FALSE;
- int i;
-
- if (!psl || !hwndListBox) return FALSE;
- SendMessage(hwndListBox, LB_RESETCONTENT, 0, 0);
- SendMessage(hwndListBox, LB_INITSTORAGE, (WPARAM)psl->uCount, (LPARAM)(SLGetSize(psl, TRUE)*sizeof(WCHAR)));
- EnterCriticalSection(&psl->csListAccess);
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- if (SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)psl->papszList[i]) >= 0)
- bReturn = TRUE;
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-BOOL SLRetrieveFromListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox)
-{
- int iCount, i, iPos;
- BOOL bReturn;
-
- if (!psl || !hwndListBox) return FALSE;
- bReturn = FALSE;
- EnterCriticalSection(&psl->csListAccess);
- iCount = SendMessage(hwndListBox, LB_GETCOUNT, 0, 0);
- for (i=0; i<iCount; i++)
- {
- iPos = SLPrepareItem(psl, SendMessage(hwndListBox, LB_GETTEXTLEN, (WPARAM)i, 0));
- if (iPos != SL_INVALID_POS)
- {
- if (SendMessage(hwndListBox, LB_GETTEXT, (WPARAM)i, (LPARAM)psl->papszList[iPos]) != LB_ERR)
- bReturn = TRUE;
- else
- SLDeleteItem(psl, iPos);
- }
- }
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-/*
-BOOL SLLoadFromIniFile(LPSTRINGLIST psl, const TCHAR* pszSearchPath, const TCHAR* pszSection, const TCHAR* pszSettingPrefix)
-{
- TCHAR szFile[MAX_PATH];
- BOOL bFileFound;
- BOOL bReturn = FALSE;
- int i, iLen, iSize;
- TCHAR* pszItem;
- TCHAR* pszBuf;
- WIN32_FIND_DATA wfd;
- HANDLE hFind;
-
- if (!psl || !pszSection || !pszSearchPath)
- return FALSE;
-
- ZeroMemory(&wfd, sizeof(wfd));
-
- EnterCriticalSection(&psl->csListAccess);
-
- // Enum all files in the directory
- hFind = FindFirstFile(pszSearchPath, &wfd);
- for (bFileFound=(hFind!=INVALID_HANDLE_VALUE); bFileFound; bFileFound=FindNextFile(hFind, &wfd))
- {
- if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
- continue;
-
- // Construct the file name
- mir_sntprintf(szFile, ARRAYSIZE(szFile), _T("%s"), pszSearchPath);
- PathRemoveFileSpec(szFile);
- PathAppend(szFile, wfd.cFileName);
-
- // Load the data from ini file
- iSize = (pszSettingPrefix?(lstrlen(pszSettingPrefix)+1):0)+MAX_INT_LENGTH+1);
- pszItem = (TCHAR*)mir_alloc(iSize*sizeof(TCHAR));
- if (!pszItem) continue;
-
- for (i=SL_MIN_POS;;i++) // no break condition
- {
- mir_sntprintf(pszItem, _T("%s%s%i"), iSize, pszSettingPrefix?pszSettingPrefix:_T(""), pszSettingPrefix?_T("|"):_T(""), i);
-
- iLen = GetPrivateProfileString(pszSection, pszItem, NULL, NULL, 0, szFile);
- if (iLen < 0) break;
-
- pszBuf = (TCHAR*)mir_alloc((iLen+1)*sizeof(TCHAR));
- if (!pszBuf) continue;
-
- GetPrivateProfileString(pszSection, pszItem, NULL, pszBuf, iLen, szFile);
- if (lstrlen(pszBuf) <= 0) break;
-
- if (SLAddItem(psl, pszBuf) != SL_INVALID_POS)
- if (!bReturn) bReturn = TRUE;
-
- mir_free(pszBuf);
- }
-
- mir_free(pszItem);
- }
-
- LeaveCriticalSection(&psl->csListAccess);
-
- if (hFind) FindClose(hFind);
-
- return bReturn;
-}
-
-
-
-BOOL SLSaveToIniFile(LPSTRINGLIST psl, const TCHAR* pszFileName, const TCHAR* pszSection, const TCHAR* pszSettingPrefix)
-{
- int i;
- char* pszItem;
- int iSize;
- BOOL bReturn = FALSE;
-
- if (!psl || !pszSection || !pszFileName)
- return FALSE;
-
- iSize = (pszSettingPrefix?(lstrlen(pszSettingPrefix)+1):0)+MAX_INT_LENGTH+1;
- pszItem = (TCHAR*)mir_alloc(iSize*sizeof(TCHAR));
-
- if (pszItem)
- {
- EnterCriticalSection(&psl->csListAccess);
-
- // Delete old items (empty section)
- WritePrivateProfileString(pszSection, NULL, NULL, pszFileName);
-
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- {
- mir_sntprintf(pszItem, iSize, _T("%s%s%i"), pszSettingPrefix?pszSettingPrefix:_T(""), pszSettingPrefix?_T("|"):_T(""), i);
-
- if (WritePrivateProfileString(pszSection, pszItem, psl->papszList[i], pszFileName))
- bReturn = TRUE;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
-
- mir_free(pszItem);
- }
-
- return bReturn;
-}
-*/
-
-
-BOOL SLLoadFromFile(LPSTRINGLIST psl, const WCHAR* pszSearchPath)
-{
- BOOL bReturn;
- WIN32_FIND_DATA wfd;
- HANDLE hFind;
- BOOL bFileFound;
- WCHAR szFile[MAX_PATH];
- HANDLE hFile;
- DWORD dwRead;
- int iAllocBufSize;
- int iAllocBufStep;
- char* pszAllocBuf;
- char* pszAllocBufTmp;
- const char szBOM[3] = {0xEF, 0xBB, 0xBF};
- BOOL bWatchBOM;
- BOOL bEndOfFile;
- WCHAR* pszContentConv;
- WCHAR* pszBuf;
-
- if (!psl || !pszSearchPath) return FALSE;
- EnterCriticalSection(&psl->csListAccess);
-
- // Initial buffer size (gets auto-enlarged if needed)
- iAllocBufSize = 128; // read-in chars buffer
- pszAllocBuf = NULL;
-
- // Enum all files in the directory
- bReturn = FALSE;
- hFind = FindFirstFile(pszSearchPath, &wfd);
- for (bFileFound=(hFind!=INVALID_HANDLE_VALUE); bFileFound; bFileFound=FindNextFile(hFind, &wfd))
- {
- if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
- continue;
- mir_sntprintf(szFile, ARRAYSIZE(szFile), _T("%s"), pszSearchPath);
- PathRemoveFileSpec(szFile);
- PathAppend(szFile, wfd.cFileName);
-
- hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
- if (hFile == INVALID_HANDLE_VALUE) continue;
- bWatchBOM = TRUE;
- bEndOfFile = FALSE;
- iAllocBufStep = 0;
- while (!bEndOfFile)
- {
- // Enlarge buffer if needed
- if (!pszAllocBuf || (iAllocBufStep >= iAllocBufSize))
- {
- pszAllocBufTmp = (char*)mir_realloc(pszAllocBuf, (iAllocBufSize*2)*sizeof(char));
- if (pszAllocBufTmp) {
- if (pszAllocBuf) iAllocBufSize *= 2;
- pszAllocBuf = pszAllocBufTmp;
- } else {
- bEndOfFile = TRUE; // out of memory
- }
- }
- if (!bEndOfFile) {
- if (!ReadFile(hFile, &pszAllocBuf[iAllocBufStep], sizeof(char), &dwRead, NULL))
- bEndOfFile = TRUE;
- if (dwRead < sizeof(char))
- bEndOfFile = TRUE;
- }
- if ((pszAllocBuf[iAllocBufStep] == '\n') || bEndOfFile)
- {
- if (!bEndOfFile && (iAllocBufStep>0) && (pszAllocBuf[iAllocBufStep-1] == '\r'))
- pszAllocBuf[iAllocBufStep-1] = '\0';
- else
- pszAllocBuf[iAllocBufStep] = '\0';
-
- if (lstrlenA(pszAllocBuf) > 0)
- {
- // Test UTF-8 BOM
- // EF BB BF = UTF-8
- // -> indicating UTF-8 Unicode text file (check only once)
- if (bWatchBOM)
- {
- if (StrCmpNA(pszAllocBuf, szBOM, ARRAYSIZE(szBOM)) == 0)
- MoveMemory(pszAllocBuf, (PBYTE)pszAllocBuf+sizeof(szBOM), ((lstrlenA(pszAllocBuf)+1)*sizeof(char))-sizeof(szBOM));
- bWatchBOM = FALSE;
- }
-
- // Decode Utf8
- mir_utf8decode(pszAllocBuf,&pszContentConv);
- if (pszContentConv)
- {
- pszBuf = pszContentConv;
- while (pszBuf)
- {
- // Find comment indicator
- pszBuf = StrChr(pszBuf, _T(';')); // find ";" comment indicator
- if (pszBuf && (*CharPrev(pszContentConv, pszBuf) != _T('\\'))) // ignore "\;" chars
- {
- *pszBuf = _T('\0');
- break;
- }
- }
-
- // Replace no-comment indicators
- pszBuf = ReplaceSubStringWithString(pszContentConv, _T("\\;"), _T(";"), TRUE, FALSE, NULL);
-
- // Add item to list (disallow empty items)
- if (lstrlen(pszContentConv) > 0)
- if (SLAddItem(psl, pszBuf?pszBuf:pszContentConv) >= 0)
- bReturn = TRUE;
-
- mir_free(pszContentConv);
- if (pszBuf) mir_free(pszBuf);
- }
- }
-
- // Reset step count
- iAllocBufStep = 0;
-
- } else {
- // Step up in string
- iAllocBufStep++;
- }
-
- } // while (!bEndOfFile)
-
- CloseHandle(hFile);
- }
-
- if (hFind) FindClose(hFind);
- if (pszAllocBuf) mir_free(pszAllocBuf);
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-
-BOOL SLSaveToFile(LPSTRINGLIST psl, const WCHAR* pszFileName)
-{
- BOOL bReturn;
- int i;
- const char szBOM[3] = {0xEF, 0xBB, 0xBF};
- HANDLE hFile;
- DWORD dwWritten; // Win98 compatibility
- WCHAR* pszBuf;
- char* pszContentUtf8;
-
- if (!psl || !pszFileName) return FALSE;
- hFile = CreateFile(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
- if (hFile == INVALID_HANDLE_VALUE) return FALSE;
- bReturn = FALSE;
- EnterCriticalSection(&psl->csListAccess);
-
- // Write UTF-8 BOM
- // EF BB BF = UTF-8
- // -> indicating UTF-8 Unicode text file
- if (WriteFile(hFile, &szBOM, sizeof(szBOM), &dwWritten, NULL))
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- {
- // Replace comment indicators
- pszBuf = ReplaceSubStringWithString(psl->papszList[i], _T(";"), _T("\\;"), TRUE, FALSE, NULL);
- if (!pszBuf) continue;
- pszContentUtf8 = mir_utf8encodeW(pszBuf);
- if (pszContentUtf8) {
- if (WriteFile(hFile, pszContentUtf8, lstrlenA(pszContentUtf8)*sizeof(char), &dwWritten, NULL))
- if (WriteFile(hFile, "\r\n", 2*sizeof(char), &dwWritten, NULL))
- bReturn = TRUE;
- mir_free(pszContentUtf8);
- }
- mir_free(pszBuf);
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- SetEndOfFile(hFile); // if it was longer before
- FlushFileBuffers(hFile); // just to be sure
- CloseHandle(hFile);
- return bReturn;
-}
-
-
-/*
-BOOL SLConvertFromString(LPSTRINGLIST psl, const TCHAR* pszString, int cchSize, const TCHAR* pszSeparator, BOOL bIgnoreEmptyItems)
-{
- // If pszSeparator is NULL a _T('\0') is taken as separator
- BOOL bReturn;
- int cchSepLen;
-
- BOOL bReachedEnd;
- TCHAR* pszAfterPrev;
- TCHAR* pszNext;
- int iPos;
-
- if (!pszString || !psl) return 0;
-
- if (cchSize < 0) cchSize = lstrlen(pszString)+1;
- cchSepLen = pszSeparator?lstrlen(pszSeparator):1;
-
- EnterCriticalSection(&psl->csListAccess);
-
- // Loop through string
- bReturn = 0;
- pszAfterPrev = (TCHAR*)pszString;
- bReachedEnd = FALSE;
- while (!bReachedEnd)
- {
- // Find first/next occurence
- if (pszSeparator)
- {
- pszNext = StrStr(pszAfterPrev, pszSeparator);
- if (!pszNext)
- {
- bReachedEnd = TRUE;
- pszNext = (TCHAR*)pszString+(cchSize*sizeof(TCHAR));
- }
-
- } else {
-
- // Find NULL separator
- pszNext = pszAfterPrev;
- while (*pszNext != _T('\0'));
- {
- pszNext = CharNext(pszNext);
- if ( pszNext >= (szString+((cchSize-1)*sizeof(TCHAR)) )
- {
- bReachedEnd = TRUE;
- break;
- }
- }
- }
-
- // Add item
- if (!bIgnoreEmptyItems || (pszNext != pszAfterPrev))
- {
- i2
- if (iPos < 0) continue;
- CopyMemory((PBYTE)psl->papszList[iPos], pszAfterPrev, ((PBYTE)pszNext-(PBYTE)pszAfterPrev));
-
- bReturn = TRUE;
- }
-
- // Step up one separated item
- pszAfterPrev = pszNext+(cchSepLen*sizeof(TCHAR));
- if ( pszAfterPrev >= pszString+((cchSize-1)*sizeof(TCHAR)) )
- bReachedEnd = TRUE;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
-
- return bReturn;
-}
-*/
-
-
-WCHAR* SLConvertToString(LPSTRINGLIST psl, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast, int* piSize)
-{
- // Returned string needs to be freed with SLFreeReturn()
- // If pszSeparator is NULL a _T('\0') is taken as separator
-
- int i;
- int iSepLen;
- int iSize;
- WCHAR* pszReturn;
- WCHAR* pszStep;
-
- if (piSize) *piSize = 0;
- if (!psl) return NULL;
-
- EnterCriticalSection(&psl->csListAccess);
-
- // Get needed size
- iSepLen = pszSeparator?lstrlen(pszSeparator):1;
- iSize = SLGetSize(psl, FALSE)+1; // character count in string list
- if (psl->uCount > 0) iSize += (psl->uCount-1)*iSepLen;
- if ((psl->uCount > 0) && bAlsoDoFirst) iSize += iSepLen;
- if (bAlsoDoLast) iSize += iSepLen;
-
- pszReturn = (WCHAR*)SLAlloc(iSize*sizeof(WCHAR));
- if (!pszReturn) {
- LeaveCriticalSection(&psl->csListAccess);
- return NULL;
- }
- if (piSize) *piSize = iSize;
-
- // Add items to memory
- pszStep = pszReturn;
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- {
- if ((i>SL_MIN_POS) || bAlsoDoFirst)
- {
- if (pszSeparator)
- CopyMemory(pszStep, pszSeparator, iSepLen*sizeof(WCHAR)); // no terminating zero
- else
- ZeroMemory(pszStep, sizeof(WCHAR));
- pszStep = &pszStep[iSepLen];
- }
-
- // Add item
- CopyMemory(pszStep, psl->papszList[i], lstrlen(psl->papszList[i])*sizeof(WCHAR)); // no terminating zero
- pszStep = &pszStep[lstrlen(psl->papszList[i])];
- }
- LeaveCriticalSection(&psl->csListAccess);
-
- if (bAlsoDoLast)
- {
- if (pszSeparator)
- CopyMemory(pszStep, pszSeparator, iSepLen*sizeof(WCHAR)); // no terminating zero
- else
- ZeroMemory(pszStep, sizeof(WCHAR));
- pszStep = &pszStep[iSepLen];
- }
-
- ZeroMemory(pszStep, sizeof(WCHAR));
- return pszReturn;
-}
-
-void SLFreeReturn(void* pPntr)
-{
- if (pPntr) SLFree(pPntr);
-}
-
-BOOL SLConvertToStringBuf(LPSTRINGLIST psl, WCHAR* pszOutput, int cchMaxSize, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast)
-{
- BOOL bReturn;
- int iSize;
- WCHAR* pszBuf;
-
- if (!psl || !pszOutput || (cchMaxSize <= 0)) return FALSE;
- pszBuf = SLConvertToString(psl, pszSeparator, bAlsoDoFirst, bAlsoDoLast, &iSize);
- if (pszBuf) {
- if (cchMaxSize < iSize) iSize = cchMaxSize;
- CopyMemory(pszOutput, pszBuf, iSize*sizeof(WCHAR));
- SLFreeReturn(pszBuf);
- bReturn = TRUE;
- } else {
- iSize = 1;
- bReturn = FALSE;
- }
- if (cchMaxSize > 1)
- ZeroMemory(&pszOutput[iSize-1], sizeof(WCHAR));
- if (!pszSeparator && bAlsoDoLast && (cchMaxSize > 2))
- ZeroMemory(&pszOutput[iSize], sizeof(WCHAR));
- return bReturn;
-}
-
-
-BOOL SLMergeList(LPSTRINGLIST pslDest, LPSTRINGLIST pslFrom)
-{
- BOOL bReturn;
- int i;
-
- if (!pslDest || !pslFrom || (pslDest == pslFrom)) return FALSE;
- EnterCriticalSection(&pslFrom->csListAccess); // first list
- if (pslFrom->uCount == 0) {
- LeaveCriticalSection(&pslFrom->csListAccess);
- return TRUE;
- }
- EnterCriticalSection(&pslDest->csListAccess); // second list
- bReturn = FALSE;
- for (i=SL_MIN_POS; i<(int)(pslFrom->uCount); i++)
- if (SLAddItem(pslDest, pslFrom->papszList[i]) != SL_INVALID_POS)
- bReturn = TRUE;
- LeaveCriticalSection(&pslFrom->csListAccess); // first list
- LeaveCriticalSection(&pslDest->csListAccess); // second list
- return bReturn;
-}
-
-
-int SLFindItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive, int iStartPos)
-{
- int i, iReturn;
-
- if (!psl || !pszItem) return SL_INVALID_POS;
- EnterCriticalSection(&psl->csListAccess);
- if (!SLIsValid(psl, iStartPos)) {
- LeaveCriticalSection(&psl->csListAccess);
- return SL_INVALID_POS;
- }
- iReturn = SL_INVALID_POS;
- for (i=iStartPos; i<(int)psl->uCount; i++)
- if ((bCaseSensitive?StrCmp(psl->papszList[i], pszItem):StrCmpI(psl->papszList[i], pszItem)) == 0) {
- iReturn = i;
- break;
- }
- LeaveCriticalSection(&psl->csListAccess);
- return iReturn;
-}
-
-BOOL SLIsItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive)
-{
- return (SLFindItem(psl, pszItem, bCaseSensitive, SL_MIN_POS) != SL_INVALID_POS);
-}
-
-int SLAddItem(LPSTRINGLIST psl, const WCHAR* pszNewItem)
-{
- WCHAR** apszBuf;
- WCHAR* pszBuf;
- int i;
-
- if (!psl) return SL_INVALID_POS;
- EnterCriticalSection(&psl->csListAccess);
- if (((int)(psl->uCount+1) <= 0) || ((int)(psl->uCount+1) == psl->uCount)) {
- #if defined(_DEBUG)
- OutputDebugString(_T("Spam Filter: Stringlist overflow.\r\n"));
- DebugBreak();
- #endif
- LeaveCriticalSection(&psl->csListAccess);
- return SL_INVALID_POS;
- }
-
- // Create/Resize the array
- if (!psl->papszList) {
- apszBuf = (WCHAR**)SLAlloc(sizeof(WCHAR*));
- psl->uCount = 0;
- } else {
- apszBuf = (WCHAR**)SLReAlloc(psl->papszList, (psl->uCount+1)*sizeof(WCHAR*));
- }
- if (apszBuf) {
- psl->papszList = apszBuf;
- } else {
- LeaveCriticalSection(&psl->csListAccess);
- return SL_INVALID_POS;
- }
-
- // Prepare new string memory
- pszBuf = (WCHAR*)SLAlloc(((pszNewItem?lstrlen(pszNewItem):0)+1)*sizeof(WCHAR));
- if (!pszBuf) {
- LeaveCriticalSection(&psl->csListAccess);
- return SL_INVALID_POS;
- }
- // Prepare new string
- if (pszNewItem)
- CopyMemory(pszBuf, pszNewItem, (lstrlen(pszNewItem)+1)*sizeof(WCHAR));
- else
- ZeroMemory(pszBuf, sizeof(WCHAR));
-
- // Insert the new string
- i = psl->uCount;
- psl->papszList[i] = pszBuf;
- psl->uCount++;
-
- LeaveCriticalSection(&psl->csListAccess);
- return i;
-}
-
-int SLAddItemPair(LPSTRINGLIST psl, const WCHAR* pszNewItem1, const WCHAR* pszNewItem2)
-{
- int iPos;
-
- if (!psl) return SL_INVALID_POS;
- EnterCriticalSection(&psl->csListAccess);
- iPos = SLAddItem(psl, pszNewItem1);
- if (iPos != SL_INVALID_POS)
- if (SLAddItem(psl, pszNewItem2) == SL_INVALID_POS)
- SLDeleteItem(psl, iPos);
- LeaveCriticalSection(&psl->csListAccess);
- return iPos;
-}
-
-int SLPrepareItem(LPSTRINGLIST psl, int cchLength)
-{
- int iPos;
-
- if (!psl) return SL_INVALID_POS;
- EnterCriticalSection(&psl->csListAccess);
- iPos = SLAddItem(psl, NULL); // empty item
- if (iPos != SL_INVALID_POS)
- if (!SLSetItemLength(psl, iPos, cchLength)) {
- SLDeleteItem(psl, iPos);
- iPos = SL_INVALID_POS;
- }
- LeaveCriticalSection(&psl->csListAccess);
- return iPos;
-}
-
-/*
-BOOL SLAddItems(LPSTRINGLIST psl, const TCHAR* apszNewItems[], UINT uNewItemsCount)
-{
- int i;
- TCHAR** apszBuf;
-
- if (!psl || !apszNewItems || (uNewItemsCount <= 0))
- return FALSE;
-
- EnterCriticalSection(&psl->csListAccess);
-
- // Create/Resize the array
- if (!psl->papszList) {
- apszBuf = (TCHAR**)SLAlloc(uNewItemCount*sizeof(TCHAR*));
- psl->uCount = 0; // just to be sure
- } else {
- apszBuf = (TCHAR**)SLReAlloc(psl->papszList, (psl->uCount+uNewItemCount)*sizeof(TCHAR*));
- }
-
- if (apszBuf) {
- psl->papszList = apszBuf;
- } else {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
-
- // Insert the new string
- for (i=SL_MIN_POS; i<=iNewItemCount; i++)
- {
- psl->papszList[psl->uCount+i] = (TCHAR*)SLAlloc((lstrlen(apszNewItems[i])+1)*sizeof(TCHAR));
-
- if (psl->papszList[psl->uCount+i])
- {
- CopyMemory((PBYTE)psl->papszList[psl->uCount+i], apszNewItems[i], (lstrlen(apszNewItems[i])+1)*sizeof(TCHAR));
- // Increase list count
- psl->uCount++;
-
- } else {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-*/
-
-BOOL SLDeleteItems(LPSTRINGLIST psl, int iPosFirst, int iPosLast)
-{
- int i;
- WCHAR** apszBuf;
-
- if (!psl) return FALSE;
- if (iPosLast < iPosFirst) {
- i = iPosLast;
- iPosLast = iPosFirst;
- iPosFirst = i;
- }
- EnterCriticalSection(&psl->csListAccess);
- if (!SLIsValid(psl, iPosFirst) || !SLIsValid(psl, iPosLast)) {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
-
- for (i=iPosFirst; i<=iPosLast; i++)
- SLFree(psl->papszList[i]);
- if ((iPosLast+1) < (int)uMsgTypesCount)
- MoveMemory(&pamtdMsgTypes[iPosFirst], &pamtdMsgTypes[iPosLast+1], (iPosLast-iPosFirst+1)*sizeof(WCHAR));
-
- psl->uCount -= (iPosLast-iPosFirst+1);
-
- if (psl->papszList && (psl->uCount > 0)) {
- apszBuf = (WCHAR**)SLReAlloc(psl->papszList, psl->uCount*sizeof(WCHAR*));
- if (apszBuf) psl->papszList = apszBuf;
- } else {
- if (psl->papszList) SLFree(psl->papszList);
- psl->papszList = NULL;
- psl->uCount = 0;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-
-BOOL SLDeleteItem(LPSTRINGLIST psl, int iPos)
-{
- return SLDeleteItems(psl, iPos, iPos);
-}
-
-BOOL SLSetItemLength(LPSTRINGLIST psl, int iPos, int cchLength)
-{
- WCHAR* pszBuf;
- int iOldLen;
- BOOL bReturn;
-
- if (!psl) return FALSE;
- if (cchLength < 0) cchLength = 0;
- EnterCriticalSection(&psl->csListAccess);
- if (!SLIsValid(psl, iPos)) {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
-
- iOldLen = lstrlen(psl->papszList[iPos]);
- pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], (cchLength+1)*sizeof(WCHAR));
- if (pszBuf) {
- psl->papszList[iPos] = pszBuf;
- if (cchLength <= iOldLen)
- ZeroMemory(&pszBuf[cchLength], sizeof(WCHAR));
- else
- ZeroMemory(&pszBuf[iOldLen], (cchLength-iOldLen+1)*sizeof(WCHAR));
- bReturn = TRUE;
- } else {
- bReturn = FALSE;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-
-BOOL SLChangeItem(LPSTRINGLIST psl, int iPos, WCHAR* pszNewStr, BOOL bDoAppend)
-{
- BOOL bReturn;
- WCHAR* pszBuf;
-
- if (!psl) return FALSE;
- EnterCriticalSection(&psl->csListAccess);
- if (!SLIsValid(psl, iPos)) {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
-
- pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], ((pszNewStr?lstrlen(pszNewStr):0) + (bDoAppend?lstrlen(psl->papszList[iPos]):0) + 1)*sizeof(WCHAR));
- if (pszBuf)
- {
- psl->papszList[iPos] = pszBuf;
-
- if (bDoAppend && pszNewStr)
- CopyMemory(&pszBuf[lstrlen(pszBuf)], pszNewStr, (lstrlen(pszNewStr)+1)*sizeof(WCHAR));
- else if (pszNewStr)
- CopyMemory(pszBuf, pszNewStr, (lstrlen(pszNewStr)+1)*sizeof(WCHAR));
- else if (!bDoAppend)
- ZeroMemory(psl->papszList[iPos], sizeof(WCHAR));
-
- bReturn = TRUE;
- } else {
- if (!bDoAppend) ZeroMemory(psl->papszList[iPos], sizeof(WCHAR));
- bReturn = FALSE;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-
-
-BOOL SLItemPrintf(LPSTRINGLIST psl, int iPos, int cchArgMaxLen, ...)
-{
- BOOL bReturn = FALSE;
- WCHAR* pszBuf;
- WCHAR* pszFmt;
- va_list arglist;
-
- if (!psl) return FALSE;
- if (cchArgMaxLen < 0) cchArgMaxLen = 0;
- EnterCriticalSection(&psl->csListAccess);
- if (SLIsValid(psl, iPos))
- {
- pszFmt = (WCHAR*)SLAlloc((lstrlen(psl->papszList[iPos])+1)*sizeof(WCHAR));
- if (pszFmt)
- {
- CopyMemory(pszFmt, psl->papszList[iPos], (lstrlen(psl->papszList[iPos])+1)*sizeof(WCHAR));
- pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], (lstrlen(psl->papszList[iPos])+cchArgMaxLen+1)*sizeof(WCHAR));
- if (pszBuf)
- {
- psl->papszList[iPos] = pszBuf;
-
- va_start(arglist, cchArgMaxLen);
- mir_vsntprintf(pszBuf, lstrlen(pszBuf)+cchArgMaxLen+1, pszFmt, arglist);
- va_end(arglist);
-
- bReturn = TRUE;
- mir_free(pszFmt);
- }
- }
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-
-/*
-BOOL SLMoveItem(LPSTRINGLIST psl, int iOldPos, int iNewPos, BOOL bOnlySwitch)
-{
- TCHAR* pszBuf;
-
- if (!psl) return FALSE;
-
- EnterCriticalSection(&psl->csListAccess);
-
- if (!SLIsValid(psl, iOldPos) || !SLIsValid(psl, iNewPos)) {
- LeaveCriticalSection(&psl->csListAccess);
- return FALSE;
- }
-
- if (iNewPos == iOldPos) {
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
- }
-
- if (bOnlySwitch)
- {
- // Switch the items
- pszBuf = psl->papszList[iOldPos];
- psl->papszList[iOldPos] = psl->papszList[iNewPos];
- psl->papszList[iOldPos] = pszBuf;
-
- } else {
-
- int i;
-
- // Cache the old item
- pszBuf = psl->papszList[iOldPos];
-
- if (iNewPos > iOldPos)
- {
- // Move items in between one down
- for (i=iNewPos; i<iOldPos; i++)
- psl->papszList[i+1] = psl->papszList[i];
- } else {
- // Move items in between one up
- for (i=(iOldPos+1); i<=iNewPos; i++)
- psl->papszList[i] = psl->papszList[i+1];
- }
-
- psl->papszList[iNewPos] = pszBuf;
- }
-
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-*/
-
-BOOL SLIsValid(LPSTRINGLIST psl, int iPos)
-{
- BOOL bReturn;
-
- if (!psl) return FALSE;
- EnterCriticalSection(&psl->csListAccess);
- bReturn = (psl->papszList && (iPos>=SL_MIN_POS) && (iPos<(int)psl->uCount));
- LeaveCriticalSection(&psl->csListAccess);
- return bReturn;
-}
-
-WCHAR* SLGetItem(LPSTRINGLIST psl, int iPos)
-{
- WCHAR* pszReturn;
-
- EnterCriticalSection(&psl->csListAccess); // other operations finished
- pszReturn = SLIsValid(psl, iPos) ? psl->papszList[iPos] : NULL;
- LeaveCriticalSection(&psl->csListAccess);
- return pszReturn;
-}
-
-int SLGetMaxPos(LPSTRINGLIST psl)
-{
- int iReturn;
-
- if (!psl) return SL_INVALID_POS;
- EnterCriticalSection(&psl->csListAccess); // other operations finished
- iReturn = (psl->uCount > 0) ? (int)(psl->uCount-1) : SL_INVALID_POS;
- LeaveCriticalSection(&psl->csListAccess);
- return iReturn;
-}
-
-
-int SLGetItemCount(LPSTRINGLIST psl)
-{
- int iReturn;
- if (!psl) return 0;
-
- EnterCriticalSection(&psl->csListAccess); // other operations finished
- iReturn = (int)psl->uCount;
- LeaveCriticalSection(&psl->csListAccess);
- return iReturn;
-}
-
-
-int SLGetSize(LPSTRINGLIST psl, BOOL bAlsoTerminatingZeros) // character count size
-{
- int i, iReturn;
-
- if (!psl) return 0;
- EnterCriticalSection(&psl->csListAccess);
- iReturn = 0;
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- iReturn += lstrlen(psl->papszList[i]);
- if (bAlsoTerminatingZeros)
- iReturn += (int)psl->uCount;
- LeaveCriticalSection(&psl->csListAccess);
- return iReturn;
-}
-
-BOOL SLClearList(LPSTRINGLIST psl)
-{
- int i;
-
- if (!psl) return FALSE;
- EnterCriticalSection(&psl->csListAccess);
-
- // Free string memory
- for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
- SLFree(psl->papszList[i]);
-
- // Free the array
- psl->uCount = 0;
- if (psl->papszList) SLFree(psl->papszList);
- psl->papszList = NULL;
-
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-
-/*
-BOOL SLBlockList(LPSTRINGLIST psl)
-{
- if (!psl) return FALSE;
- EnterCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-
-BOOL SLUnBlockList(LPSTRINGLIST psl)
-{
- if (!psl) return FALSE;
- LeaveCriticalSection(&psl->csListAccess);
- return TRUE;
-}
-*/
-
-LPSTRINGLIST SLNewList(void)
-{
- LPSTRINGLIST psl = (LPSTRINGLIST)SLAlloc(sizeof(STRINGLIST));
- psl->papszList = NULL;
- psl->uCount = 0;
- InitializeCriticalSection(&psl->csListAccess);
- return psl;
-
-}
-
-void SLFreeList(LPSTRINGLIST psl)
-{
- if (!psl) return;
- SLClearList(psl);
- DeleteCriticalSection(&psl->csListAccess);
- SLFree(psl);
+/*
+
+"Spam Filter"-Plugin for Miranda IM
+
+Copyright 2003-2006 Heiko Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program ("SpamFilter-License.txt"); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+// -- Includes
+#include "common.h"
+
+// -- Macros
+#define SLAlloc(s) mir_alloc(s)
+#define SLReAlloc(p, s) mir_realloc((p), (s))
+#define SLFree(p) mir_free(p)
+//#define SLAlloc(s) HeapAlloc(GetProcessHeap(), 0, (s))
+//#define SLReAlloc(p, s) HeapReAlloc(GetProcessHeap(), 0, (p), (s))
+//#define SLFree(p) HeapFree(GetProcessHeap(), 0, (p))
+
+
+// -----------------------------------------
+
+
+BOOL SLAssignToListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox)
+{
+ BOOL bReturn = FALSE;
+ int i;
+
+ if (!psl || !hwndListBox) return FALSE;
+ SendMessage(hwndListBox, LB_RESETCONTENT, 0, 0);
+ SendMessage(hwndListBox, LB_INITSTORAGE, (WPARAM)psl->uCount, (LPARAM)(SLGetSize(psl, TRUE)*sizeof(WCHAR)));
+ EnterCriticalSection(&psl->csListAccess);
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ if (SendMessage(hwndListBox, LB_ADDSTRING, 0, (LPARAM)psl->papszList[i]) >= 0)
+ bReturn = TRUE;
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+BOOL SLRetrieveFromListBoxCtrl(LPSTRINGLIST psl, HWND hwndListBox)
+{
+ int iCount, i, iPos;
+ BOOL bReturn;
+
+ if (!psl || !hwndListBox) return FALSE;
+ bReturn = FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+ iCount = SendMessage(hwndListBox, LB_GETCOUNT, 0, 0);
+ for (i=0; i<iCount; i++)
+ {
+ iPos = SLPrepareItem(psl, SendMessage(hwndListBox, LB_GETTEXTLEN, (WPARAM)i, 0));
+ if (iPos != SL_INVALID_POS)
+ {
+ if (SendMessage(hwndListBox, LB_GETTEXT, (WPARAM)i, (LPARAM)psl->papszList[iPos]) != LB_ERR)
+ bReturn = TRUE;
+ else
+ SLDeleteItem(psl, iPos);
+ }
+ }
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+/*
+BOOL SLLoadFromIniFile(LPSTRINGLIST psl, const TCHAR* pszSearchPath, const TCHAR* pszSection, const TCHAR* pszSettingPrefix)
+{
+ TCHAR szFile[MAX_PATH];
+ BOOL bFileFound;
+ BOOL bReturn = FALSE;
+ int i, iLen, iSize;
+ TCHAR* pszItem;
+ TCHAR* pszBuf;
+ WIN32_FIND_DATA wfd;
+ HANDLE hFind;
+
+ if (!psl || !pszSection || !pszSearchPath)
+ return FALSE;
+
+ ZeroMemory(&wfd, sizeof(wfd));
+
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Enum all files in the directory
+ hFind = FindFirstFile(pszSearchPath, &wfd);
+ for (bFileFound=(hFind!=INVALID_HANDLE_VALUE); bFileFound; bFileFound=FindNextFile(hFind, &wfd))
+ {
+ if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ // Construct the file name
+ mir_sntprintf(szFile, ARRAYSIZE(szFile), _T("%s"), pszSearchPath);
+ PathRemoveFileSpec(szFile);
+ PathAppend(szFile, wfd.cFileName);
+
+ // Load the data from ini file
+ iSize = (pszSettingPrefix?(lstrlen(pszSettingPrefix)+1):0)+MAX_INT_LENGTH+1);
+ pszItem = (TCHAR*)mir_alloc(iSize*sizeof(TCHAR));
+ if (!pszItem) continue;
+
+ for (i=SL_MIN_POS;;i++) // no break condition
+ {
+ mir_sntprintf(pszItem, _T("%s%s%i"), iSize, pszSettingPrefix?pszSettingPrefix:_T(""), pszSettingPrefix?_T("|"):_T(""), i);
+
+ iLen = GetPrivateProfileString(pszSection, pszItem, NULL, NULL, 0, szFile);
+ if (iLen < 0) break;
+
+ pszBuf = (TCHAR*)mir_alloc((iLen+1)*sizeof(TCHAR));
+ if (!pszBuf) continue;
+
+ GetPrivateProfileString(pszSection, pszItem, NULL, pszBuf, iLen, szFile);
+ if (lstrlen(pszBuf) <= 0) break;
+
+ if (SLAddItem(psl, pszBuf) != SL_INVALID_POS)
+ if (!bReturn) bReturn = TRUE;
+
+ mir_free(pszBuf);
+ }
+
+ mir_free(pszItem);
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+
+ if (hFind) FindClose(hFind);
+
+ return bReturn;
+}
+
+
+
+BOOL SLSaveToIniFile(LPSTRINGLIST psl, const TCHAR* pszFileName, const TCHAR* pszSection, const TCHAR* pszSettingPrefix)
+{
+ int i;
+ char* pszItem;
+ int iSize;
+ BOOL bReturn = FALSE;
+
+ if (!psl || !pszSection || !pszFileName)
+ return FALSE;
+
+ iSize = (pszSettingPrefix?(lstrlen(pszSettingPrefix)+1):0)+MAX_INT_LENGTH+1;
+ pszItem = (TCHAR*)mir_alloc(iSize*sizeof(TCHAR));
+
+ if (pszItem)
+ {
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Delete old items (empty section)
+ WritePrivateProfileString(pszSection, NULL, NULL, pszFileName);
+
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ {
+ mir_sntprintf(pszItem, iSize, _T("%s%s%i"), pszSettingPrefix?pszSettingPrefix:_T(""), pszSettingPrefix?_T("|"):_T(""), i);
+
+ if (WritePrivateProfileString(pszSection, pszItem, psl->papszList[i], pszFileName))
+ bReturn = TRUE;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+
+ mir_free(pszItem);
+ }
+
+ return bReturn;
+}
+*/
+
+
+BOOL SLLoadFromFile(LPSTRINGLIST psl, const WCHAR* pszSearchPath)
+{
+ BOOL bReturn;
+ WIN32_FIND_DATA wfd;
+ HANDLE hFind;
+ BOOL bFileFound;
+ WCHAR szFile[MAX_PATH];
+ HANDLE hFile;
+ DWORD dwRead;
+ int iAllocBufSize;
+ int iAllocBufStep;
+ char* pszAllocBuf;
+ char* pszAllocBufTmp;
+ const char szBOM[3] = {0xEF, 0xBB, 0xBF};
+ BOOL bWatchBOM;
+ BOOL bEndOfFile;
+ WCHAR* pszContentConv;
+ WCHAR* pszBuf;
+
+ if (!psl || !pszSearchPath) return FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Initial buffer size (gets auto-enlarged if needed)
+ iAllocBufSize = 128; // read-in chars buffer
+ pszAllocBuf = NULL;
+
+ // Enum all files in the directory
+ bReturn = FALSE;
+ hFind = FindFirstFile(pszSearchPath, &wfd);
+ for (bFileFound=(hFind!=INVALID_HANDLE_VALUE); bFileFound; bFileFound=FindNextFile(hFind, &wfd))
+ {
+ if (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+ mir_sntprintf(szFile, ARRAYSIZE(szFile), _T("%s"), pszSearchPath);
+ PathRemoveFileSpec(szFile);
+ PathAppend(szFile, wfd.cFileName);
+
+ hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) continue;
+ bWatchBOM = TRUE;
+ bEndOfFile = FALSE;
+ iAllocBufStep = 0;
+ while (!bEndOfFile)
+ {
+ // Enlarge buffer if needed
+ if (!pszAllocBuf || (iAllocBufStep >= iAllocBufSize))
+ {
+ pszAllocBufTmp = (char*)mir_realloc(pszAllocBuf, (iAllocBufSize*2)*sizeof(char));
+ if (pszAllocBufTmp) {
+ if (pszAllocBuf) iAllocBufSize *= 2;
+ pszAllocBuf = pszAllocBufTmp;
+ } else {
+ bEndOfFile = TRUE; // out of memory
+ }
+ }
+ if (!bEndOfFile) {
+ if (!ReadFile(hFile, &pszAllocBuf[iAllocBufStep], sizeof(char), &dwRead, NULL))
+ bEndOfFile = TRUE;
+ if (dwRead < sizeof(char))
+ bEndOfFile = TRUE;
+ }
+ if ((pszAllocBuf[iAllocBufStep] == '\n') || bEndOfFile)
+ {
+ if (!bEndOfFile && (iAllocBufStep>0) && (pszAllocBuf[iAllocBufStep-1] == '\r'))
+ pszAllocBuf[iAllocBufStep-1] = '\0';
+ else
+ pszAllocBuf[iAllocBufStep] = '\0';
+
+ if (lstrlenA(pszAllocBuf) > 0)
+ {
+ // Test UTF-8 BOM
+ // EF BB BF = UTF-8
+ // -> indicating UTF-8 Unicode text file (check only once)
+ if (bWatchBOM)
+ {
+ if (StrCmpNA(pszAllocBuf, szBOM, ARRAYSIZE(szBOM)) == 0)
+ MoveMemory(pszAllocBuf, (PBYTE)pszAllocBuf+sizeof(szBOM), ((lstrlenA(pszAllocBuf)+1)*sizeof(char))-sizeof(szBOM));
+ bWatchBOM = FALSE;
+ }
+
+ // Decode Utf8
+ mir_utf8decode(pszAllocBuf,&pszContentConv);
+ if (pszContentConv)
+ {
+ pszBuf = pszContentConv;
+ while (pszBuf)
+ {
+ // Find comment indicator
+ pszBuf = StrChr(pszBuf, _T(';')); // find ";" comment indicator
+ if (pszBuf && (*CharPrev(pszContentConv, pszBuf) != _T('\\'))) // ignore "\;" chars
+ {
+ *pszBuf = _T('\0');
+ break;
+ }
+ }
+
+ // Replace no-comment indicators
+ pszBuf = ReplaceSubStringWithString(pszContentConv, _T("\\;"), _T(";"), TRUE, FALSE, NULL);
+
+ // Add item to list (disallow empty items)
+ if (lstrlen(pszContentConv) > 0)
+ if (SLAddItem(psl, pszBuf?pszBuf:pszContentConv) >= 0)
+ bReturn = TRUE;
+
+ mir_free(pszContentConv);
+ if (pszBuf) mir_free(pszBuf);
+ }
+ }
+
+ // Reset step count
+ iAllocBufStep = 0;
+
+ } else {
+ // Step up in string
+ iAllocBufStep++;
+ }
+
+ } // while (!bEndOfFile)
+
+ CloseHandle(hFile);
+ }
+
+ if (hFind) FindClose(hFind);
+ if (pszAllocBuf) mir_free(pszAllocBuf);
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+
+BOOL SLSaveToFile(LPSTRINGLIST psl, const WCHAR* pszFileName)
+{
+ BOOL bReturn;
+ int i;
+ const char szBOM[3] = {0xEF, 0xBB, 0xBF};
+ HANDLE hFile;
+ DWORD dwWritten; // Win98 compatibility
+ WCHAR* pszBuf;
+ char* pszContentUtf8;
+
+ if (!psl || !pszFileName) return FALSE;
+ hFile = CreateFile(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) return FALSE;
+ bReturn = FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Write UTF-8 BOM
+ // EF BB BF = UTF-8
+ // -> indicating UTF-8 Unicode text file
+ if (WriteFile(hFile, &szBOM, sizeof(szBOM), &dwWritten, NULL))
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ {
+ // Replace comment indicators
+ pszBuf = ReplaceSubStringWithString(psl->papszList[i], _T(";"), _T("\\;"), TRUE, FALSE, NULL);
+ if (!pszBuf) continue;
+ pszContentUtf8 = mir_utf8encodeW(pszBuf);
+ if (pszContentUtf8) {
+ if (WriteFile(hFile, pszContentUtf8, lstrlenA(pszContentUtf8)*sizeof(char), &dwWritten, NULL))
+ if (WriteFile(hFile, "\r\n", 2*sizeof(char), &dwWritten, NULL))
+ bReturn = TRUE;
+ mir_free(pszContentUtf8);
+ }
+ mir_free(pszBuf);
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ SetEndOfFile(hFile); // if it was longer before
+ FlushFileBuffers(hFile); // just to be sure
+ CloseHandle(hFile);
+ return bReturn;
+}
+
+
+/*
+BOOL SLConvertFromString(LPSTRINGLIST psl, const TCHAR* pszString, int cchSize, const TCHAR* pszSeparator, BOOL bIgnoreEmptyItems)
+{
+ // If pszSeparator is NULL a _T('\0') is taken as separator
+ BOOL bReturn;
+ int cchSepLen;
+
+ BOOL bReachedEnd;
+ TCHAR* pszAfterPrev;
+ TCHAR* pszNext;
+ int iPos;
+
+ if (!pszString || !psl) return 0;
+
+ if (cchSize < 0) cchSize = lstrlen(pszString)+1;
+ cchSepLen = pszSeparator?lstrlen(pszSeparator):1;
+
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Loop through string
+ bReturn = 0;
+ pszAfterPrev = (TCHAR*)pszString;
+ bReachedEnd = FALSE;
+ while (!bReachedEnd)
+ {
+ // Find first/next occurence
+ if (pszSeparator)
+ {
+ pszNext = StrStr(pszAfterPrev, pszSeparator);
+ if (!pszNext)
+ {
+ bReachedEnd = TRUE;
+ pszNext = (TCHAR*)pszString+(cchSize*sizeof(TCHAR));
+ }
+
+ } else {
+
+ // Find NULL separator
+ pszNext = pszAfterPrev;
+ while (*pszNext != _T('\0'));
+ {
+ pszNext = CharNext(pszNext);
+ if ( pszNext >= (szString+((cchSize-1)*sizeof(TCHAR)) )
+ {
+ bReachedEnd = TRUE;
+ break;
+ }
+ }
+ }
+
+ // Add item
+ if (!bIgnoreEmptyItems || (pszNext != pszAfterPrev))
+ {
+ i2
+ if (iPos < 0) continue;
+ CopyMemory((PBYTE)psl->papszList[iPos], pszAfterPrev, ((PBYTE)pszNext-(PBYTE)pszAfterPrev));
+
+ bReturn = TRUE;
+ }
+
+ // Step up one separated item
+ pszAfterPrev = pszNext+(cchSepLen*sizeof(TCHAR));
+ if ( pszAfterPrev >= pszString+((cchSize-1)*sizeof(TCHAR)) )
+ bReachedEnd = TRUE;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+
+ return bReturn;
+}
+*/
+
+
+WCHAR* SLConvertToString(LPSTRINGLIST psl, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast, int* piSize)
+{
+ // Returned string needs to be freed with SLFreeReturn()
+ // If pszSeparator is NULL a _T('\0') is taken as separator
+
+ int i;
+ int iSepLen;
+ int iSize;
+ WCHAR* pszReturn;
+ WCHAR* pszStep;
+
+ if (piSize) *piSize = 0;
+ if (!psl) return NULL;
+
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Get needed size
+ iSepLen = pszSeparator?lstrlen(pszSeparator):1;
+ iSize = SLGetSize(psl, FALSE)+1; // character count in string list
+ if (psl->uCount > 0) iSize += (psl->uCount-1)*iSepLen;
+ if ((psl->uCount > 0) && bAlsoDoFirst) iSize += iSepLen;
+ if (bAlsoDoLast) iSize += iSepLen;
+
+ pszReturn = (WCHAR*)SLAlloc(iSize*sizeof(WCHAR));
+ if (!pszReturn) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return NULL;
+ }
+ if (piSize) *piSize = iSize;
+
+ // Add items to memory
+ pszStep = pszReturn;
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ {
+ if ((i>SL_MIN_POS) || bAlsoDoFirst)
+ {
+ if (pszSeparator)
+ CopyMemory(pszStep, pszSeparator, iSepLen*sizeof(WCHAR)); // no terminating zero
+ else
+ ZeroMemory(pszStep, sizeof(WCHAR));
+ pszStep = &pszStep[iSepLen];
+ }
+
+ // Add item
+ CopyMemory(pszStep, psl->papszList[i], lstrlen(psl->papszList[i])*sizeof(WCHAR)); // no terminating zero
+ pszStep = &pszStep[lstrlen(psl->papszList[i])];
+ }
+ LeaveCriticalSection(&psl->csListAccess);
+
+ if (bAlsoDoLast)
+ {
+ if (pszSeparator)
+ CopyMemory(pszStep, pszSeparator, iSepLen*sizeof(WCHAR)); // no terminating zero
+ else
+ ZeroMemory(pszStep, sizeof(WCHAR));
+ pszStep = &pszStep[iSepLen];
+ }
+
+ ZeroMemory(pszStep, sizeof(WCHAR));
+ return pszReturn;
+}
+
+void SLFreeReturn(void* pPntr)
+{
+ if (pPntr) SLFree(pPntr);
+}
+
+BOOL SLConvertToStringBuf(LPSTRINGLIST psl, WCHAR* pszOutput, int cchMaxSize, const WCHAR* pszSeparator, BOOL bAlsoDoFirst, BOOL bAlsoDoLast)
+{
+ BOOL bReturn;
+ int iSize;
+ WCHAR* pszBuf;
+
+ if (!psl || !pszOutput || (cchMaxSize <= 0)) return FALSE;
+ pszBuf = SLConvertToString(psl, pszSeparator, bAlsoDoFirst, bAlsoDoLast, &iSize);
+ if (pszBuf) {
+ if (cchMaxSize < iSize) iSize = cchMaxSize;
+ CopyMemory(pszOutput, pszBuf, iSize*sizeof(WCHAR));
+ SLFreeReturn(pszBuf);
+ bReturn = TRUE;
+ } else {
+ iSize = 1;
+ bReturn = FALSE;
+ }
+ if (cchMaxSize > 1)
+ ZeroMemory(&pszOutput[iSize-1], sizeof(WCHAR));
+ if (!pszSeparator && bAlsoDoLast && (cchMaxSize > 2))
+ ZeroMemory(&pszOutput[iSize], sizeof(WCHAR));
+ return bReturn;
+}
+
+
+BOOL SLMergeList(LPSTRINGLIST pslDest, LPSTRINGLIST pslFrom)
+{
+ BOOL bReturn;
+ int i;
+
+ if (!pslDest || !pslFrom || (pslDest == pslFrom)) return FALSE;
+ EnterCriticalSection(&pslFrom->csListAccess); // first list
+ if (pslFrom->uCount == 0) {
+ LeaveCriticalSection(&pslFrom->csListAccess);
+ return TRUE;
+ }
+ EnterCriticalSection(&pslDest->csListAccess); // second list
+ bReturn = FALSE;
+ for (i=SL_MIN_POS; i<(int)(pslFrom->uCount); i++)
+ if (SLAddItem(pslDest, pslFrom->papszList[i]) != SL_INVALID_POS)
+ bReturn = TRUE;
+ LeaveCriticalSection(&pslFrom->csListAccess); // first list
+ LeaveCriticalSection(&pslDest->csListAccess); // second list
+ return bReturn;
+}
+
+
+int SLFindItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive, int iStartPos)
+{
+ int i, iReturn;
+
+ if (!psl || !pszItem) return SL_INVALID_POS;
+ EnterCriticalSection(&psl->csListAccess);
+ if (!SLIsValid(psl, iStartPos)) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return SL_INVALID_POS;
+ }
+ iReturn = SL_INVALID_POS;
+ for (i=iStartPos; i<(int)psl->uCount; i++)
+ if ((bCaseSensitive?StrCmp(psl->papszList[i], pszItem):StrCmpI(psl->papszList[i], pszItem)) == 0) {
+ iReturn = i;
+ break;
+ }
+ LeaveCriticalSection(&psl->csListAccess);
+ return iReturn;
+}
+
+BOOL SLIsItem(LPSTRINGLIST psl, const WCHAR* pszItem, BOOL bCaseSensitive)
+{
+ return (SLFindItem(psl, pszItem, bCaseSensitive, SL_MIN_POS) != SL_INVALID_POS);
+}
+
+int SLAddItem(LPSTRINGLIST psl, const WCHAR* pszNewItem)
+{
+ WCHAR** apszBuf;
+ WCHAR* pszBuf;
+ int i;
+
+ if (!psl) return SL_INVALID_POS;
+ EnterCriticalSection(&psl->csListAccess);
+ if (((int)(psl->uCount+1) <= 0) || ((int)(psl->uCount+1) == psl->uCount)) {
+ #if defined(_DEBUG)
+ OutputDebugString(_T("Spam Filter: Stringlist overflow.\r\n"));
+ DebugBreak();
+ #endif
+ LeaveCriticalSection(&psl->csListAccess);
+ return SL_INVALID_POS;
+ }
+
+ // Create/Resize the array
+ if (!psl->papszList) {
+ apszBuf = (WCHAR**)SLAlloc(sizeof(WCHAR*));
+ psl->uCount = 0;
+ } else {
+ apszBuf = (WCHAR**)SLReAlloc(psl->papszList, (psl->uCount+1)*sizeof(WCHAR*));
+ }
+ if (apszBuf) {
+ psl->papszList = apszBuf;
+ } else {
+ LeaveCriticalSection(&psl->csListAccess);
+ return SL_INVALID_POS;
+ }
+
+ // Prepare new string memory
+ pszBuf = (WCHAR*)SLAlloc(((pszNewItem?lstrlen(pszNewItem):0)+1)*sizeof(WCHAR));
+ if (!pszBuf) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return SL_INVALID_POS;
+ }
+ // Prepare new string
+ if (pszNewItem)
+ CopyMemory(pszBuf, pszNewItem, (lstrlen(pszNewItem)+1)*sizeof(WCHAR));
+ else
+ ZeroMemory(pszBuf, sizeof(WCHAR));
+
+ // Insert the new string
+ i = psl->uCount;
+ psl->papszList[i] = pszBuf;
+ psl->uCount++;
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return i;
+}
+
+int SLAddItemPair(LPSTRINGLIST psl, const WCHAR* pszNewItem1, const WCHAR* pszNewItem2)
+{
+ int iPos;
+
+ if (!psl) return SL_INVALID_POS;
+ EnterCriticalSection(&psl->csListAccess);
+ iPos = SLAddItem(psl, pszNewItem1);
+ if (iPos != SL_INVALID_POS)
+ if (SLAddItem(psl, pszNewItem2) == SL_INVALID_POS)
+ SLDeleteItem(psl, iPos);
+ LeaveCriticalSection(&psl->csListAccess);
+ return iPos;
+}
+
+int SLPrepareItem(LPSTRINGLIST psl, int cchLength)
+{
+ int iPos;
+
+ if (!psl) return SL_INVALID_POS;
+ EnterCriticalSection(&psl->csListAccess);
+ iPos = SLAddItem(psl, NULL); // empty item
+ if (iPos != SL_INVALID_POS)
+ if (!SLSetItemLength(psl, iPos, cchLength)) {
+ SLDeleteItem(psl, iPos);
+ iPos = SL_INVALID_POS;
+ }
+ LeaveCriticalSection(&psl->csListAccess);
+ return iPos;
+}
+
+/*
+BOOL SLAddItems(LPSTRINGLIST psl, const TCHAR* apszNewItems[], UINT uNewItemsCount)
+{
+ int i;
+ TCHAR** apszBuf;
+
+ if (!psl || !apszNewItems || (uNewItemsCount <= 0))
+ return FALSE;
+
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Create/Resize the array
+ if (!psl->papszList) {
+ apszBuf = (TCHAR**)SLAlloc(uNewItemCount*sizeof(TCHAR*));
+ psl->uCount = 0; // just to be sure
+ } else {
+ apszBuf = (TCHAR**)SLReAlloc(psl->papszList, (psl->uCount+uNewItemCount)*sizeof(TCHAR*));
+ }
+
+ if (apszBuf) {
+ psl->papszList = apszBuf;
+ } else {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+
+ // Insert the new string
+ for (i=SL_MIN_POS; i<=iNewItemCount; i++)
+ {
+ psl->papszList[psl->uCount+i] = (TCHAR*)SLAlloc((lstrlen(apszNewItems[i])+1)*sizeof(TCHAR));
+
+ if (psl->papszList[psl->uCount+i])
+ {
+ CopyMemory((PBYTE)psl->papszList[psl->uCount+i], apszNewItems[i], (lstrlen(apszNewItems[i])+1)*sizeof(TCHAR));
+ // Increase list count
+ psl->uCount++;
+
+ } else {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+*/
+
+BOOL SLDeleteItems(LPSTRINGLIST psl, int iPosFirst, int iPosLast)
+{
+ int i;
+ WCHAR** apszBuf;
+
+ if (!psl) return FALSE;
+ if (iPosLast < iPosFirst) {
+ i = iPosLast;
+ iPosLast = iPosFirst;
+ iPosFirst = i;
+ }
+ EnterCriticalSection(&psl->csListAccess);
+ if (!SLIsValid(psl, iPosFirst) || !SLIsValid(psl, iPosLast)) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+
+ for (i=iPosFirst; i<=iPosLast; i++)
+ SLFree(psl->papszList[i]);
+ if ((iPosLast+1) < (int)uMsgTypesCount)
+ MoveMemory(&pamtdMsgTypes[iPosFirst], &pamtdMsgTypes[iPosLast+1], (iPosLast-iPosFirst+1)*sizeof(WCHAR));
+
+ psl->uCount -= (iPosLast-iPosFirst+1);
+
+ if (psl->papszList && (psl->uCount > 0)) {
+ apszBuf = (WCHAR**)SLReAlloc(psl->papszList, psl->uCount*sizeof(WCHAR*));
+ if (apszBuf) psl->papszList = apszBuf;
+ } else {
+ if (psl->papszList) SLFree(psl->papszList);
+ psl->papszList = NULL;
+ psl->uCount = 0;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+
+BOOL SLDeleteItem(LPSTRINGLIST psl, int iPos)
+{
+ return SLDeleteItems(psl, iPos, iPos);
+}
+
+BOOL SLSetItemLength(LPSTRINGLIST psl, int iPos, int cchLength)
+{
+ WCHAR* pszBuf;
+ int iOldLen;
+ BOOL bReturn;
+
+ if (!psl) return FALSE;
+ if (cchLength < 0) cchLength = 0;
+ EnterCriticalSection(&psl->csListAccess);
+ if (!SLIsValid(psl, iPos)) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+
+ iOldLen = lstrlen(psl->papszList[iPos]);
+ pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], (cchLength+1)*sizeof(WCHAR));
+ if (pszBuf) {
+ psl->papszList[iPos] = pszBuf;
+ if (cchLength <= iOldLen)
+ ZeroMemory(&pszBuf[cchLength], sizeof(WCHAR));
+ else
+ ZeroMemory(&pszBuf[iOldLen], (cchLength-iOldLen+1)*sizeof(WCHAR));
+ bReturn = TRUE;
+ } else {
+ bReturn = FALSE;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+
+BOOL SLChangeItem(LPSTRINGLIST psl, int iPos, WCHAR* pszNewStr, BOOL bDoAppend)
+{
+ BOOL bReturn;
+ WCHAR* pszBuf;
+
+ if (!psl) return FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+ if (!SLIsValid(psl, iPos)) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+
+ pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], ((pszNewStr?lstrlen(pszNewStr):0) + (bDoAppend?lstrlen(psl->papszList[iPos]):0) + 1)*sizeof(WCHAR));
+ if (pszBuf)
+ {
+ psl->papszList[iPos] = pszBuf;
+
+ if (bDoAppend && pszNewStr)
+ CopyMemory(&pszBuf[lstrlen(pszBuf)], pszNewStr, (lstrlen(pszNewStr)+1)*sizeof(WCHAR));
+ else if (pszNewStr)
+ CopyMemory(pszBuf, pszNewStr, (lstrlen(pszNewStr)+1)*sizeof(WCHAR));
+ else if (!bDoAppend)
+ ZeroMemory(psl->papszList[iPos], sizeof(WCHAR));
+
+ bReturn = TRUE;
+ } else {
+ if (!bDoAppend) ZeroMemory(psl->papszList[iPos], sizeof(WCHAR));
+ bReturn = FALSE;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+
+
+BOOL SLItemPrintf(LPSTRINGLIST psl, int iPos, int cchArgMaxLen, ...)
+{
+ BOOL bReturn = FALSE;
+ WCHAR* pszBuf;
+ WCHAR* pszFmt;
+ va_list arglist;
+
+ if (!psl) return FALSE;
+ if (cchArgMaxLen < 0) cchArgMaxLen = 0;
+ EnterCriticalSection(&psl->csListAccess);
+ if (SLIsValid(psl, iPos))
+ {
+ pszFmt = (WCHAR*)SLAlloc((lstrlen(psl->papszList[iPos])+1)*sizeof(WCHAR));
+ if (pszFmt)
+ {
+ CopyMemory(pszFmt, psl->papszList[iPos], (lstrlen(psl->papszList[iPos])+1)*sizeof(WCHAR));
+ pszBuf = (WCHAR*)SLReAlloc(psl->papszList[iPos], (lstrlen(psl->papszList[iPos])+cchArgMaxLen+1)*sizeof(WCHAR));
+ if (pszBuf)
+ {
+ psl->papszList[iPos] = pszBuf;
+
+ va_start(arglist, cchArgMaxLen);
+ mir_vsntprintf(pszBuf, lstrlen(pszBuf)+cchArgMaxLen+1, pszFmt, arglist);
+ va_end(arglist);
+
+ bReturn = TRUE;
+ mir_free(pszFmt);
+ }
+ }
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+
+/*
+BOOL SLMoveItem(LPSTRINGLIST psl, int iOldPos, int iNewPos, BOOL bOnlySwitch)
+{
+ TCHAR* pszBuf;
+
+ if (!psl) return FALSE;
+
+ EnterCriticalSection(&psl->csListAccess);
+
+ if (!SLIsValid(psl, iOldPos) || !SLIsValid(psl, iNewPos)) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return FALSE;
+ }
+
+ if (iNewPos == iOldPos) {
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+ }
+
+ if (bOnlySwitch)
+ {
+ // Switch the items
+ pszBuf = psl->papszList[iOldPos];
+ psl->papszList[iOldPos] = psl->papszList[iNewPos];
+ psl->papszList[iOldPos] = pszBuf;
+
+ } else {
+
+ int i;
+
+ // Cache the old item
+ pszBuf = psl->papszList[iOldPos];
+
+ if (iNewPos > iOldPos)
+ {
+ // Move items in between one down
+ for (i=iNewPos; i<iOldPos; i++)
+ psl->papszList[i+1] = psl->papszList[i];
+ } else {
+ // Move items in between one up
+ for (i=(iOldPos+1); i<=iNewPos; i++)
+ psl->papszList[i] = psl->papszList[i+1];
+ }
+
+ psl->papszList[iNewPos] = pszBuf;
+ }
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+*/
+
+BOOL SLIsValid(LPSTRINGLIST psl, int iPos)
+{
+ BOOL bReturn;
+
+ if (!psl) return FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+ bReturn = (psl->papszList && (iPos>=SL_MIN_POS) && (iPos<(int)psl->uCount));
+ LeaveCriticalSection(&psl->csListAccess);
+ return bReturn;
+}
+
+WCHAR* SLGetItem(LPSTRINGLIST psl, int iPos)
+{
+ WCHAR* pszReturn;
+
+ EnterCriticalSection(&psl->csListAccess); // other operations finished
+ pszReturn = SLIsValid(psl, iPos) ? psl->papszList[iPos] : NULL;
+ LeaveCriticalSection(&psl->csListAccess);
+ return pszReturn;
+}
+
+int SLGetMaxPos(LPSTRINGLIST psl)
+{
+ int iReturn;
+
+ if (!psl) return SL_INVALID_POS;
+ EnterCriticalSection(&psl->csListAccess); // other operations finished
+ iReturn = (psl->uCount > 0) ? (int)(psl->uCount-1) : SL_INVALID_POS;
+ LeaveCriticalSection(&psl->csListAccess);
+ return iReturn;
+}
+
+
+int SLGetItemCount(LPSTRINGLIST psl)
+{
+ int iReturn;
+ if (!psl) return 0;
+
+ EnterCriticalSection(&psl->csListAccess); // other operations finished
+ iReturn = (int)psl->uCount;
+ LeaveCriticalSection(&psl->csListAccess);
+ return iReturn;
+}
+
+
+int SLGetSize(LPSTRINGLIST psl, BOOL bAlsoTerminatingZeros) // character count size
+{
+ int i, iReturn;
+
+ if (!psl) return 0;
+ EnterCriticalSection(&psl->csListAccess);
+ iReturn = 0;
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ iReturn += lstrlen(psl->papszList[i]);
+ if (bAlsoTerminatingZeros)
+ iReturn += (int)psl->uCount;
+ LeaveCriticalSection(&psl->csListAccess);
+ return iReturn;
+}
+
+BOOL SLClearList(LPSTRINGLIST psl)
+{
+ int i;
+
+ if (!psl) return FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+
+ // Free string memory
+ for (i=SL_MIN_POS; i<(int)psl->uCount; i++)
+ SLFree(psl->papszList[i]);
+
+ // Free the array
+ psl->uCount = 0;
+ if (psl->papszList) SLFree(psl->papszList);
+ psl->papszList = NULL;
+
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+
+/*
+BOOL SLBlockList(LPSTRINGLIST psl)
+{
+ if (!psl) return FALSE;
+ EnterCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+
+BOOL SLUnBlockList(LPSTRINGLIST psl)
+{
+ if (!psl) return FALSE;
+ LeaveCriticalSection(&psl->csListAccess);
+ return TRUE;
+}
+*/
+
+LPSTRINGLIST SLNewList(void)
+{
+ LPSTRINGLIST psl = (LPSTRINGLIST)SLAlloc(sizeof(STRINGLIST));
+ psl->papszList = NULL;
+ psl->uCount = 0;
+ InitializeCriticalSection(&psl->csListAccess);
+ return psl;
+
+}
+
+void SLFreeList(LPSTRINGLIST psl)
+{
+ if (!psl) return;
+ SLClearList(psl);
+ DeleteCriticalSection(&psl->csListAccess);
+ SLFree(psl);
} \ No newline at end of file