summaryrefslogtreecommitdiff
path: root/stringlist.c
diff options
context:
space:
mode:
authorGluzskiy Alexandr <sss123next@gmail.com>2010-02-15 05:51:01 +0300
committerGluzskiy Alexandr <sss123next@gmail.com>2010-02-15 05:51:01 +0300
commit7fd9fe181150f166a098eaf4e006f878c28cb770 (patch)
tree093af9d26a08e6bac60112a9c5f2f870ddef0fe8 /stringlist.c
parent6f32ef233b95d78efb905c97081193a2a454590e (diff)
sort
Diffstat (limited to 'stringlist.c')
-rw-r--r--stringlist.c1007
1 files changed, 1007 insertions, 0 deletions
diff --git a/stringlist.c b/stringlist.c
new file mode 100644
index 0000000..e1d6de5
--- /dev/null
+++ b/stringlist.c
@@ -0,0 +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);
+} \ No newline at end of file