diff options
author | Kirill Volinsky <mataes2007@gmail.com> | 2012-05-18 22:10:43 +0000 |
---|---|---|
committer | Kirill Volinsky <mataes2007@gmail.com> | 2012-05-18 22:10:43 +0000 |
commit | 725f68b6808a8a30778f58223fac75386f082785 (patch) | |
tree | ccba410760749d45139e5e78fd5e08f416ade1a0 /plugins/Utils | |
parent | f920ef497f3299ae24fe783ce03bdd93b419f764 (diff) |
plugins folders renaming
git-svn-id: http://svn.miranda-ng.org/main/trunk@61 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Utils')
27 files changed, 5429 insertions, 0 deletions
diff --git a/plugins/Utils/ContactAsyncQueue.cpp b/plugins/Utils/ContactAsyncQueue.cpp new file mode 100644 index 0000000000..2d5d1f104d --- /dev/null +++ b/plugins/Utils/ContactAsyncQueue.cpp @@ -0,0 +1,234 @@ +/*
+Copyright (C) 2006-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#include "ContactAsyncQueue.h"
+#include <process.h>
+
+
+// Itens with higher time at end
+static int QueueSortItems(const QueueItem *oldItem, const QueueItem *newItem)
+{
+ if (oldItem->check_time == newItem->check_time)
+ return -1;
+
+ return oldItem->check_time - newItem->check_time;
+}
+
+// Itens with higher time at end
+static void ContactAsyncQueueThread(void *obj)
+{
+ ((ContactAsyncQueue *)obj)->Thread();
+}
+
+ContactAsyncQueue::ContactAsyncQueue(pfContactAsyncQueueCallback fContactAsyncQueueCallback, int initialSize)
+ : queue(30, QueueSortItems)
+{
+ hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ finished = 0;
+ callback = fContactAsyncQueueCallback;
+
+ InitializeCriticalSection(&cs);
+
+ _beginthread(ContactAsyncQueueThread, 0, this);
+ //mir_forkthread(ContactAsyncQueueThread, this);
+}
+
+ContactAsyncQueue::~ContactAsyncQueue()
+{
+ Finish();
+
+ int count = 0;
+ while(finished != 2 && ++count < 50)
+ Sleep(30);
+
+ for (int i = 0; i < queue.getCount(); i++)
+ if (queue[i] != NULL)
+ mir_free(queue[i]);
+
+ DeleteCriticalSection(&cs);
+}
+
+void ContactAsyncQueue::Finish()
+{
+ if (finished == 0)
+ finished = 1;
+ SetEvent(hEvent);
+}
+
+void ContactAsyncQueue::Lock()
+{
+ EnterCriticalSection(&cs);
+}
+
+void ContactAsyncQueue::Release()
+{
+ LeaveCriticalSection(&cs);
+}
+
+void ContactAsyncQueue::RemoveAll(HANDLE hContact)
+{
+ Lock();
+
+ for (int i = queue.getCount() - 1; i >= 0; --i)
+ {
+ QueueItem *item = queue[i];
+
+ if (item->hContact == hContact)
+ {
+ queue.remove(i);
+ mir_free(item);
+ }
+ }
+
+ Release();
+}
+
+void ContactAsyncQueue::RemoveAllConsiderParam(HANDLE hContact, void *param)
+{
+ Lock();
+
+ for (int i = queue.getCount() - 1; i >= 0; --i)
+ {
+ QueueItem *item = queue[i];
+
+ if (item->hContact == hContact && item->param == param)
+ {
+ queue.remove(i);
+ mir_free(item);
+ }
+ }
+
+ Release();
+}
+
+void ContactAsyncQueue::Add(int waitTime, HANDLE hContact, void *param)
+{
+ Lock();
+
+ InternalAdd(waitTime, hContact, param);
+
+ Release();
+}
+
+void ContactAsyncQueue::AddIfDontHave(int waitTime, HANDLE hContact, void *param)
+{
+ Lock();
+
+ int i;
+ for (i = queue.getCount() - 1; i >= 0; --i)
+ if (queue[i]->hContact == hContact)
+ break;
+
+ if (i < 0)
+ InternalAdd(waitTime, hContact, param);
+
+ Release();
+}
+
+void ContactAsyncQueue::AddAndRemovePrevious(int waitTime, HANDLE hContact, void *param)
+{
+ Lock();
+
+ RemoveAll(hContact);
+ InternalAdd(waitTime, hContact, param);
+
+ Release();
+}
+
+void ContactAsyncQueue::AddAndRemovePreviousConsiderParam(int waitTime, HANDLE hContact, void *param)
+{
+ Lock();
+
+ RemoveAllConsiderParam(hContact, param);
+ InternalAdd(waitTime, hContact, param);
+
+ Release();
+}
+
+void ContactAsyncQueue::InternalAdd(int waitTime, HANDLE hContact, void *param)
+{
+ QueueItem *item = (QueueItem *) mir_alloc(sizeof(QueueItem));
+ item->hContact = hContact;
+ item->check_time = GetTickCount() + waitTime;
+ item->param = param;
+
+ queue.insert(item);
+
+ SetEvent(hEvent);
+}
+
+void ContactAsyncQueue::Thread()
+{
+ while (!finished)
+ {
+ ResetEvent(hEvent);
+
+ if (finished)
+ break;
+
+ Lock();
+
+ if (queue.getCount() <= 0)
+ {
+ // No items, so supend thread
+ Release();
+
+ wait(/*INFINITE*/ 2 * 60 * 1000);
+ }
+ else
+ {
+ // Take a look at first item
+ QueueItem *qi = queue[0];
+
+ int dt = qi->check_time - GetTickCount();
+ if (dt > 0)
+ {
+ // Not time to request yet, wait...
+ Release();
+
+ wait(dt);
+ }
+ else
+ {
+ // Will request this item
+ queue.remove(0);
+
+ Release();
+
+ callback(qi->hContact, qi->param);
+
+ mir_free(qi);
+ }
+ }
+ }
+
+ finished = 2;
+}
+
+void ContactAsyncQueue::wait(int time)
+{
+ if (!finished)
+ WaitForSingleObject(hEvent, time);
+}
+
+
+
+
+
+
diff --git a/plugins/Utils/ContactAsyncQueue.h b/plugins/Utils/ContactAsyncQueue.h new file mode 100644 index 0000000000..b38509869d --- /dev/null +++ b/plugins/Utils/ContactAsyncQueue.h @@ -0,0 +1,95 @@ +/*
+Copyright (C) 2006-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __CONTACTASYNCQUEUE_H__
+# define __CONTACTASYNCQUEUE_H__
+
+#ifndef MIRANDA_VER
+#define MIRANDA_VER 0x0A00
+#endif
+
+#include <windows.h>
+#include <newpluginapi.h>
+#include <m_system_cpp.h>
+
+
+typedef void (*pfContactAsyncQueueCallback) (HANDLE hContact, void *param);
+
+
+struct QueueItem
+{
+ DWORD check_time;
+ HANDLE hContact;
+ void *param;
+};
+
+
+class ContactAsyncQueue
+{
+public:
+
+ ContactAsyncQueue(pfContactAsyncQueueCallback fContactAsyncQueueCallback, int initialSize = 10);
+ ~ContactAsyncQueue();
+
+ void Finish();
+
+ inline int Size() const { return queue.getCount(); }
+ inline int Remove(int idx) { mir_free(queue[idx]); return queue.remove(idx); }
+ inline QueueItem* Get(int idx) const { return queue[idx]; }
+
+
+ void RemoveAll(HANDLE hContact);
+ void RemoveAllConsiderParam(HANDLE hContact, void *param);
+ void Add(int waitTime, HANDLE hContact, void *param = NULL);
+ void AddIfDontHave(int waitTime, HANDLE hContact, void *param = NULL);
+ void AddAndRemovePrevious(int waitTime, HANDLE hContact, void *param = NULL);
+ void AddAndRemovePreviousConsiderParam(int waitTime, HANDLE hContact, void *param = NULL);
+
+ void Lock();
+ void Release();
+
+
+ void Thread();
+
+private:
+
+ LIST<QueueItem> queue;
+
+ CRITICAL_SECTION cs;
+ pfContactAsyncQueueCallback callback;
+ HANDLE hEvent;
+ int finished;
+
+
+ void InternalAdd(int waitTime, HANDLE hContact, void *param);
+ void wait(int time);
+};
+
+
+
+
+
+
+
+
+
+
+
+#endif // __CONTACTASYNCQUEUE_H__
diff --git a/plugins/Utils/MemoryModule.c b/plugins/Utils/MemoryModule.c new file mode 100644 index 0000000000..1e7ac0ac01 --- /dev/null +++ b/plugins/Utils/MemoryModule.c @@ -0,0 +1,540 @@ +/*
+ * Memory DLL loading code
+ * Version 0.0.2 with additions from Thomas Heller
+ *
+ * Copyright (c) 2004-2005 by Joachim Bauch / mail@joachim-bauch.de
+ * http://www.joachim-bauch.de
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MemoryModule.c
+ *
+ * The Initial Developer of the Original Code is Joachim Bauch.
+ *
+ * Portions created by Joachim Bauch are Copyright (C) 2004-2005
+ * Joachim Bauch. All Rights Reserved.
+ *
+ * Portions Copyright (C) 2005 Thomas Heller.
+ *
+ */
+
+// disable warnings about pointer <-> DWORD conversions
+#pragma warning( disable : 4311 4312 )
+
+#include <Windows.h>
+#include <winnt.h>
+#ifdef DEBUG_OUTPUT
+#include <stdio.h>
+#endif
+
+#ifndef IMAGE_SIZEOF_BASE_RELOCATION
+// Vista SDKs no longer define IMAGE_SIZEOF_BASE_RELOCATION!?
+# define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION))
+#endif
+#include "MemoryModule.h"
+
+
+struct NAME_TABLE {
+ char *name;
+ DWORD ordinal;
+};
+
+typedef struct tagMEMORYMODULE {
+ PIMAGE_NT_HEADERS headers;
+ unsigned char *codeBase;
+ HMODULE *modules;
+ int numModules;
+ int initialized;
+
+ struct NAME_TABLE *name_table;
+} MEMORYMODULE, *PMEMORYMODULE;
+
+typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
+
+#define GET_HEADER_DICTIONARY(module, idx) &(module)->headers->OptionalHeader.DataDirectory[idx]
+
+#ifdef DEBUG_OUTPUT
+static void
+OutputLastError(const char *msg)
+{
+ LPVOID tmp;
+ char *tmpmsg;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&tmp, 0, NULL);
+ tmpmsg = (char *)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3);
+ sprintf(tmpmsg, "%s: %s", msg, tmp);
+ OutputDebugString(tmpmsg);
+ LocalFree(tmpmsg);
+ LocalFree(tmp);
+}
+#endif
+
+static void
+CopySections(const unsigned char *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module)
+{
+ int i, size;
+ unsigned char *codeBase = module->codeBase;
+ unsigned char *dest;
+ PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
+ for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++)
+ {
+ if (section->SizeOfRawData == 0)
+ {
+ // section doesn't contain data in the dll itself, but may define
+ // uninitialized data
+ size = old_headers->OptionalHeader.SectionAlignment;
+ if (size > 0)
+ {
+ dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
+ size,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+
+ section->Misc.PhysicalAddress = (DWORD)dest;
+ memset(dest, 0, size);
+ }
+
+ // section is empty
+ continue;
+ }
+
+ // commit memory block and copy data from dll
+ dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
+ section->SizeOfRawData,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData);
+ section->Misc.PhysicalAddress = (DWORD)dest;
+ }
+}
+
+// Protection flags for memory pages (Executable, Readable, Writeable)
+static int ProtectionFlags[2][2][2] = {
+ {
+ // not executable
+ {PAGE_NOACCESS, PAGE_WRITECOPY},
+ {PAGE_READONLY, PAGE_READWRITE},
+ }, {
+ // executable
+ {PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY},
+ {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE},
+ },
+};
+
+static void
+FinalizeSections(PMEMORYMODULE module)
+{
+ int i;
+ PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
+
+ // loop through all sections and change access flags
+ for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++)
+ {
+ DWORD protect, oldProtect, size;
+ int executable = (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
+ int readable = (section->Characteristics & IMAGE_SCN_MEM_READ) != 0;
+ int writeable = (section->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
+
+ if (section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
+ {
+ // section is not needed any more and can safely be freed
+ VirtualFree((LPVOID)section->Misc.PhysicalAddress, section->SizeOfRawData, MEM_DECOMMIT);
+ continue;
+ }
+
+ // determine protection flags based on characteristics
+ protect = ProtectionFlags[executable][readable][writeable];
+ if (section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
+ protect |= PAGE_NOCACHE;
+
+ // determine size of region
+ size = section->SizeOfRawData;
+ if (size == 0)
+ {
+ if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
+ size = module->headers->OptionalHeader.SizeOfInitializedData;
+ else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ size = module->headers->OptionalHeader.SizeOfUninitializedData;
+ }
+
+ if (size > 0)
+ {
+ // change memory access flags
+ if (VirtualProtect((LPVOID)section->Misc.PhysicalAddress, size, protect, &oldProtect) == 0)
+#ifdef DEBUG_OUTPUT
+ OutputLastError("Error protecting memory page")
+#endif
+ ;
+ }
+ }
+}
+
+static void
+PerformBaseRelocation(PMEMORYMODULE module, DWORD delta)
+{
+ DWORD i;
+ unsigned char *codeBase = module->codeBase;
+
+ PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);
+ if (directory->Size > 0)
+ {
+ PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION)(codeBase + directory->VirtualAddress);
+ for (; relocation->VirtualAddress > 0; )
+ {
+ unsigned char *dest = (unsigned char *)(codeBase + relocation->VirtualAddress);
+ unsigned short *relInfo = (unsigned short *)((unsigned char *)relocation + IMAGE_SIZEOF_BASE_RELOCATION);
+ for (i=0; i<((relocation->SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++)
+ {
+ DWORD *patchAddrHL;
+ int type, offset;
+
+ // the upper 4 bits define the type of relocation
+ type = *relInfo >> 12;
+ // the lower 12 bits define the offset
+ offset = *relInfo & 0xfff;
+
+ switch (type)
+ {
+ case IMAGE_REL_BASED_ABSOLUTE:
+ // skip relocation
+ break;
+
+ case IMAGE_REL_BASED_HIGHLOW:
+ // change complete 32 bit address
+ patchAddrHL = (DWORD *)(dest + offset);
+ *patchAddrHL += delta;
+ break;
+
+ default:
+ //printf("Unknown relocation: %d\n", type);
+ break;
+ }
+ }
+
+ // advance to next relocation block
+ relocation = (PIMAGE_BASE_RELOCATION)(((DWORD)relocation) + relocation->SizeOfBlock);
+ }
+ }
+}
+
+static int
+BuildImportTable(PMEMORYMODULE module)
+{
+ int result=1;
+ unsigned char *codeBase = module->codeBase;
+
+ PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);
+ if (directory->Size > 0)
+ {
+ PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR)(codeBase + directory->VirtualAddress);
+ for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++)
+ {
+ DWORD *thunkRef, *funcRef;
+ HMODULE handle = LoadLibraryA((LPCSTR)(codeBase + importDesc->Name));
+ if (handle == INVALID_HANDLE_VALUE || handle == NULL)
+ {
+ //LastError should already be set
+#if DEBUG_OUTPUT
+ OutputLastError("Can't load library");
+#endif
+ result = 0;
+ break;
+ }
+
+ module->modules = (HMODULE *)realloc(module->modules, (module->numModules+1)*(sizeof(HMODULE)));
+ if (module->modules == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ result = 0;
+ break;
+ }
+
+ module->modules[module->numModules++] = handle;
+ if (importDesc->OriginalFirstThunk)
+ {
+ thunkRef = (DWORD *)(codeBase + importDesc->OriginalFirstThunk);
+ funcRef = (DWORD *)(codeBase + importDesc->FirstThunk);
+ } else {
+ // no hint table
+ thunkRef = (DWORD *)(codeBase + importDesc->FirstThunk);
+ funcRef = (DWORD *)(codeBase + importDesc->FirstThunk);
+ }
+ for (; *thunkRef; thunkRef++, funcRef++)
+ {
+ if IMAGE_SNAP_BY_ORDINAL(*thunkRef)
+ *funcRef = (DWORD)GetProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef));
+ else {
+ PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)(codeBase + *thunkRef);
+ *funcRef = (DWORD)GetProcAddress(handle, (LPCSTR)&thunkData->Name);
+ }
+ if (*funcRef == 0)
+ {
+ SetLastError(ERROR_PROC_NOT_FOUND);
+ result = 0;
+ break;
+ }
+ }
+
+ if (!result)
+ break;
+ }
+ }
+
+ return result;
+}
+
+HMEMORYMODULE MemoryLoadLibrary(const void *data)
+{
+ PMEMORYMODULE result;
+ PIMAGE_DOS_HEADER dos_header;
+ PIMAGE_NT_HEADERS old_header;
+ unsigned char *code, *headers;
+ DWORD locationDelta;
+ DllEntryProc DllEntry;
+ BOOL successfull;
+
+ dos_header = (PIMAGE_DOS_HEADER)data;
+ if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
+ {
+ SetLastError(ERROR_BAD_FORMAT);
+#if DEBUG_OUTPUT
+ OutputDebugString("Not a valid executable file.\n");
+#endif
+ return NULL;
+ }
+
+ old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(data))[dos_header->e_lfanew];
+ if (old_header->Signature != IMAGE_NT_SIGNATURE)
+ {
+ SetLastError(ERROR_BAD_FORMAT);
+#if DEBUG_OUTPUT
+ OutputDebugString("No PE header found.\n");
+#endif
+ return NULL;
+ }
+
+ // reserve memory for image of library
+ code = (unsigned char *)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase),
+ old_header->OptionalHeader.SizeOfImage,
+ MEM_RESERVE,
+ PAGE_READWRITE);
+
+ if (code == NULL)
+ // try to allocate memory at arbitrary position
+ code = (unsigned char *)VirtualAlloc(NULL,
+ old_header->OptionalHeader.SizeOfImage,
+ MEM_RESERVE,
+ PAGE_READWRITE);
+
+ if (code == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+#if DEBUG_OUTPUT
+ OutputLastError("Can't reserve memory");
+#endif
+ return NULL;
+ }
+
+ result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), 0, sizeof(MEMORYMODULE));
+ result->codeBase = code;
+ result->numModules = 0;
+ result->modules = NULL;
+ result->initialized = 0;
+ result->name_table = NULL;
+
+ // XXX: is it correct to commit the complete memory region at once?
+ // calling DllEntry raises an exception if we don't...
+ VirtualAlloc(code,
+ old_header->OptionalHeader.SizeOfImage,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+
+ // commit memory for headers
+ headers = (unsigned char *)VirtualAlloc(code,
+ old_header->OptionalHeader.SizeOfHeaders,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+
+ // copy PE header to code
+ memcpy(headers, dos_header, dos_header->e_lfanew + old_header->OptionalHeader.SizeOfHeaders);
+ result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew];
+
+ // update position
+ result->headers->OptionalHeader.ImageBase = (DWORD)code;
+
+ // copy sections from DLL file block to new memory location
+ CopySections(data, old_header, result);
+
+ // adjust base address of imported data
+ locationDelta = (DWORD)(code - old_header->OptionalHeader.ImageBase);
+ if (locationDelta != 0)
+ PerformBaseRelocation(result, locationDelta);
+
+ // load required dlls and adjust function table of imports
+ if (!BuildImportTable(result))
+ goto error;
+
+ // mark memory pages depending on section headers and release
+ // sections that are marked as "discardable"
+ FinalizeSections(result);
+
+ // get entry point of loaded library
+ if (result->headers->OptionalHeader.AddressOfEntryPoint != 0)
+ {
+ DllEntry = (DllEntryProc)(code + result->headers->OptionalHeader.AddressOfEntryPoint);
+ if (DllEntry == 0)
+ {
+ SetLastError(ERROR_BAD_FORMAT); /* XXX ? */
+#if DEBUG_OUTPUT
+ OutputDebugString("Library has no entry point.\n");
+#endif
+ goto error;
+ }
+
+ // notify library about attaching to process
+ successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0);
+ if (!successfull)
+ {
+#if DEBUG_OUTPUT
+ OutputDebugString("Can't attach library.\n");
+#endif
+ goto error;
+ }
+ result->initialized = 1;
+ }
+
+ return (HMEMORYMODULE)result;
+
+error:
+ // cleanup
+ MemoryFreeLibrary(result);
+ return NULL;
+}
+
+int _compare(const struct NAME_TABLE *p1, const struct NAME_TABLE *p2)
+{
+ return stricmp(p1->name, p2->name);
+}
+
+int _find(const char **name, const struct NAME_TABLE *p)
+{
+ return stricmp(*name, p->name);
+}
+
+struct NAME_TABLE *GetNameTable(PMEMORYMODULE module)
+{
+ unsigned char *codeBase;
+ PIMAGE_EXPORT_DIRECTORY exports;
+ PIMAGE_DATA_DIRECTORY directory;
+ DWORD i, *nameRef;
+ WORD *ordinal;
+ struct NAME_TABLE *p, *ptab;
+
+ if (module->name_table)
+ return module->name_table;
+
+ codeBase = module->codeBase;
+ directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXPORT);
+ exports = (PIMAGE_EXPORT_DIRECTORY)(codeBase + directory->VirtualAddress);
+
+ nameRef = (DWORD *)(codeBase + exports->AddressOfNames);
+ ordinal = (WORD *)(codeBase + exports->AddressOfNameOrdinals);
+
+ p = ((PMEMORYMODULE)module)->name_table = (struct NAME_TABLE *)malloc(sizeof(struct NAME_TABLE)
+ * exports->NumberOfNames);
+ if (p == NULL)
+ return NULL;
+ ptab = p;
+ for (i=0; i<exports->NumberOfNames; ++i) {
+ p->name = (char *)(codeBase + *nameRef++);
+ p->ordinal = *ordinal++;
+ ++p;
+ }
+ qsort(ptab, exports->NumberOfNames, sizeof(struct NAME_TABLE), _compare);
+ return ptab;
+}
+
+FARPROC MemoryGetProcAddress(HMEMORYMODULE module, const char *name)
+{
+ unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase;
+ int idx=-1;
+ PIMAGE_EXPORT_DIRECTORY exports;
+ PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT);
+
+ if (directory->Size == 0)
+ // no export table found
+ return NULL;
+
+ exports = (PIMAGE_EXPORT_DIRECTORY)(codeBase + directory->VirtualAddress);
+ if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0)
+ // DLL doesn't export anything
+ return NULL;
+
+ if (HIWORD(name)) {
+ struct NAME_TABLE *ptab;
+ struct NAME_TABLE *found;
+ ptab = GetNameTable((PMEMORYMODULE)module);
+ if (ptab == NULL)
+ // some failure
+ return NULL;
+ found = bsearch(&name, ptab, exports->NumberOfNames, sizeof(struct NAME_TABLE), _find);
+ if (found == NULL)
+ // exported symbol not found
+ return NULL;
+
+ idx = found->ordinal;
+ }
+ else
+ idx = LOWORD(name) - exports->Base;
+
+ if ((DWORD)idx > exports->NumberOfFunctions)
+ // name <-> ordinal number don't match
+ return NULL;
+
+ // AddressOfFunctions contains the RVAs to the "real" functions
+ return (FARPROC)(codeBase + *(DWORD *)(codeBase + exports->AddressOfFunctions + (idx*4)));
+}
+
+void MemoryFreeLibrary(HMEMORYMODULE mod)
+{
+ int i;
+ PMEMORYMODULE module = (PMEMORYMODULE)mod;
+
+ if (module != NULL)
+ {
+ if (module->initialized != 0)
+ {
+ // notify library about detaching from process
+ DllEntryProc DllEntry = (DllEntryProc)(module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint);
+ (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0);
+ module->initialized = 0;
+ }
+
+ if (module->modules != NULL)
+ {
+ // free previously opened libraries
+ for (i=0; i<module->numModules; i++)
+ if (module->modules[i] != INVALID_HANDLE_VALUE)
+ FreeLibrary(module->modules[i]);
+
+ free(module->modules);
+ }
+
+ if (module->codeBase != NULL)
+ // release memory of library
+ VirtualFree(module->codeBase, 0, MEM_RELEASE);
+
+ if (module->name_table != NULL)
+ free(module->name_table);
+
+ HeapFree(GetProcessHeap(), 0, module);
+ }
+}
diff --git a/plugins/Utils/MemoryModule.h b/plugins/Utils/MemoryModule.h new file mode 100644 index 0000000000..f314e5d1fb --- /dev/null +++ b/plugins/Utils/MemoryModule.h @@ -0,0 +1,48 @@ +/*
+ * Memory DLL loading code
+ * Version 0.0.2
+ *
+ * Copyright (c) 2004-2005 by Joachim Bauch / mail@joachim-bauch.de
+ * http://www.joachim-bauch.de
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MemoryModule.h
+ *
+ * The Initial Developer of the Original Code is Joachim Bauch.
+ *
+ * Portions created by Joachim Bauch are Copyright (C) 2004-2005
+ * Joachim Bauch. All Rights Reserved.
+ *
+ */
+
+#ifndef __MEMORY_MODULE_HEADER
+#define __MEMORY_MODULE_HEADER
+
+#include <Windows.h>
+
+typedef void *HMEMORYMODULE;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HMEMORYMODULE MemoryLoadLibrary(const void *);
+
+FARPROC MemoryGetProcAddress(HMEMORYMODULE, const char *);
+
+void MemoryFreeLibrary(HMEMORYMODULE);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __MEMORY_MODULE_HEADER
diff --git a/plugins/Utils/mir_buffer.h b/plugins/Utils/mir_buffer.h new file mode 100644 index 0000000000..492050faf8 --- /dev/null +++ b/plugins/Utils/mir_buffer.h @@ -0,0 +1,545 @@ +/*
+Copyright (C) 2005-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __MIR_BUFFER_H__
+# define __MIR_BUFFER_H__
+
+#include <windows.h>
+
+#include "mir_memory.h"
+#include <m_variables.h>
+
+
+template<class T>
+static int __bvsnprintf(T *str, size_t size, const T *fmt, va_list args)
+{
+ return 0;
+}
+
+template<>
+static inline int __bvsnprintf<char>(char *str, size_t size, const char *fmt, va_list args)
+{
+ return _vsnprintf(str, size, fmt, args);
+}
+
+template<>
+static inline int __bvsnprintf<wchar_t>(wchar_t *str, size_t size, const wchar_t *fmt, va_list args)
+{
+ return _vsnwprintf(str, size, fmt, args);
+}
+
+template<class T>
+static inline size_t __blen(const T *str)
+{
+ return 0;
+}
+
+template<>
+static inline size_t __blen<char>(const char *str)
+{
+ return strlen(str);
+}
+
+template<>
+static inline size_t __blen<wchar_t>(const wchar_t *str)
+{
+ return lstrlenW(str);
+}
+
+template<class T>
+static inline T * __bTranslate(const T *str)
+{
+ return 0;
+}
+
+template<>
+static inline char * __bTranslate<char>(const char *str)
+{
+ return Translate(str);
+}
+
+template<>
+static inline wchar_t * __bTranslate<wchar_t>(const wchar_t *str)
+{
+ return TranslateW(str);
+}
+
+
+template<class O, class D>
+static void __bcopy(D *dest, const O *orig, size_t len)
+{
+}
+
+template<>
+static void __bcopy(char *dest, const char *orig, size_t len)
+{
+ strncpy(dest, orig, len);
+}
+
+template<>
+static void __bcopy(WCHAR *dest, const WCHAR *orig, size_t len)
+{
+ wcsncpy(dest, orig, len);
+}
+
+template<>
+static void __bcopy(WCHAR *dest, const char *orig, size_t len)
+{
+ MultiByteToWideChar(CallService("LangPack/GetCodePage", 0, 0), 0, orig, (int)len, dest, (int)len);
+}
+
+template<>
+static void __bcopy(char *dest, const WCHAR *orig, size_t len)
+{
+ WideCharToMultiByte(CallService("LangPack/GetCodePage", 0, 0), 0, orig, (int)len, dest, (int)len, NULL, NULL);
+}
+
+
+
+template<class T>
+class Buffer
+{
+ public:
+ size_t len;
+ T *str;
+
+ Buffer() : str(NULL), size(0), len(0)
+ {
+ alloc(1);
+ pack();
+ }
+
+ Buffer(T in) : str(NULL), size(0), len(0)
+ {
+ if (in == NULL)
+ {
+ alloc(1);
+ pack();
+ }
+ else
+ {
+ str = in;
+ size = len = __blen(str);
+ }
+ }
+
+ ~Buffer()
+ {
+ free();
+ }
+
+ void pack()
+ {
+ if (str != NULL)
+ memset(&str[len], 0, sizeof(str[len]));
+ }
+
+ void alloc(size_t total)
+ {
+ if (total > size)
+ {
+ size = total + 256 - total % 256;
+ if (str == NULL)
+ str = (T *) mir_alloc(size * sizeof(T));
+ else
+ str = (T *) mir_realloc(str, size * sizeof(T));
+ }
+ }
+
+ void free()
+ {
+ if (str != NULL)
+ {
+ mir_free(str);
+ str = NULL;
+ len = size = 0;
+ }
+ }
+
+ void clear()
+ {
+ len = 0;
+ pack();
+ }
+
+ void append(T app)
+ {
+ alloc(len + 1 + 1);
+
+ str[len] = app;
+ len++;
+ pack();
+ }
+
+ void appendn(size_t n, T app)
+ {
+ alloc(len + n + 1);
+
+ for(; n > 0; n--)
+ {
+ str[len] = app;
+ len++;
+ }
+ pack();
+ }
+
+ void append(const char *app, size_t appLen = -1)
+ {
+ if (app == NULL)
+ return;
+ if (appLen == -1)
+ appLen = __blen(app);
+
+ size_t total = len + appLen + 1;
+ alloc(total);
+
+ __bcopy(&str[len], app, appLen);
+ len += appLen;
+ pack();
+ }
+
+ void append(const WCHAR *app, size_t appLen = -1)
+ {
+ if (app == NULL)
+ return;
+ if (appLen == -1)
+ appLen = __blen(app);
+
+ size_t total = len + appLen + 1;
+ alloc(total);
+
+ __bcopy(&str[len], app, appLen);
+ len += appLen;
+ pack();
+ }
+
+ void append(const Buffer<char> &app)
+ {
+ if (app.str == NULL)
+ return;
+ size_t appLen = app.len;
+
+ size_t total = len + appLen + 1;
+ alloc(total);
+
+ __bcopy(&str[len], app.str, appLen);
+ len += appLen;
+ pack();
+ }
+
+ void append(const Buffer<WCHAR> &app)
+ {
+ size_t appLen = app.len;
+
+ size_t total = len + appLen + 1;
+ alloc(total);
+
+ __bcopy(&str[len], app.str , appLen);
+ len += appLen;
+ pack();
+ }
+
+ void appendPrintf(const T *app, ...)
+ {
+ size_t total = len + 512;
+ alloc(total);
+
+ va_list arg;
+ va_start(arg, app);
+ total = __bvsnprintf<T>(&str[len], size - len - 1, app, arg);
+ if (total < 0)
+ total = size - len - 1;
+ len += total;
+ pack();
+ }
+
+ void insert(size_t pos, T *app, size_t appLen = -1)
+ {
+ if (pos > len)
+ pos = len;
+ if (pos < 0)
+ pos = 0;
+
+ if (appLen == -1)
+ appLen = __blen(app);
+
+ alloc(len + appLen + 1);
+
+ if (pos < len)
+ memmove(&str[pos + appLen], &str[pos], (len - pos) * sizeof(T));
+ memmove(&str[pos], app, appLen * sizeof(T));
+
+ len += appLen;
+ pack();
+ }
+
+ void replace(size_t start, size_t end, T *app, size_t appLen = -1)
+ {
+ if (start > len)
+ start = len;
+ if (start < 0)
+ start = 0;
+
+ if (end > len)
+ end = len;
+ if (end < start)
+ end = start;
+
+ if (appLen == -1)
+ appLen = __blen(app);
+
+ size_t oldLen = end - start;
+ if (oldLen < appLen)
+ alloc(len + appLen - oldLen + 1);
+
+ if (end < len && oldLen != appLen)
+ memmove(&str[start + appLen], &str[end], (len - end) * sizeof(T));
+ memmove(&str[start], app, appLen * sizeof(T));
+
+ len += appLen - oldLen;
+ pack();
+ }
+
+ void replaceAll(T find, T replace)
+ {
+ for(size_t i = 0; i < len; i++)
+ if (str[len] == find)
+ str[len] = replace;
+ pack();
+ }
+
+ void translate()
+ {
+ if (str == NULL || len == 0)
+ return;
+
+ str[len] = 0;
+ T *tmp = __bTranslate(str);
+ len = __blen(tmp);
+ alloc(len + 1);
+ memmove(str, tmp, len * sizeof(T));
+ pack();
+ }
+
+ void reverse()
+ {
+ for(size_t i = 0; i < len/2; i++)
+ {
+ T tmp = str[i];
+ str[i] = str[len-i-1];
+ str[len-i-1] = tmp;
+ }
+ }
+
+ T *appender(size_t appLen)
+ {
+ alloc(len + appLen + 1);
+ T *ret = &str[len];
+ len += appLen;
+ return ret;
+ }
+
+ T *lock(size_t maxSize)
+ {
+ alloc(len + maxSize + 1);
+ return &str[len];
+ }
+
+ void release()
+ {
+ len += max(__blen(&str[len]), size - len - 1);
+ }
+
+ T *detach()
+ {
+ T *ret = str;
+ str = NULL;
+ len = 0;
+ return ret;
+ }
+
+ void trimRight()
+ {
+ if (str == NULL)
+ return;
+
+ int e;
+ for(e = len-1; e >= 0 && (str[e] == (T)' '
+ || str[e] == (T)'\t'
+ || str[e] == (T)'\r'
+ || str[e] == (T)'\n'); e--) ;
+ len = e+1;
+ pack();
+ }
+
+ void trimLeft()
+ {
+ if (str == NULL)
+ return;
+
+ int s;
+ for(s = 0; str[s] == (T)' '
+ || str[s] == (T)'\t'
+ || str[s] == (T)'\r'
+ || str[s] == (T)'\n'; s++) ;
+ if (s > 0)
+ {
+ memmove(str, &str[s], (len - s) * sizeof(T));
+ len -= s;
+ }
+ pack();
+ }
+
+ void trim()
+ {
+ trimRight();
+ trimLeft();
+ }
+
+ Buffer<T>& operator+=(const char *txt)
+ {
+ append(txt);
+ return *this;
+ }
+
+ Buffer<T>& operator+=(const WCHAR *txt)
+ {
+ append(txt);
+ return *this;
+ }
+
+ Buffer<T>& operator+=(const Buffer<T> &txt)
+ {
+ append(txt);
+ return *this;
+ }
+
+ Buffer<T>& operator=(const char *txt)
+ {
+ clear();
+ append(txt);
+ return *this;
+ }
+
+ Buffer<T>& operator=(const WCHAR *txt)
+ {
+ clear();
+ append(txt);
+ return *this;
+ }
+
+ Buffer<T>& operator=(const Buffer<T> &txt)
+ {
+ clear();
+ append(txt);
+ return *this;
+ }
+
+
+ private:
+ size_t size;
+};
+
+
+static void ReplaceVars(Buffer<TCHAR> *buffer, HANDLE hContact, TCHAR **variables, int numVariables)
+{
+ if (buffer->len < 3)
+ return;
+
+ if (numVariables < 0)
+ return;
+
+ for(size_t i = buffer->len - 1; i > 0; i--)
+ {
+ if (buffer->str[i] == _T('%'))
+ {
+ // Find previous
+ size_t j;
+ for(j = i - 1; j > 0 && ((buffer->str[j] >= _T('a') && buffer->str[j] <= _T('z'))
+ || (buffer->str[j] >= _T('A') && buffer->str[j] <= _T('Z'))
+ || buffer->str[j] == _T('-')
+ || buffer->str[j] == _T('_')); j--) ;
+
+ if (buffer->str[j] == _T('%'))
+ {
+ size_t foundLen = i - j + 1;
+ if (foundLen == 9 && _tcsncmp(&buffer->str[j], _T("%contact%"), 9) == 0)
+ {
+ buffer->replace(j, i + 1, (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR | GCDNF_NOCACHE));
+ }
+ else if (foundLen == 6 && _tcsncmp(&buffer->str[j], _T("%date%"), 6) == 0)
+ {
+ TCHAR tmp[128];
+ DBTIMETOSTRINGT tst = {0};
+ tst.szFormat = _T("d s");
+ tst.szDest = tmp;
+ tst.cbDest = 128;
+ CallService(MS_DB_TIME_TIMESTAMPTOSTRINGT, (WPARAM) time(NULL), (LPARAM) &tst);
+ buffer->replace(j, i + 1, tmp);
+ }
+ else
+ {
+ for(int k = 0; k < numVariables; k += 2)
+ {
+ size_t len = lstrlen(variables[k]);
+ if (foundLen == len + 2 && _tcsncmp(&buffer->str[j]+1, variables[k], len) == 0)
+ {
+ buffer->replace(j, i + 1, variables[k + 1]);
+ break;
+ }
+ }
+ }
+ }
+
+ i = j;
+ if (i == 0)
+ break;
+ }
+ else if (buffer->str[i] == _T('\\') && i+1 <= buffer->len-1 && buffer->str[i+1] == _T('n'))
+ {
+ buffer->str[i] = _T('\r');
+ buffer->str[i+1] = _T('\n');
+ }
+ }
+}
+
+
+static void ReplaceTemplate(Buffer<TCHAR> *out, HANDLE hContact, TCHAR *templ, TCHAR **vars, int numVars)
+{
+
+ if (ServiceExists(MS_VARS_FORMATSTRING))
+ {
+ TCHAR *tmp = variables_parse_ex(templ, NULL, hContact, vars, numVars);
+ if (tmp != NULL)
+ {
+ out->append(tmp);
+ variables_free(tmp);
+ out->pack();
+ return;
+ }
+ }
+
+ out->append(templ);
+ ReplaceVars(out, hContact, vars, numVars);
+ out->pack();
+}
+
+
+#endif // __MIR_BUFFER_H__
diff --git a/plugins/Utils/mir_dblists.cpp b/plugins/Utils/mir_dblists.cpp new file mode 100644 index 0000000000..a1711eda4b --- /dev/null +++ b/plugins/Utils/mir_dblists.cpp @@ -0,0 +1,149 @@ +/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#include "mir_dblists.h"
+#include "mir_memory.h"
+
+#include <stdio.h>
+
+#include <newpluginapi.h>
+#include <m_system.h>
+
+
+struct LIST_INTERFACE list_interface = {0};
+
+
+void init_list_interface()
+{
+ list_interface.cbSize = sizeof(list_interface);
+ CallService(MS_SYSTEM_GET_LI, 0, (LPARAM)&list_interface);
+}
+
+
+void List_DestroyFreeContents( SortedList* p_list ) +{ + if ( p_list == NULL ) + return; + + if ( p_list->items != NULL ) + { + int i; + for ( i = 0 ; i < p_list->realCount ; i++ ) + { + if ( p_list->items[i] != NULL ) + { + mir_free( p_list->items[i] ); + } + } + } + + List_Destroy( p_list ); +} + +
+int List_Append( SortedList* p_list, void* p_value ) +{ + return List_Insert( p_list, p_value, p_list->realCount ); +} + +
+int List_InsertOrdered( SortedList* p_list, void* p_value )
+{
+ int index;
+
+ List_GetIndex( p_list, p_value, &index );
+ List_Insert( p_list, p_value, index );
+
+ return index;
+}
+
+
+int List_RemoveByValue( SortedList* p_list, void* p_value )
+{
+ int ret = 0;
+
+ if ( p_list->items != NULL )
+ {
+ int i;
+ for ( i = p_list->realCount - 1 ; i >= 0 ; i-- )
+ {
+ if ( p_list->items[ i ] == p_value )
+ ret += List_Remove( p_list, i );
+ }
+ }
+
+ return ret;
+} +
+
+int List_RemoveByValueFreeContents( SortedList* p_list, void* p_value )
+{
+ int ret = 0;
+
+ if ( p_list->items != NULL )
+ {
+ int i;
+ for ( i = p_list->realCount - 1 ; i >= 0 ; i-- )
+ {
+ if ( p_list->items[ i ] == p_value )
+ {
+ mir_free( p_list->items[ i ] );
+ ret += List_Remove( p_list, i );
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+void List_Push( SortedList* p_list, void* p_value )
+{
+ List_Insert( p_list, p_value, p_list->realCount );
+}
+
+
+void* List_Pop( SortedList* p_list )
+{
+ void *ret;
+
+ if ( p_list->realCount <= 0 )
+ return NULL;
+
+ ret = p_list->items[ p_list->realCount - 1 ];
+ List_Remove( p_list, p_list->realCount - 1 );
+
+ return ret;
+}
+
+
+void* List_Peek( SortedList* p_list )
+{
+ if ( p_list->realCount <= 0 )
+ return NULL;
+
+ return p_list->items[ p_list->realCount - 1 ];
+}
+
+
+BOOL List_HasItens( SortedList* p_list )
+{
+ return p_list->realCount > 0;
+}
\ No newline at end of file diff --git a/plugins/Utils/mir_dblists.h b/plugins/Utils/mir_dblists.h new file mode 100644 index 0000000000..4d4552b49d --- /dev/null +++ b/plugins/Utils/mir_dblists.h @@ -0,0 +1,62 @@ +/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __MIR_DBLISTS_H__
+# define __MIR_DBLISTS_H__
+
+#include <windows.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+
+
+
+extern struct LIST_INTERFACE list_interface;
+
+
+// Need to be called on ME_SYSTEM_MODULESLOADED
+void init_list_interface();
+
+
+#define List_Create(x,y) (list_interface.List_Create(x,y))
+#define List_Destroy(x) (list_interface.List_Destroy(x))
+#define List_Find(x,y) (list_interface.List_Find(x,y))
+#define List_GetIndex(x,y,z) (list_interface.List_GetIndex(x,y,z))
+#define List_Insert(x,y,z) (list_interface.List_Insert(x,y,z))
+#define List_Remove(x,y) (list_interface.List_Remove(x,y))
+#define List_IndexOf(x,y) (list_interface.List_IndexOf(x,y))
+
+
+BOOL List_HasItens( SortedList* p_list );
+
+void List_DestroyFreeContents( SortedList* );
+int List_RemoveByValue( SortedList*, void* );
+int List_RemoveByValueFreeContents( SortedList*, void* );
+
+int List_Append( SortedList*, void* );
+int List_InsertOrdered( SortedList*, void* );
+
+// Theese work on the end of the list
+void List_Push( SortedList* p_list, void* p_value );
+void* List_Pop( SortedList* p_list );
+void* List_Peek( SortedList* p_list );
+
+
+
+#endif // __MIR_DBLISTS_H__
diff --git a/plugins/Utils/mir_dbutils.h b/plugins/Utils/mir_dbutils.h new file mode 100644 index 0000000000..cb7400a5ff --- /dev/null +++ b/plugins/Utils/mir_dbutils.h @@ -0,0 +1,70 @@ +/*
+Copyright (C) 2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+#ifndef __DBUTILS_H__
+# define __DBUTILS_H__
+
+
+class DBTString
+{
+ DBVARIANT dbv;
+ bool exists;
+
+public:
+ DBTString(HANDLE hContact, char *module, char *setting)
+ {
+ ZeroMemory(&dbv, sizeof(dbv));
+ exists = (DBGetContactSettingTString(hContact, module, setting, &dbv) == 0);
+ }
+
+ ~DBTString()
+ {
+ if (exists)
+ DBFreeVariant(&dbv);
+ }
+
+ const TCHAR * get() const
+ {
+ if (!exists)
+ return NULL;
+ else
+ return dbv.ptszVal;
+ }
+
+ const bool operator==(const TCHAR *other)
+ {
+ return get() == other;
+ }
+
+ const bool operator!=(const TCHAR *other)
+ {
+ return get() != other;
+ }
+
+ operator const TCHAR *() const
+ {
+ return get();
+ }
+};
+
+
+
+
+
+
+#endif // __DBUTILS_H__
diff --git a/plugins/Utils/mir_icons.cpp b/plugins/Utils/mir_icons.cpp new file mode 100644 index 0000000000..1fb2c0ef82 --- /dev/null +++ b/plugins/Utils/mir_icons.cpp @@ -0,0 +1,86 @@ +/*
+Copyright (C) 2007-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#include "mir_icons.h"
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_icolib.h>
+
+extern HINSTANCE hInst;
+
+
+
+HICON IcoLib_LoadIcon(const char *iconName, BOOL copy)
+{
+ if (!ServiceExists(MS_SKIN2_GETICON))
+ return NULL;
+
+ if (iconName == NULL || iconName[0] == 0)
+ return NULL;
+
+ HICON hIcon = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) iconName);
+ if (copy && hIcon != NULL)
+ {
+ hIcon = CopyIcon(hIcon);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM) hIcon, 0);
+ }
+ return hIcon;
+}
+
+void IcoLib_ReleaseIcon(const char *iconName)
+{
+ if (ServiceExists(MS_SKIN2_RELEASEICON))
+ CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM) iconName);
+}
+
+
+void IcoLib_ReleaseIcon(HICON hIcon)
+{
+ if (ServiceExists(MS_SKIN2_RELEASEICON))
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM) hIcon, 0);
+}
+
+
+void IcoLib_Register(char *name, TCHAR *section, TCHAR *description, int id)
+{
+ HICON hIcon = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) name);
+ if (hIcon != NULL)
+ {
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM) hIcon, 0);
+ return;
+ }
+
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.flags = SIDF_TCHAR;
+ sid.pszName = name;
+ sid.ptszSection = section;
+ sid.ptszDescription = description;
+
+ int cx = GetSystemMetrics(SM_CXSMICON);
+ sid.hDefaultIcon = (HICON) LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON, cx, cx, LR_DEFAULTCOLOR | LR_SHARED);
+
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ if (sid.hDefaultIcon)
+ DestroyIcon(sid.hDefaultIcon);
+}
+
diff --git a/plugins/Utils/mir_icons.h b/plugins/Utils/mir_icons.h new file mode 100644 index 0000000000..178094c803 --- /dev/null +++ b/plugins/Utils/mir_icons.h @@ -0,0 +1,38 @@ +/*
+Copyright (C) 2005-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __MIR_ICONS_H__
+# define __MIR_ICONS_H__
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <windows.h>
+
+
+void IcoLib_Register(char *name, TCHAR *section, TCHAR *description, int id);
+
+HICON IcoLib_LoadIcon(const char *iconName, BOOL copy = FALSE);
+void IcoLib_ReleaseIcon(const char *iconName);
+void IcoLib_ReleaseIcon(HICON hIcon);
+
+
+
+
+#endif // __MIR_ICONS_H__
diff --git a/plugins/Utils/mir_log.cpp b/plugins/Utils/mir_log.cpp new file mode 100644 index 0000000000..5a5a18060f --- /dev/null +++ b/plugins/Utils/mir_log.cpp @@ -0,0 +1,220 @@ +/*
+Copyright (C) 2005-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#include "mir_log.h"
+
+#include <stdio.h>
+
+#include <newpluginapi.h>
+#include <m_netlib.h>
+#include <m_protocols.h>
+#include <m_clist.h>
+
+#define ENABLE_LOG
+
+
+int MLog::deep = 0;
+
+MLog::MLog(const char *aModule, const char *aFunction)
+ : module(aModule)
+{
+ memset(&total, 0, sizeof(total));
+
+ function = "";
+ for(int i = 0; i < deep; i++)
+ function += " ";
+ function += aFunction;
+
+ deep ++;
+
+ mlog(module.c_str(), function.c_str(), "BEGIN");
+
+ StartTimer();
+}
+
+MLog::~MLog()
+{
+ StopTimer();
+
+ mlog(module.c_str(), function.c_str(), "END in %2.1lf ms", GetTotalTimeMS());
+ deep --;
+}
+
+int MLog::log(const char *fmt, ...)
+{
+ StopTimer();
+
+ double elapsed = GetElapsedTimeMS();
+
+ va_list va;
+ va_start(va, fmt);
+
+ char text[1024];
+ mir_snprintf(text, sizeof(text) - 10, "%s [in %2.1lf ms | total %2.1lf ms]",
+ fmt, GetElapsedTimeMS(), GetTotalTimeMS());
+
+ int ret = mlog(module.c_str(), function.c_str(), text, va);
+
+ va_end(va);
+
+ StartTimer();
+
+ return ret;
+}
+
+void MLog::StartTimer()
+{
+ QueryPerformanceCounter(&start);
+}
+
+void MLog::StopTimer()
+{
+ QueryPerformanceCounter(&end);
+
+ total.QuadPart += end.QuadPart - start.QuadPart;
+}
+
+double MLog::GetElapsedTimeMS()
+{
+ LARGE_INTEGER frequency;
+ QueryPerformanceFrequency(&frequency);
+
+ return (end.QuadPart - start.QuadPart) * 1000. / frequency.QuadPart;
+}
+
+double MLog::GetTotalTimeMS()
+{
+ LARGE_INTEGER frequency;
+ QueryPerformanceFrequency(&frequency);
+
+ return total.QuadPart * 1000. / frequency.QuadPart;
+}
+
+
+int mlog(const char *module, const char *function, const char *fmt, va_list va)
+{
+#ifdef ENABLE_LOG
+
+ char text[1024];
+ size_t len;
+
+ mir_snprintf(text, sizeof(text) - 10, "[%08u - %08u] [%s] [%s] ",
+ GetCurrentThreadId(), GetTickCount(), module, function);
+ len = strlen(text);
+
+ mir_vsnprintf(&text[len], sizeof(text) - len, fmt, va);
+
+#ifdef LOG_TO_NETLIB
+
+ return CallService(MS_NETLIB_LOG, NULL, (LPARAM) text);
+
+#else
+ char file[256];
+ _snprintf(file, sizeof(file), "c:\\miranda_%s.log.txt", module);
+
+ FILE *fp = fopen(file,"at");
+
+ if (fp != NULL)
+ {
+ fprintf(fp, "%s\n", text);
+ fclose(fp);
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+
+#endif
+
+#else
+
+ return 0;
+
+#endif
+}
+
+
+int mlog(const char *module, const char *function, const char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+
+ int ret = mlog(module, function, fmt, va);
+
+ va_end(va);
+
+ return ret;
+}
+
+int mlogC(const char *module, const char *function, HANDLE hContact, const char *fmt, ...)
+{
+#ifdef ENABLE_LOG
+
+ va_list va;
+ char text[1024];
+ size_t len;
+
+ char *name = NULL;
+ char *proto = NULL;
+ if (hContact != NULL)
+ {
+ name = (char*) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0);
+ proto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ }
+
+ mir_snprintf(text, sizeof(text) - 10, "[%08u - %08u] [%s] [%s] [%08d - %s - %s] ",
+ GetCurrentThreadId(), GetTickCount(), module, function,
+ hContact, proto == NULL ? "" : proto, name == NULL ? "" : name);
+ len = strlen(text);
+
+ va_start(va, fmt);
+ mir_vsnprintf(&text[len], sizeof(text) - len, fmt, va);
+ va_end(va);
+
+#ifdef LOG_TO_NETLIB
+
+ return CallService(MS_NETLIB_LOG, NULL, (LPARAM) text);
+
+#else
+ char file[256];
+ _snprintf(file, sizeof(file), "c:\\miranda_%s.log.txt", module);
+
+ FILE *fp = fopen(file,"at");
+
+ if (fp != NULL)
+ {
+ fprintf(fp, "%s\n", text);
+ fclose(fp);
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+
+#endif
+
+#else
+
+ return 0;
+
+#endif
+}
diff --git a/plugins/Utils/mir_log.h b/plugins/Utils/mir_log.h new file mode 100644 index 0000000000..5785e191ff --- /dev/null +++ b/plugins/Utils/mir_log.h @@ -0,0 +1,63 @@ +/*
+Copyright (C) 2005-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __LOG_H__
+# define __LOG_H__
+
+#include <windows.h>
+#include <string>
+
+
+int mlog(const char *module, const char *function, const char *fmt, ...);
+int mlog(const char *module, const char *function, const char *fmt, va_list va);
+int mlogC(const char *module, const char *function, HANDLE hContact, const char *fmt, ...);
+
+
+#ifdef __cplusplus
+
+class MLog
+{
+private:
+ std::string module;
+ std::string function;
+ LARGE_INTEGER start;
+ LARGE_INTEGER end;
+ LARGE_INTEGER total;
+
+ static int deep;
+
+ void StartTimer();
+ void StopTimer();
+ double GetElapsedTimeMS();
+ double GetTotalTimeMS();
+
+public:
+ MLog(const char *aModule, const char *aFunction);
+ ~MLog();
+
+ int log(const char *fmt, ...);
+};
+
+
+#endif __cplusplus
+
+
+
+#endif // __LOG_H__
diff --git a/plugins/Utils/mir_memory.h b/plugins/Utils/mir_memory.h new file mode 100644 index 0000000000..b7ed17b6aa --- /dev/null +++ b/plugins/Utils/mir_memory.h @@ -0,0 +1,124 @@ +/*
+Copyright (C) 2005-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __MIR_MEMORY_H__
+# define __MIR_MEMORY_H__
+
+
+#include <windows.h>
+
+
+
+static BOOL mir_is_unicode()
+{
+ static int is_unicode = -1;
+ if (is_unicode == -1)
+ {
+ char ver[1024];
+ CallService(MS_SYSTEM_GETVERSIONTEXT, (WPARAM) sizeof(ver), (LPARAM) ver);
+ is_unicode = (strstr(ver, "Unicode") != NULL ? 1 : 0);
+ }
+ return is_unicode;
+}
+
+
+static void * mir_alloc0(size_t size)
+{
+ void * ptr = mir_alloc(size);
+
+ if (ptr != NULL)
+ memset(ptr, 0, size);
+
+ return ptr;
+}
+
+static int strcmpnull(char *str1, char *str2)
+{
+ if ( str1 == NULL && str2 == NULL )
+ return 0;
+ if ( str1 != NULL && str2 == NULL )
+ return 1;
+ if ( str1 == NULL && str2 != NULL )
+ return -1;
+
+ return strcmp(str1, str2);
+}
+
+static int strcmpnullW(WCHAR *str1, WCHAR *str2)
+{
+ if ( str1 == NULL && str2 == NULL )
+ return 0;
+ if ( str1 != NULL && str2 == NULL )
+ return 1;
+ if ( str1 == NULL && str2 != NULL )
+ return -1;
+
+ return lstrcmpW(str1, str2);
+}
+
+
+#ifdef UNICODE
+
+#define CHECK_VERSION(_NAME_) \
+ if (!mir_is_unicode()) \
+ { \
+ MessageBox(NULL, _T("Your Miranda is ansi. You have to install ansi ") _T(_NAME_), \
+ _T(_NAME_), MB_OK | MB_ICONERROR); \
+ return -1; \
+ }
+
+# define lstrcmpnull strcmpnullW
+
+#define INPLACE_CHAR_TO_TCHAR(_new_var_, _size_, _old_var_) \
+ TCHAR _new_var_[_size_]; \
+ MultiByteToWideChar(CP_ACP, 0, _old_var_, -1, _new_var_, _size_)
+
+
+#define INPLACE_TCHAR_TO_CHAR(_new_var_, _size_, _old_var_) \
+ char _new_var_[_size_]; \
+ WideCharToMultiByte(CP_ACP, 0, _old_var_, -1, _new_var_, _size_, NULL, NULL);
+
+#else
+
+#define CHECK_VERSION(_NAME_) \
+ if (mir_is_unicode()) \
+ { \
+ MessageBox(NULL, _T("Your Miranda is unicode. You have to install unicode ") _T(_NAME_), \
+ _T(_NAME_), MB_OK | MB_ICONERROR); \
+ return -1; \
+ }
+
+# define lstrcmpnull strcmpnull
+
+#define INPLACE_CHAR_TO_TCHAR(_new_var_, _size_, _old_var_) \
+ TCHAR *_new_var_ = _old_var_
+
+#define INPLACE_TCHAR_TO_CHAR(_new_var_, _size_, _old_var_) \
+ char *_new_var_ = _old_var_;
+
+#endif
+
+
+
+// Free memory and set to NULL
+//#define MIR_FREE(_x_) if (_x_ != NULL) { mir_free(_x_); _x_ = NULL; }
+
+
+
+#endif // __MIR_MEMORY_H__
diff --git a/plugins/Utils/mir_options.cpp b/plugins/Utils/mir_options.cpp new file mode 100644 index 0000000000..9b43a256c9 --- /dev/null +++ b/plugins/Utils/mir_options.cpp @@ -0,0 +1,650 @@ +/*
+Copyright (C) 2005-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#include <windows.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <tchar.h>
+
+#define MIRANDA_VER 0x0A00
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_utils.h>
+#include <m_langpack.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_system.h>
+
+#include "mir_options.h"
+#include "mir_memory.h"
+
+
+#define MAX_REGS(_A_) ( sizeof(_A_) / sizeof(_A_[0]) )
+
+
+static TCHAR* MyDBGetContactSettingTString(HANDLE hContact, char* module, char* setting, TCHAR* out, size_t len, TCHAR *def)
+{
+ DBVARIANT dbv = {0};
+
+ out[0] = _T('\0');
+
+ if (!DBGetContactSettingTString(hContact, module, setting, &dbv))
+ {
+#ifdef UNICODE
+ if (dbv.type == DBVT_ASCIIZ)
+ {
+ MultiByteToWideChar(CP_ACP, 0, dbv.pszVal, -1, out, (int)len);
+ }
+ else if (dbv.type == DBVT_UTF8)
+ {
+ MultiByteToWideChar(CP_UTF8, 0, dbv.pszVal, -1, out, (int)len);
+ }
+ else if (dbv.type == DBVT_WCHAR)
+ {
+ lstrcpyn(out, dbv.pwszVal, (int)len);
+ }
+#else
+ if (dbv.type == DBVT_ASCIIZ)
+ {
+ lstrcpyn(out, dbv.pszVal, len);
+ }
+#endif
+ else
+ {
+ if (def != NULL)
+ lstrcpyn(out, def, (int)len);
+ }
+
+ DBFreeVariant(&dbv);
+ }
+ else
+ {
+ if (def != NULL)
+ lstrcpyn(out, def, (int)len);
+ }
+
+ return out;
+}
+
+
+static TCHAR dbPath[MAX_PATH] = {0}; // database profile path (read at startup only)
+
+
+static int PathIsAbsolute(const TCHAR *path)
+{
+ if (!path || !(lstrlen(path) > 2))
+ return 0;
+ if ((path[1]==_T(':') && path[2]==_T('\\')) || (path[0]==_T('\\')&&path[1]==_T('\\')))
+ return 1;
+ return 0;
+}
+
+static void PathToRelative(TCHAR *pOut, size_t outSize, const TCHAR *pSrc)
+{
+ if (!PathIsAbsolute(pSrc))
+ {
+ lstrcpyn(pOut, pSrc, (int)outSize);
+ }
+ else
+ {
+ if (dbPath[0] == _T('\0'))
+ {
+ char tmp[1024];
+ CallService(MS_DB_GETPROFILEPATH, MAX_REGS(tmp), (LPARAM) tmp);
+ mir_sntprintf(dbPath, MAX_REGS(dbPath), _T(TCHAR_STR_PARAM) _T("\\"), tmp);
+ }
+
+ size_t len = lstrlen(dbPath);
+ if (_tcsnicmp(pSrc, dbPath, len))
+ {
+ mir_sntprintf(pOut, outSize, _T("%s"), pSrc + len);
+ }
+ else
+ {
+ lstrcpyn(pOut, pSrc, (int)outSize);
+ }
+ }
+}
+
+static void PathToAbsolute(TCHAR *pOut, size_t outSize, const TCHAR *pSrc)
+{
+ if (PathIsAbsolute(pSrc) || !isalnum(pSrc[0]))
+ {
+ lstrcpyn(pOut, pSrc, (int)outSize);
+ }
+ else
+ {
+ if (dbPath[0] == _T('\0'))
+ {
+ char tmp[1024];
+ CallService(MS_DB_GETPROFILEPATH, MAX_REGS(tmp), (LPARAM) tmp);
+ mir_sntprintf(dbPath, MAX_REGS(dbPath), _T(TCHAR_STR_PARAM) _T("\\"), tmp);
+ }
+
+ mir_sntprintf(pOut, outSize, _T("%s%s"), dbPath, pSrc);
+ }
+}
+
+
+static void LoadOpt(OptPageControl *ctrl, char *module)
+{
+ if (ctrl->var == NULL)
+ return;
+
+ switch(ctrl->type)
+ {
+ case CONTROL_CHECKBOX:
+ {
+ *((BYTE *) ctrl->var) = DBGetContactSettingByte(NULL, module, ctrl->setting, ctrl->dwDefValue);
+ break;
+ }
+ case CONTROL_SPIN:
+ {
+ *((WORD *) ctrl->var) = DBGetContactSettingWord(NULL, module, ctrl->setting, ctrl->dwDefValue);
+ break;
+ }
+ case CONTROL_COLOR:
+ {
+ *((COLORREF *) ctrl->var) = (COLORREF) DBGetContactSettingDword(NULL, module, ctrl->setting, ctrl->dwDefValue);
+ break;
+ }
+ case CONTROL_RADIO:
+ {
+ *((WORD *) ctrl->var) = DBGetContactSettingWord(NULL, module, ctrl->setting, ctrl->dwDefValue);
+ break;
+ }
+ case CONTROL_COMBO:
+ {
+ *((WORD *) ctrl->var) = DBGetContactSettingWord(NULL, module, ctrl->setting, ctrl->dwDefValue);
+ break;
+ }
+ case CONTROL_PROTOCOL_LIST:
+ {
+ break;
+ }
+ case CONTROL_TEXT:
+ {
+ MyDBGetContactSettingTString(NULL, module, ctrl->setting, ((TCHAR *) ctrl->var), min(ctrl->max <= 0 ? 1024 : ctrl->max, 1024), ctrl->tszDefValue == NULL ? NULL : TranslateTS(ctrl->tszDefValue));
+ break;
+ }
+ case CONTROL_PASSWORD:
+ {
+ char tmp[1024];
+ tmp[0]=0;
+
+ DBVARIANT dbv = {0};
+ if (!DBGetContactSettingString(NULL, module, ctrl->setting, &dbv))
+ {
+ lstrcpynA(tmp, dbv.pszVal, MAX_REGS(tmp));
+ DBFreeVariant(&dbv);
+ }
+
+ if (tmp[0] != 0)
+ CallService(MS_DB_CRYPT_DECODESTRING, MAX_REGS(tmp), (LPARAM) tmp);
+ else if (ctrl->szDefValue != NULL)
+ lstrcpynA(tmp, ctrl->szDefValue, MAX_REGS(tmp));
+
+ char *var = (char *) ctrl->var;
+ int size = min(ctrl->max <= 0 ? 1024 : ctrl->max, 1024);
+ lstrcpynA(var, tmp, size);
+ break;
+ }
+ case CONTROL_INT:
+ {
+ *((int *) ctrl->var) = (int) DBGetContactSettingDword(NULL, module, ctrl->setting, ctrl->dwDefValue);
+ break;
+ }
+ case CONTROL_FILE:
+ {
+ TCHAR tmp[1024];
+ MyDBGetContactSettingTString(NULL, module, ctrl->setting, tmp, 1024, ctrl->tszDefValue == NULL ? NULL : ctrl->tszDefValue);
+ PathToAbsolute(((TCHAR *) ctrl->var), min(ctrl->max <= 0 ? 1024 : ctrl->max, 1024), tmp);
+ break;
+ }
+ case CONTROL_COMBO_TEXT:
+ case CONTROL_COMBO_ITEMDATA:
+ {
+ MyDBGetContactSettingTString(NULL, module, ctrl->setting, ((TCHAR *) ctrl->var), min(ctrl->max <= 0 ? 1024 : ctrl->max, 1024), ctrl->tszDefValue == NULL ? NULL : TranslateTS(ctrl->tszDefValue));
+ break;
+ }
+ }
+}
+
+void LoadOpts(OptPageControl *controls, int controlsSize, char *module)
+{
+ for (int i = 0 ; i < controlsSize ; i++)
+ {
+ LoadOpt(&controls[i], module);
+ }
+}
+
+
+
+INT_PTR CALLBACK SaveOptsDlgProc(OptPageControl *controls, int controlsSize, char *module, HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ for (int i = 0 ; i < controlsSize ; i++)
+ {
+ OptPageControl *ctrl = &controls[i];
+
+ if (GetDlgItem(hwndDlg, ctrl->nID) == NULL)
+ continue;
+
+ switch(ctrl->type)
+ {
+ case CONTROL_CHECKBOX:
+ {
+ CheckDlgButton(hwndDlg, ctrl->nID, DBGetContactSettingByte(NULL, module, ctrl->setting, ctrl->dwDefValue) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ break;
+ }
+ case CONTROL_SPIN:
+ {
+ SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, ctrl->nID),0);
+ SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_SETRANGE, 0, MAKELONG(ctrl->max, ctrl->min));
+ SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_SETPOS,0, MAKELONG(DBGetContactSettingWord(NULL, module, ctrl->setting, ctrl->dwDefValue), 0));
+ break;
+ }
+ case CONTROL_COLOR:
+ {
+ SendDlgItemMessage(hwndDlg, ctrl->nID, CPM_SETCOLOUR, 0, (COLORREF) DBGetContactSettingDword(NULL, module, ctrl->setting, ctrl->dwDefValue));
+ break;
+ }
+ case CONTROL_RADIO:
+ {
+ CheckDlgButton(hwndDlg, ctrl->nID, DBGetContactSettingWord(NULL, module, ctrl->setting, ctrl->dwDefValue) == ctrl->value ? BST_CHECKED : BST_UNCHECKED);
+ break;
+ }
+ case CONTROL_COMBO:
+ {
+ SendDlgItemMessage(hwndDlg, ctrl->nID, CB_SETCURSEL, DBGetContactSettingWord(NULL, module, ctrl->setting, ctrl->dwDefValue), 0);
+ break;
+ }
+ case CONTROL_PROTOCOL_LIST:
+ {
+ // Fill list view
+ HWND hwndProtocols = GetDlgItem(hwndDlg, ctrl->nID);
+ LVCOLUMN lvc;
+ LVITEM lvi;
+
+ ListView_SetExtendedListViewStyle(hwndProtocols, LVS_EX_CHECKBOXES);
+
+ ZeroMemory(&lvc, sizeof(lvc));
+ lvc.mask = LVCF_FMT;
+ lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
+ ListView_InsertColumn(hwndProtocols, 0, &lvc);
+
+ ZeroMemory(&lvi, sizeof(lvi));
+ lvi.mask = LVIF_TEXT | LVIF_PARAM;
+ lvi.iSubItem = 0;
+ lvi.iItem = 1000;
+
+ PROTOACCOUNT **protos;
+ int count;
+
+ BOOL hasAccounts = ServiceExists(MS_PROTO_ENUMACCOUNTS);
+
+ if (hasAccounts)
+ CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)&count, (LPARAM)&protos);
+ else
+ CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&count, (LPARAM)&protos);
+
+ for (int i = 0; i < count; i++)
+ {
+ if (protos[i]->type != PROTOTYPE_PROTOCOL)
+ continue;
+
+ if (protos[i]->szModuleName == NULL || protos[i]->szModuleName[0] == '\0')
+ continue;
+
+ if (ctrl->allowProtocol != NULL && !ctrl->allowProtocol(protos[i]->szModuleName))
+ continue;
+
+ TCHAR *name;
+ if (hasAccounts)
+ {
+ name = mir_tstrdup(protos[i]->tszAccountName);
+ }
+ else
+ {
+ char szName[128];
+ CallProtoService(protos[i]->szModuleName, PS_GETNAME, sizeof(szName), (LPARAM)szName);
+ name = mir_a2t(szName);
+ }
+
+ char *setting = (char *) mir_alloc(128 * sizeof(char));
+ mir_snprintf(setting, 128, ctrl->setting, protos[i]->szModuleName);
+
+ BOOL show = (BOOL)DBGetContactSettingByte(NULL, module, setting, ctrl->dwDefValue);
+
+ lvi.lParam = (LPARAM)setting;
+ lvi.pszText = TranslateTS(name);
+ lvi.iItem = ListView_InsertItem(hwndProtocols, &lvi);
+ ListView_SetItemState(hwndProtocols, lvi.iItem, INDEXTOSTATEIMAGEMASK(show?2:1), LVIS_STATEIMAGEMASK);
+
+ mir_free(name);
+ }
+
+ ListView_SetColumnWidth(hwndProtocols, 0, LVSCW_AUTOSIZE);
+ ListView_Arrange(hwndProtocols, LVA_ALIGNLEFT | LVA_ALIGNTOP);
+ break;
+ }
+ case CONTROL_TEXT:
+ {
+ TCHAR tmp[1024];
+ SetDlgItemText(hwndDlg, ctrl->nID, MyDBGetContactSettingTString(NULL, module, ctrl->setting, tmp, 1024, ctrl->tszDefValue == NULL ? NULL : TranslateTS(ctrl->tszDefValue)));
+ SendDlgItemMessage(hwndDlg, ctrl->nID, EM_LIMITTEXT, min(ctrl->max <= 0 ? 1024 : ctrl->max, 1024), 0);
+ break;
+ }
+ case CONTROL_PASSWORD:
+ {
+ char tmp[1024];
+ tmp[0]=0;
+
+ DBVARIANT dbv = {0};
+ if (!DBGetContactSettingString(NULL, module, ctrl->setting, &dbv))
+ {
+ lstrcpynA(tmp, dbv.pszVal, MAX_REGS(tmp));
+ DBFreeVariant(&dbv);
+ }
+
+ if (tmp[0] != 0)
+ CallService(MS_DB_CRYPT_DECODESTRING, MAX_REGS(tmp), (LPARAM) tmp);
+ else if (ctrl->szDefValue != NULL)
+ lstrcpynA(tmp, ctrl->szDefValue, MAX_REGS(tmp));
+
+ SetDlgItemTextA(hwndDlg, ctrl->nID, tmp);
+ SendDlgItemMessage(hwndDlg, ctrl->nID, EM_LIMITTEXT, min(ctrl->max <= 0 ? 1024 : ctrl->max, 1024), 0);
+ break;
+ }
+ case CONTROL_INT:
+ {
+ DWORD var = DBGetContactSettingDword(NULL, module, ctrl->setting, ctrl->dwDefValue);
+ SetDlgItemInt(hwndDlg, ctrl->nID, var, ctrl->min <= 0);
+ SendDlgItemMessage(hwndDlg, ctrl->nID, EM_LIMITTEXT, 9, 0);
+ break;
+ }
+ case CONTROL_FILE:
+ {
+ TCHAR tmp[1024];
+ MyDBGetContactSettingTString(NULL, module, ctrl->setting, tmp, 1024, ctrl->tszDefValue == NULL ? NULL : ctrl->tszDefValue);
+ TCHAR abs[1024];
+ PathToAbsolute(abs, 1024, tmp);
+
+ SetDlgItemText(hwndDlg, ctrl->nID, abs);
+ SendDlgItemMessage(hwndDlg, ctrl->nID, EM_LIMITTEXT, min(ctrl->max <= 0 ? 1024 : ctrl->max, 1024), 0);
+ break;
+ }
+ case CONTROL_COMBO_TEXT:
+ {
+ TCHAR tmp[1024];
+ MyDBGetContactSettingTString(NULL, module, ctrl->setting, tmp, 1024, ctrl->tszDefValue == NULL ? NULL : TranslateTS(ctrl->tszDefValue));
+ SendDlgItemMessage(hwndDlg, ctrl->nID, CB_SELECTSTRING, 0, (WPARAM) tmp);
+ break;
+ }
+ case CONTROL_COMBO_ITEMDATA:
+ {
+ TCHAR tmp[1024];
+ MyDBGetContactSettingTString(NULL, module, ctrl->setting, tmp, 1024, ctrl->tszDefValue == NULL ? NULL : TranslateTS(ctrl->tszDefValue));
+ int count = SendDlgItemMessage(hwndDlg, ctrl->nID, CB_GETCOUNT, 0, 0);
+ int i;
+ for(i = 0; i < count; i++)
+ {
+ TCHAR *id = (TCHAR *) SendDlgItemMessage(hwndDlg, ctrl->nID, CB_GETITEMDATA, (WPARAM) i, 0);
+ if (lstrcmp(id, tmp) == 0)
+ break;
+ }
+ if (i < count)
+ SendDlgItemMessage(hwndDlg, ctrl->nID, CB_SETCURSEL, i, 0);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case WM_COMMAND:
+ {
+ for (int i = 0 ; i < controlsSize ; i++)
+ {
+ OptPageControl *ctrl = &controls[i];
+
+ if (LOWORD(wParam) == ctrl->nID)
+ {
+ switch(ctrl->type)
+ {
+ case CONTROL_TEXT:
+ case CONTROL_SPIN:
+ case CONTROL_INT:
+ case CONTROL_PASSWORD:
+ {
+ // Don't make apply enabled during buddy set
+ if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
+ return 0;
+
+ break;
+ }
+ case CONTROL_COMBO_ITEMDATA:
+ case CONTROL_COMBO_TEXT:
+ case CONTROL_COMBO:
+ {
+ if (HIWORD(wParam) != CBN_SELCHANGE || (HWND)lParam != GetFocus())
+ return 0;
+
+ break;
+ }
+ }
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ LPNMHDR lpnmhdr = (LPNMHDR)lParam;
+
+ if (lpnmhdr->idFrom == 0 && lpnmhdr->code == PSN_APPLY)
+ {
+ for (int i = 0 ; i < controlsSize ; i++)
+ {
+ OptPageControl *ctrl = &controls[i];
+
+ if (GetDlgItem(hwndDlg, ctrl->nID) == NULL)
+ continue;
+
+ switch(ctrl->type)
+ {
+ case CONTROL_CHECKBOX:
+ {
+ DBWriteContactSettingByte(NULL, module, ctrl->setting, (BYTE) IsDlgButtonChecked(hwndDlg, ctrl->nID));
+ break;
+ }
+ case CONTROL_SPIN:
+ {
+ DBWriteContactSettingWord(NULL, module, ctrl->setting, (WORD) SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_GETPOS, 0, 0));
+ break;
+ }
+ case CONTROL_COLOR:
+ {
+ DBWriteContactSettingDword(NULL, module, ctrl->setting, (DWORD) SendDlgItemMessage(hwndDlg, ctrl->nID, CPM_GETCOLOUR, 0, 0));
+ break;
+ }
+ case CONTROL_RADIO:
+ {
+ if (IsDlgButtonChecked(hwndDlg, ctrl->nID))
+ DBWriteContactSettingWord(NULL, module, ctrl->setting, (BYTE) ctrl->value);
+ break;
+ }
+ case CONTROL_COMBO:
+ {
+ DBWriteContactSettingWord(NULL, module, ctrl->setting, (WORD) SendDlgItemMessage(hwndDlg, ctrl->nID, CB_GETCURSEL, 0, 0));
+ break;
+ }
+ case CONTROL_PROTOCOL_LIST:
+ {
+ LVITEM lvi = {0};
+ HWND hwndProtocols = GetDlgItem(hwndDlg, ctrl->nID);
+ int i;
+
+ lvi.mask = (UINT) LVIF_PARAM;
+
+ for (i = 0; i < ListView_GetItemCount(hwndProtocols); i++)
+ {
+ lvi.iItem = i;
+ ListView_GetItem(hwndProtocols, &lvi);
+
+ char *setting = (char *)lvi.lParam;
+ DBWriteContactSettingByte(NULL, module, setting, (BYTE)ListView_GetCheckState(hwndProtocols, i));
+ }
+ break;
+ }
+ case CONTROL_TEXT:
+ {
+ TCHAR tmp[1024];
+ GetDlgItemText(hwndDlg, ctrl->nID, tmp, MAX_REGS(tmp));
+ DBWriteContactSettingTString(NULL, module, ctrl->setting, tmp);
+ break;
+ }
+ case CONTROL_PASSWORD:
+ {
+ char tmp[1024];
+ GetDlgItemTextA(hwndDlg, ctrl->nID, tmp, MAX_REGS(tmp));
+
+ if (ctrl->var != NULL)
+ {
+ char *var = (char *) ctrl->var;
+ int size = min(ctrl->max <= 0 ? 1024 : ctrl->max, 1024);
+ lstrcpynA(var, tmp, size);
+ }
+
+ if (ctrl->checkboxID != 0 && !IsDlgButtonChecked(hwndDlg, ctrl->checkboxID))
+ {
+ DBDeleteContactSetting(NULL, module, ctrl->setting);
+ continue;
+ }
+
+ CallService(MS_DB_CRYPT_ENCODESTRING, MAX_REGS(tmp), (LPARAM) tmp);
+ DBWriteContactSettingString(NULL, module, ctrl->setting, tmp);
+
+ // Don't load from DB
+ continue;
+ }
+ case CONTROL_INT:
+ {
+ BOOL trans;
+ int val = GetDlgItemInt(hwndDlg, ctrl->nID, &trans, ctrl->min <= 0);
+ if (!trans)
+ val = ctrl->dwDefValue;
+ if (ctrl->max != 0)
+ val = min(val, ctrl->max);
+ if (ctrl->min != 0)
+ val = max(val, ctrl->min);
+ DBWriteContactSettingDword(NULL, module, ctrl->setting, val);
+ break;
+ }
+ case CONTROL_FILE:
+ {
+ TCHAR tmp[1024];
+ GetDlgItemText(hwndDlg, ctrl->nID, tmp, 1024);
+ TCHAR rel[1024];
+ PathToRelative(rel, 1024, tmp);
+ DBWriteContactSettingTString(NULL, module, ctrl->setting, rel);
+ break;
+ }
+ case CONTROL_COMBO_TEXT:
+ {
+ TCHAR tmp[1024];
+ GetDlgItemText(hwndDlg, ctrl->nID, tmp, 1024);
+ DBWriteContactSettingTString(NULL, module, ctrl->setting, tmp);
+ break;
+ }
+ case CONTROL_COMBO_ITEMDATA:
+ {
+ int sel = SendDlgItemMessage(hwndDlg, ctrl->nID, CB_GETCURSEL, 0, 0);
+ DBWriteContactSettingTString(NULL, module, ctrl->setting, (TCHAR *) SendDlgItemMessage(hwndDlg, ctrl->nID, CB_GETITEMDATA, (WPARAM) sel, 0));
+ break;
+ }
+ }
+
+ LoadOpt(ctrl, module);
+ }
+
+ return TRUE;
+ }
+ else if (lpnmhdr->idFrom != 0 && lpnmhdr->code == LVN_ITEMCHANGED)
+ {
+ // Changed for protocols
+ for (int i = 0 ; i < controlsSize ; i++)
+ {
+ OptPageControl *ctrl = &controls[i];
+
+ if (ctrl->type == CONTROL_PROTOCOL_LIST && ctrl->nID == lpnmhdr->idFrom)
+ {
+ NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam;
+
+ if(IsWindowVisible(GetDlgItem(hwndDlg, ctrl->nID)) && ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK))
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case WM_DESTROY:
+ {
+ for (int i = 0 ; i < controlsSize ; i++)
+ {
+ OptPageControl *ctrl = &controls[i];
+
+ if (GetDlgItem(hwndDlg, ctrl->nID) == NULL)
+ continue;
+
+ switch(ctrl->type)
+ {
+ case CONTROL_PROTOCOL_LIST:
+ {
+ LVITEM lvi = {0};
+ HWND hwndProtocols = GetDlgItem(hwndDlg, ctrl->nID);
+ int i;
+
+ lvi.mask = (UINT) LVIF_PARAM;
+
+ for (i = 0; i < ListView_GetItemCount(hwndProtocols); i++)
+ {
+ lvi.iItem = i;
+ ListView_GetItem(hwndProtocols, &lvi);
+ mir_free((char *) lvi.lParam);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/plugins/Utils/mir_options.h b/plugins/Utils/mir_options.h new file mode 100644 index 0000000000..8bfcd4dd0d --- /dev/null +++ b/plugins/Utils/mir_options.h @@ -0,0 +1,72 @@ +/*
+Copyright (C) 2005-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __MIR_OPTIONS_H__
+# define __MIR_OPTIONS_H__
+
+#include <windows.h>
+
+
+#define CONTROL_CHECKBOX 0 // Stored as BYTE
+#define CONTROL_SPIN 1 // Stored as WORD
+#define CONTROL_COLOR 2 // Stored as DWORD
+#define CONTROL_RADIO 3 // Stored as WORD
+#define CONTROL_COMBO 4 // Stored as WORD
+#define CONTROL_PROTOCOL_LIST 5 // Stored as BYTEs
+#define CONTROL_TEXT 6 // Stored as TCHARs, max len 1024
+#define CONTROL_COMBO_TEXT 7 // Stored as TCHARs, max len 1024
+#define CONTROL_COMBO_ITEMDATA 8 // Stored as TCHARs, max len 1024
+#define CONTROL_FILE 9 // Stored as TCHARs, max len 1024
+#define CONTROL_INT 10 // Stored as DWORD
+#define CONTROL_PASSWORD 11 // Stored as chars, max len 1024
+
+
+typedef BOOL (* FPAllowProtocol) (const char *proto);
+
+typedef struct {
+ void *var;
+ int type;
+ unsigned int nID;
+ char *setting;
+ union {
+ ULONG_PTR dwDefValue;
+ TCHAR *tszDefValue;
+ char *szDefValue;
+ };
+ union {
+ int nIDSpin;
+ int value;
+ FPAllowProtocol allowProtocol;
+ unsigned int checkboxID;
+ };
+ WORD min;
+ WORD max;
+} OptPageControl;
+
+INT_PTR CALLBACK SaveOptsDlgProc(OptPageControl *controls, int controlsSize, char *module, HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+void LoadOpts(OptPageControl *controls, int controlsSize, char *module);
+
+
+
+
+
+
+#endif // __MIR_OPTIONS_H__
diff --git a/plugins/Utils/mir_options_notify.cpp b/plugins/Utils/mir_options_notify.cpp new file mode 100644 index 0000000000..ddc0a548c1 --- /dev/null +++ b/plugins/Utils/mir_options_notify.cpp @@ -0,0 +1,199 @@ +/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#include "mir_options_notify.h"
+
+#include <stdio.h>
+#include <commctrl.h>
+#include <tchar.h>
+
+extern "C"
+{
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_utils.h>
+#include <m_langpack.h>
+#include <m_notify.h>
+#include "templates.h"
+}
+
+
+#define MAX_REGS(_A_) ( sizeof(_A_) / sizeof(_A_[0]) )
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Dialog to save options
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+BOOL CALLBACK SaveOptsDlgProc(OptPageControl *controls, int controlsSize, HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_USER+100:
+ {
+ HANDLE hNotify = (HANDLE)lParam;
+ SetWindowLong(hwndDlg, GWL_USERDATA, lParam);
+
+ TranslateDialogDefault(hwndDlg);
+
+ for (int i = 0 ; i < controlsSize ; i++)
+ {
+ OptPageControl *ctrl = &controls[i];
+
+ switch(ctrl->type)
+ {
+ case CONTROL_CHECKBOX:
+ {
+ CheckDlgButton(hwndDlg, ctrl->nID, MNotifyGetByte(hNotify, ctrl->setting, (BYTE)ctrl->dwDefValue) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ break;
+ }
+ case CONTROL_SPIN:
+ {
+ SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, ctrl->nID),0);
+ SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_SETRANGE, 0, MAKELONG(ctrl->max, ctrl->min));
+ SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_SETPOS,0, MAKELONG(MNotifyGetWord(hNotify, ctrl->setting, (WORD)ctrl->dwDefValue), 0));
+
+ break;
+ }
+ case CONTROL_COLOR:
+ {
+ SendDlgItemMessage(hwndDlg, ctrl->nID, CPM_SETCOLOUR, 0, (COLORREF) MNotifyGetDWord(hNotify, ctrl->setting, (DWORD)ctrl->dwDefValue));
+
+ break;
+ }
+ case CONTROL_RADIO:
+ {
+ CheckDlgButton(hwndDlg, ctrl->nID, MNotifyGetWord(hNotify, ctrl->setting, (WORD)ctrl->dwDefValue) == ctrl->value ? BST_CHECKED : BST_UNCHECKED);
+ break;
+ }
+ case CONTROL_TEXT:
+ {
+ SetDlgItemText(hwndDlg, ctrl->nID, MNotifyGetTString(hNotify, ctrl->setting, ctrl->szDefVale));
+
+ if (ctrl->max > 0)
+ SendDlgItemMessage(hwndDlg, ctrl->nID, EM_LIMITTEXT, min(ctrl->max, 1024), 0);
+ else
+ SendDlgItemMessage(hwndDlg, ctrl->nID, EM_LIMITTEXT, 1024, 0);
+
+ break;
+ }
+ case CONTROL_TEMPLATE:
+ {
+ SetDlgItemText(hwndDlg, ctrl->nID, MNotifyGetTTemplate(hNotify, ctrl->setting, ctrl->szDefVale));
+
+ if (ctrl->max > 0)
+ SendDlgItemMessage(hwndDlg, ctrl->nID, EM_LIMITTEXT, min(ctrl->max, 1024), 0);
+ else
+ SendDlgItemMessage(hwndDlg, ctrl->nID, EM_LIMITTEXT, 1024, 0);
+
+ break;
+ }
+ }
+ }
+
+ return TRUE;
+ break;
+ }
+ case WM_COMMAND:
+ {
+ // Don't make apply enabled during buddy set crap
+ if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
+ {
+ for (int i = 0 ; i < controlsSize ; i++)
+ {
+ if (controls[i].type == CONTROL_SPIN && LOWORD(wParam) == controls[i].nID)
+ {
+ return 0;
+ }
+ }
+ }
+
+ SendMessage(GetParent(GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ HANDLE hNotify = (HANDLE)GetWindowLong(hwndDlg, GWL_USERDATA);
+ TCHAR tmp[1024];
+
+ for (int i = 0 ; i < controlsSize ; i++)
+ {
+ OptPageControl *ctrl = &controls[i];
+
+ switch(ctrl->type)
+ {
+ case CONTROL_CHECKBOX:
+ {
+ MNotifySetByte(hNotify, ctrl->setting, (BYTE)IsDlgButtonChecked(hwndDlg, ctrl->nID));
+ break;
+ }
+ case CONTROL_SPIN:
+ {
+ MNotifySetWord(hNotify, ctrl->setting, (WORD)SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_GETPOS, 0, 0));
+ break;
+ }
+ case CONTROL_COLOR:
+ {
+ MNotifySetDWord(hNotify, ctrl->setting, (DWORD)SendDlgItemMessage(hwndDlg, ctrl->nID, CPM_GETCOLOUR, 0, 0));
+ break;
+ }
+ case CONTROL_RADIO:
+ {
+ if (IsDlgButtonChecked(hwndDlg, ctrl->nID))
+ MNotifySetWord(hNotify, ctrl->setting, (BYTE)ctrl->value);
+ break;
+ }
+ case CONTROL_TEXT:
+ {
+ GetDlgItemText(hwndDlg, ctrl->nID, tmp, MAX_REGS(tmp));
+ MNotifySetTString(hNotify, ctrl->setting, tmp);
+ break;
+ }
+ case CONTROL_TEMPLATE:
+ {
+ GetDlgItemText(hwndDlg, ctrl->nID, tmp, MAX_REGS(tmp));
+ MNotifySetTTemplate(hNotify, ctrl->setting, tmp);
+ break;
+ }
+ }
+ }
+
+ return TRUE;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/plugins/Utils/mir_options_notify.h b/plugins/Utils/mir_options_notify.h new file mode 100644 index 0000000000..1f5494863a --- /dev/null +++ b/plugins/Utils/mir_options_notify.h @@ -0,0 +1,69 @@ +/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __MIR_OPTIONS_NOTIFY_H__
+# define __MIR_OPTIONS_NOTIFY_H__
+
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Dialog to save options
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define CONTROL_CHECKBOX 0 // Stored as BYTE
+#define CONTROL_SPIN 1 // Stored as WORD
+#define CONTROL_COLOR 2 // Stored as DWORD
+#define CONTROL_RADIO 3 // Stored as WORD
+#define CONTROL_TEXT 4 // Stored as char *
+#define CONTROL_TEMPLATE 5 // Stored as Template
+
+struct OptPageControl {
+ int type;
+ int nID;
+ char *setting;
+ union {
+ DWORD dwDefValue;
+ const TCHAR *szDefVale;
+ };
+ union {
+ int nIDSpin;
+ int value;
+ };
+ WORD min;
+ WORD max;
+};
+
+BOOL CALLBACK SaveOptsDlgProc(OptPageControl *controls, int controlsSize, HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __MIR_OPTIONS_NOTIFY_H__
diff --git a/plugins/Utils/mir_profiler.cpp b/plugins/Utils/mir_profiler.cpp new file mode 100644 index 0000000000..b788fd2dd2 --- /dev/null +++ b/plugins/Utils/mir_profiler.cpp @@ -0,0 +1,178 @@ +/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+// Disable "...truncated to '255' characters in the debug information" warnings
+#pragma warning(disable: 4786)
+
+
+#include "mir_profiler.h"
+#include "mir_log.h"
+
+#include <stdio.h>
+
+
+MProfiler::Block MProfiler::root;
+MProfiler::Block * MProfiler::current = &MProfiler::root;
+
+
+MProfiler::Block::Block()
+{
+ parent = NULL;
+ memset(&total, 0, sizeof(total));
+ started = false;
+}
+
+
+MProfiler::Block::~Block()
+{
+ Reset();
+}
+
+
+void MProfiler::Block::Reset()
+{
+ for(std::map<std::string, MProfiler::Block *>::iterator it = children.begin();
+ it != children.end(); ++it)
+ delete it->second;
+ children.clear();
+
+ memset(&total, 0, sizeof(total));
+ started = false;
+}
+
+
+void MProfiler::Block::Start()
+{
+ if (started)
+ return;
+
+ QueryPerformanceCounter(&start);
+ last_step = start;
+ started = true;
+}
+
+
+void MProfiler::Block::Step(const char *name)
+{
+ if (!started)
+ return;
+
+ LARGE_INTEGER end;
+ QueryPerformanceCounter(&end);
+
+ GetChild(name)->total.QuadPart += end.QuadPart - last_step.QuadPart;
+
+ last_step = end;
+}
+
+
+void MProfiler::Block::Stop()
+{
+ if (!started)
+ return;
+
+ LARGE_INTEGER end;
+ QueryPerformanceCounter(&end);
+
+ total.QuadPart += end.QuadPart - start.QuadPart;
+
+ started = false;
+}
+
+
+double MProfiler::Block::GetTimeMS() const
+{
+ LARGE_INTEGER frequency;
+ QueryPerformanceFrequency(&frequency);
+
+ return total.QuadPart * 1000. / frequency.QuadPart;
+}
+
+
+MProfiler::Block * MProfiler::Block::GetChild(const char *name)
+{
+ MProfiler::Block *ret = children[name];
+ if (ret == NULL)
+ {
+ ret = new MProfiler::Block();
+ ret->name = name;
+ ret->parent = this;
+ children[name] = ret;
+ }
+ return ret;
+}
+
+
+void MProfiler::Reset()
+{
+ root.Reset();
+}
+
+void MProfiler::Start(const char *name)
+{
+ current = current->GetChild(name);
+ current->Start();
+}
+
+void MProfiler::Step(const char *name)
+{
+ current->Step(name);
+}
+
+void MProfiler::End()
+{
+ current->Stop();
+
+ if (current->parent != NULL)
+ {
+ current = current->parent;
+ QueryPerformanceCounter(¤t->last_step);
+ }
+}
+
+void MProfiler::Dump(const char *module)
+{
+ Dump(module, "", &root, -1, -1);
+}
+
+
+void MProfiler::Dump(const char *module, std::string prefix, Block *block, double parent, double total)
+{
+ for(std::map<std::string, MProfiler::Block *>::iterator it = block->children.begin();
+ it != block->children.end(); ++it)
+ {
+ Block *child = it->second;
+ double elapsed = child->GetTimeMS();
+
+ if (total > 0)
+ {
+ mlog(module, "Profiler", "%s%-20s\t%5.1lf\t[%3.0lf%%]\t[%3.0lf%%]", prefix.c_str(), it->first.c_str(),
+ elapsed, elapsed / parent * 100, elapsed / total * 100);
+ }
+ else
+ {
+ mlog(module, "Profiler", "%s%-20s\t%5.1lf", prefix.c_str(), it->first.c_str(),
+ elapsed);
+ }
+
+ Dump(module, prefix + " ", child, elapsed, total > 0 ? total : elapsed);
+ }
+}
+
diff --git a/plugins/Utils/mir_profiler.h b/plugins/Utils/mir_profiler.h new file mode 100644 index 0000000000..92d776f2ee --- /dev/null +++ b/plugins/Utils/mir_profiler.h @@ -0,0 +1,77 @@ +/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __PROFILER_H__
+# define __PROFILER_H__
+
+#include <windows.h>
+#include <string>
+#include <map>
+
+
+
+class MProfiler
+{
+public:
+
+ static void Reset();
+ static void Start(const char *name);
+ static void Step(const char *name);
+ static void End();
+ static void Dump(const char *module);
+
+
+
+ static struct Block
+ {
+ std::string name;
+ Block *parent;
+ std::map<std::string, Block *> children;
+ bool started;
+ LARGE_INTEGER start;
+ LARGE_INTEGER last_step;
+ LARGE_INTEGER total;
+
+ Block();
+ ~Block();
+
+ void Reset();
+ void Start();
+ void Step(const char *name);
+ void Stop();
+ double GetTimeMS() const;
+
+ Block * GetChild(const char *name);
+ };
+
+
+private:
+
+ static Block root;
+ static Block *current;
+
+ static void Dump(const char *module, std::string prefix, Block *block, double parent, double total);
+
+};
+
+
+
+
+#endif // __PROFILER_H__
diff --git a/plugins/Utils/mir_scope.h b/plugins/Utils/mir_scope.h new file mode 100644 index 0000000000..2f54044d83 --- /dev/null +++ b/plugins/Utils/mir_scope.h @@ -0,0 +1,35 @@ +#ifndef __PTR_H__
+# define __PTR_H__
+
+
+template<class T>
+class scope
+{
+public:
+ scope(T t) : p(t) {}
+ ~scope() { mir_free(); }
+
+ void free()
+ {
+ if (p != NULL)
+ mir_free(p);
+ p = NULL;
+ }
+
+// T operator->() const { return p; }
+ operator T() const { return p; }
+
+ T detach()
+ {
+ T ret = p;
+ p = NULL;
+ return ret;
+ }
+
+private:
+ T p;
+};
+
+
+
+#endif // __PTR_H__
diff --git a/plugins/Utils/mir_smileys.cpp b/plugins/Utils/mir_smileys.cpp new file mode 100644 index 0000000000..59587f4c9c --- /dev/null +++ b/plugins/Utils/mir_smileys.cpp @@ -0,0 +1,521 @@ +/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#define MIRANDA_VER 0x0A00
+#include "mir_smileys.h"
+#include "mir_memory.h"
+#include "utf8_helpers.h"
+
+#include <richedit.h>
+#include <m_smileyadd.h>
+#include <newpluginapi.h>
+#include <m_langpack.h>
+#include <m_clui.h>
+#include <m_database.h>
+#include <commctrl.h>
+#include <m_skin_eng.h>
+#include <tchar.h>
+
+
+
+// Prototypes
+
+#define TEXT_PIECE_TYPE_TEXT 0
+#define TEXT_PIECE_TYPE_SMILEY 1
+typedef struct
+{
+ int type;
+ int len;
+ union
+ {
+ struct
+ {
+ int start_pos;
+ };
+ struct
+ {
+ HICON smiley;
+ int smiley_width;
+ int smiley_height;
+ };
+ };
+} TextPiece;
+
+
+
+SortedList * ReplaceSmileys(const char *text, int text_size, const char *protocol, int *max_smiley_height);
+void DrawTextSmiley(HDC hdcMem, RECT free_rc, const char *szText, int len, SortedList *plText, UINT uTextFormat, int max_smiley_height);
+void DestroySmileyList( SortedList* p_list );
+SIZE GetTextSize(HDC hdcMem, const char *szText, SortedList *plText, UINT uTextFormat, int max_smiley_height);
+
+
+
+// Functions
+
+int InitContactListSmileys()
+{
+ // Register smiley category
+ if (ServiceExists(MS_SMILEYADD_REGISTERCATEGORY))
+ {
+ SMADD_REGCAT rc;
+
+ rc.cbSize = sizeof(rc);
+ rc.name = "clist";
+ rc.dispname = Translate("Contact List smileys");
+
+ CallService(MS_SMILEYADD_REGISTERCATEGORY, 0, (LPARAM)&rc);
+ }
+
+ return 0;
+}
+
+SmileysParseInfo Smileys_PreParse(LPCSTR lpString, int nCount, const char *protocol)
+{
+ SmileysParseInfo info = (SmileysParseInfo) mir_alloc0(sizeof(_SmileysParseInfo));
+
+ info->pieces = ReplaceSmileys(lpString, nCount, protocol, &info->max_height);
+
+ return info;
+}
+
+void Smileys_FreeParse(SmileysParseInfo parseInfo)
+{
+ if (parseInfo != NULL)
+ {
+ if (parseInfo->pieces != NULL)
+ DestroySmileyList(parseInfo->pieces);
+
+ mir_free(parseInfo);
+ }
+}
+
+int skin_DrawText(HDC hDC, LPCSTR lpString, int nCount, LPRECT lpRect, UINT uFormat)
+{
+ if ((uFormat & DT_CALCRECT) == 0 && ServiceExists(MS_SKINENG_ALPHATEXTOUT))
+ {
+ COLORREF color = SetTextColor(hDC, 0);
+ SetTextColor(hDC, color);
+
+ if (mir_is_unicode())
+ {
+ return AlphaText(hDC, (char *) (const WCHAR *) CharToWchar(lpString), nCount, lpRect, uFormat, color);
+ }
+ else
+ {
+ return AlphaText(hDC, lpString, nCount, lpRect, uFormat, color);
+ }
+ }
+ else
+ {
+ return DrawText(hDC, lpString, nCount, lpRect, uFormat);
+ }
+}
+
+int skin_DrawIconEx(HDC hdc, int xLeft, int yTop, HICON hIcon, int cxWidth, int cyWidth,
+ UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags)
+{
+ if (ServiceExists(MS_SKINENG_DRAWICONEXFIX))
+ return mod_DrawIconEx_helper(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth, istepIfAniCur, hbrFlickerFreeDraw, diFlags);
+ else
+ return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth, istepIfAniCur, hbrFlickerFreeDraw, diFlags);
+}
+
+
+
+// Similar to DrawText win32 api function
+// Pass uFormat | DT_CALCRECT to calc rectangle to be returned by lpRect
+// parseInfo is optional (pass NULL and it will be calculated and deleted inside function
+int Smileys_DrawText(HDC hDC, LPCSTR lpString, int nCount, LPRECT lpRect, UINT uFormat, const char *protocol, SmileysParseInfo parseInfo)
+{
+ SmileysParseInfo info;
+ int ret;
+
+ if (nCount < 0)
+ nCount = strlen(lpString);
+
+ // Get parse info
+ if (parseInfo == NULL)
+ info = Smileys_PreParse(lpString, nCount, protocol);
+ else
+ info = parseInfo;
+
+ if (uFormat & DT_CALCRECT)
+ {
+ SIZE text_size = GetTextSize(hDC, lpString, info->pieces, uFormat, info->max_height);
+
+ lpRect->bottom = min(lpRect->bottom, lpRect->top + text_size.cy);
+
+ if (text_size.cx < lpRect->right - lpRect->left)
+ {
+ if (uFormat & DT_RIGHT)
+ lpRect->left = lpRect->right - text_size.cx;
+ else
+ lpRect->right = lpRect->left + text_size.cx;
+ }
+
+ ret = text_size.cy;
+ }
+ else
+ {
+ // Clipping rgn
+ HRGN oldRgn = CreateRectRgn(0,0,1,1);
+ if (GetClipRgn(hDC, oldRgn) != 1)
+ {
+ DeleteObject(oldRgn);
+ oldRgn = NULL;
+ }
+
+ HRGN rgn = CreateRectRgnIndirect(lpRect);
+ ExtSelectClipRgn(hDC, rgn, RGN_AND);
+
+ // Draw
+ if (info->pieces == NULL)
+ {
+ ret = skin_DrawText(hDC, lpString, nCount, lpRect, uFormat);
+ }
+ else
+ {
+ RECT rc = *lpRect;
+
+ SIZE text_size = GetTextSize(hDC, lpString, info->pieces, uFormat, info->max_height);
+
+ if (text_size.cx < rc.right - rc.left)
+ {
+ if (uFormat & DT_RIGHT)
+ rc.left = rc.right - text_size.cx;
+ else
+ rc.right = rc.left + text_size.cx;
+ }
+
+ ret = text_size.cy;
+
+ DrawTextSmiley(hDC, rc, lpString, nCount, info->pieces, uFormat, info->max_height);
+ }
+
+ // Clipping rgn
+ SelectClipRgn(hDC, oldRgn);
+ DeleteObject(rgn);
+ if (oldRgn) DeleteObject(oldRgn);
+ }
+
+
+ // Free parse info
+ if (parseInfo == NULL)
+ Smileys_FreeParse(info);
+
+ return ret;
+}
+
+
+
+SIZE GetTextSize(HDC hdcMem, const char *szText, SortedList *plText, UINT uTextFormat, int max_smiley_height)
+{
+ SIZE text_size;
+
+ if (szText == NULL)
+ {
+ text_size.cy = 0;
+ text_size.cx = 0;
+ }
+ else
+ {
+ RECT text_rc = {0, 0, 0x7FFFFFFF, 0x7FFFFFFF};
+
+ // Always need cy...
+ DrawText(hdcMem,szText,lstrlen(szText), &text_rc, DT_CALCRECT | uTextFormat);
+ text_size.cy = text_rc.bottom - text_rc.top;
+
+ if (plText == NULL)
+ {
+ text_size.cx = text_rc.right - text_rc.left;
+ }
+ else
+ {
+ if (!(uTextFormat & DT_RESIZE_SMILEYS))
+ text_size.cy = max(text_size.cy, max_smiley_height);
+
+ text_size.cx = 0;
+
+ // See each item of list
+ for (int i = 0; i < plText->realCount; i++)
+ {
+ TextPiece *piece = (TextPiece *) plText->items[i];
+
+ if (piece->type == TEXT_PIECE_TYPE_TEXT)
+ {
+ RECT text_rc = {0, 0, 0x7FFFFFFF, 0x7FFFFFFF};
+
+ DrawText(hdcMem, &szText[piece->start_pos], piece->len, &text_rc, DT_CALCRECT | uTextFormat);
+ text_size.cx = text_size.cx + text_rc.right - text_rc.left;
+ }
+ else
+ {
+ double factor;
+
+ if ((uTextFormat & DT_RESIZE_SMILEYS) && piece->smiley_height > text_size.cy)
+ {
+ factor = text_size.cy / (double) piece->smiley_height;
+ }
+ else
+ {
+ factor = 1;
+ }
+
+ text_size.cx = text_size.cx + (LONG)(factor * piece->smiley_width);
+ }
+ }
+ }
+ }
+
+ return text_size;
+}
+
+void DrawTextSmiley(HDC hdcMem, RECT free_rc, const char *szText, int len, SortedList *plText, UINT uTextFormat, int max_smiley_height)
+{
+ if (szText == NULL)
+ {
+ return;
+ }
+
+ uTextFormat &= ~DT_RIGHT;
+
+ // Draw list
+ int i;
+ int pos_x = 0;
+ int row_height, text_height;
+ RECT tmp_rc = free_rc;
+
+ if (uTextFormat & DT_RTLREADING)
+ i = plText->realCount - 1;
+ else
+ i = 0;
+
+ // Get real height of the line
+ text_height = skin_DrawText(hdcMem, "A", 1, &tmp_rc, DT_CALCRECT | uTextFormat);
+ if (uTextFormat & DT_RESIZE_SMILEYS)
+ row_height = text_height;
+ else
+ row_height = max(text_height, max_smiley_height);
+
+ // Just draw ellipsis
+ if (free_rc.right <= free_rc.left)
+ {
+ skin_DrawText(hdcMem, "...", 3, &free_rc, uTextFormat & ~DT_END_ELLIPSIS);
+ }
+ else
+ {
+ // Draw text and smileys
+ for (; i < plText->realCount && i >= 0 && pos_x < free_rc.right - free_rc.left && len > 0; i += (uTextFormat & DT_RTLREADING ? -1 : 1))
+ {
+ TextPiece *piece = (TextPiece *) plText->items[i];
+ RECT text_rc = free_rc;
+
+ if (uTextFormat & DT_RTLREADING)
+ text_rc.right -= pos_x;
+ else
+ text_rc.left += pos_x;
+
+ if (piece->type == TEXT_PIECE_TYPE_TEXT)
+ {
+ text_rc.top += (row_height - text_height) >> 1;
+
+ tmp_rc = text_rc;
+ tmp_rc.right += 50;
+ skin_DrawText(hdcMem, &szText[piece->start_pos], min(len, piece->len), &tmp_rc, DT_CALCRECT | (uTextFormat & ~DT_END_ELLIPSIS));
+ pos_x += tmp_rc.right - tmp_rc.left;
+
+ if (uTextFormat & DT_RTLREADING)
+ text_rc.left = max(text_rc.left, text_rc.right - (tmp_rc.right - tmp_rc.left));
+
+ skin_DrawText(hdcMem, &szText[piece->start_pos], min(len, piece->len), &text_rc, uTextFormat);
+ len -= piece->len;
+ }
+ else
+ {
+ double factor;
+
+ if (len < piece->len)
+ {
+ len = 0;
+ }
+ else
+ {
+ len -= piece->len;
+
+ if ((uTextFormat & DT_RESIZE_SMILEYS) && piece->smiley_height > row_height)
+ {
+ factor = row_height / (double) piece->smiley_height;
+ }
+ else
+ {
+ factor = 1;
+ }
+
+ if (uTextFormat & DT_RTLREADING)
+ text_rc.left = max(text_rc.right - (LONG) (piece->smiley_width * factor), text_rc.left);
+
+ if ((LONG)(piece->smiley_width * factor) <= text_rc.right - text_rc.left)
+ {
+ text_rc.top += (row_height - (LONG)(piece->smiley_height * factor)) >> 1;
+
+ skin_DrawIconEx(hdcMem, text_rc.left, text_rc.top, piece->smiley,
+ (LONG)(piece->smiley_width * factor), (LONG)(piece->smiley_height * factor), 0, NULL, DI_NORMAL);
+ }
+ else
+ {
+ text_rc.top += (row_height - text_height) >> 1;
+ skin_DrawText(hdcMem, "...", 3, &text_rc, uTextFormat);
+ }
+
+ pos_x += (LONG)(piece->smiley_width * factor);
+ }
+ }
+ }
+ }
+}
+
+
+void DestroySmileyList( SortedList* p_list )
+{
+ if ( p_list == NULL )
+ return;
+
+ if ( p_list->items != NULL )
+ {
+ int i;
+ for ( i = 0 ; i < p_list->realCount ; i++ )
+ {
+ TextPiece *piece = (TextPiece *) p_list->items[i];
+
+ if ( piece != NULL )
+ {
+ if (piece->type == TEXT_PIECE_TYPE_SMILEY)
+ DestroyIcon(piece->smiley);
+
+ mir_free(piece);
+ }
+ }
+ }
+
+ List_Destroy( p_list );
+}
+
+
+
+// Generete the list of smileys / text to be drawn
+SortedList * ReplaceSmileys(const char *text, int text_size, const char *protocol, int *max_smiley_height)
+{
+ SMADD_BATCHPARSE2 sp = {0};
+ SMADD_BATCHPARSERES *spres;
+
+ *max_smiley_height = 0;
+
+ if (text[0] == '\0' || !ServiceExists(MS_SMILEYADD_BATCHPARSE))
+ {
+ return NULL;
+ }
+
+ // Parse it!
+ sp.cbSize = sizeof(sp);
+ sp.Protocolname = protocol;
+ sp.str = (char *)text;
+ sp.oflag = SAFL_TCHAR;
+ spres = (SMADD_BATCHPARSERES *) CallService(MS_SMILEYADD_BATCHPARSE, 0, (LPARAM)&sp);
+
+ if (spres == NULL)
+ {
+ // Did not find a simley
+ return NULL;
+ }
+
+ // Lets add smileys
+ SortedList *plText = List_Create(0, 10);
+
+ const char *next_text_pos = text;
+ const char *last_text_pos = _tcsninc(text, text_size);
+
+ for (unsigned int i = 0; i < sp.numSmileys; i++)
+ {
+ char * start = _tcsninc(text, spres[i].startChar);
+ char * end = _tcsninc(start, spres[i].size);
+
+ if (spres[i].hIcon != NULL) // For deffective smileypacks
+ {
+ // Add text
+ if (start > next_text_pos)
+ {
+ TextPiece *piece = (TextPiece *) mir_alloc0(sizeof(TextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_TEXT;
+ piece->start_pos = next_text_pos - text;
+ piece->len = start - next_text_pos;
+
+ List_Append(plText, piece);
+ }
+
+ // Add smiley
+ {
+ BITMAP bm;
+ ICONINFO icon;
+ TextPiece *piece = (TextPiece *) mir_alloc0(sizeof(TextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_SMILEY;
+ piece->len = end - start;
+ piece->smiley = spres[i].hIcon;
+
+ piece->smiley_width = 16;
+ piece->smiley_height = 16;
+ if (GetIconInfo(piece->smiley, &icon))
+ {
+ if (GetObject(icon.hbmColor,sizeof(BITMAP),&bm))
+ {
+ piece->smiley_width = bm.bmWidth;
+ piece->smiley_height = bm.bmHeight;
+ }
+
+ DeleteObject(icon.hbmMask);
+ DeleteObject(icon.hbmColor);
+ }
+
+ *max_smiley_height = max(piece->smiley_height, *max_smiley_height);
+
+ List_Append(plText, piece);
+ }
+
+ next_text_pos = end;
+ }
+ }
+
+ // Add rest of text
+ if (last_text_pos > next_text_pos)
+ {
+ TextPiece *piece = (TextPiece *) mir_alloc0(sizeof(TextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_TEXT;
+ piece->start_pos = next_text_pos - text;
+ piece->len = last_text_pos - next_text_pos;
+
+ List_Append(plText, piece);
+ }
+
+ CallService(MS_SMILEYADD_BATCHFREE, 0, (LPARAM)spres);
+
+ return plText;
+}
diff --git a/plugins/Utils/mir_smileys.h b/plugins/Utils/mir_smileys.h new file mode 100644 index 0000000000..cfbebb853a --- /dev/null +++ b/plugins/Utils/mir_smileys.h @@ -0,0 +1,69 @@ +/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __MIR_SMILEYS_H__
+# define __MIR_SMILEYS_H__
+
+#include <windows.h>
+
+
+/*
+To use this files mir_dblists.h/.c are needed
+*/
+#include "mir_dblists.h"
+
+
+// Init settings needed to draw smileys using the contact list itens
+// To use then, pass "clist" as the protocol name
+// Need to be called on ME_SYSTEM_MODULESLOADED
+int InitContactListSmileys();
+
+
+// Pre-parse smileys
+typedef struct _SmileysParseInfo
+{
+ SortedList *pieces;
+ int max_height;
+} * SmileysParseInfo;
+
+SmileysParseInfo Smileys_PreParse(LPCSTR lpString, int nCount, const char *protocol);
+void Smileys_FreeParse(SmileysParseInfo parseInfo);
+
+// TODO:
+// SmileysParseInfo Smileys_PreParseW(HDC hDC, LPCWSTR lpString, int nCount, const char *protocol);
+
+
+#define DT_RESIZE_SMILEYS 0x10000000
+
+// Similar to DrawText win32 api function
+// Pass uFormat | DT_CALCRECT to calc rectangle to be returned by lpRect
+// parseInfo is optional (pass NULL and it will be calculated and deleted inside function)
+int Smileys_DrawText(HDC hDC, LPCSTR lpString, int nCount, LPRECT lpRect, UINT uFormat, const char *protocol, SmileysParseInfo parseInfo);
+
+// TODO:
+// int Smileys_DrawTextW(HDC hDC, LPCWSTR lpString, int nCount, LPRECT lpRect, UINT uFormat, const char *protocol, SmileysParseInfo parseInfo);
+
+
+int skin_DrawText(HDC hDC, LPCSTR lpString, int nCount, LPRECT lpRect, UINT uFormat);
+int skin_DrawIconEx(HDC hdc, int xLeft, int yTop, HICON hIcon, int cxWidth, int cyWidth, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags);
+
+
+
+#endif // __MIR_SMILEYS_H__
diff --git a/plugins/Utils/scope.h b/plugins/Utils/scope.h new file mode 100644 index 0000000000..5556e5f97f --- /dev/null +++ b/plugins/Utils/scope.h @@ -0,0 +1,106 @@ +/*
+Copyright (C) 2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __SCOPE_H__
+# define __SCOPE_H__
+
+
+#define DEFINE_SCOPED_TYPE(_NAME_, _DELETE_) \
+ template<class T> \
+ class _NAME_ \
+ { \
+ _NAME_(_NAME_ &); \
+ _NAME_ & operator=(_NAME_ &); \
+ \
+ public: \
+ _NAME_(T *t = NULL) : p(t) {} \
+ \
+ ~_NAME_() \
+ { \
+ release(); \
+ } \
+ \
+ T * operator=(T *t) \
+ { \
+ release(); \
+ p = t; \
+ return t; \
+ } \
+ \
+ operator T*() const \
+ { \
+ return p; \
+ } \
+ \
+ bool operator==(T *t) const \
+ { \
+ return p == t; \
+ } \
+ \
+ bool operator!=(T *t) const \
+ { \
+ return p != t; \
+ } \
+ \
+ T *get() const \
+ { \
+ return p; \
+ } \
+ \
+ void release() \
+ { \
+ if (p != NULL) \
+ dealoc(p); \
+ p = NULL; \
+ } \
+ \
+ T* detach() \
+ { \
+ T *ret = p; \
+ p = NULL; \
+ return ret; \
+ } \
+ \
+ protected: \
+ T *p; \
+ \
+ void dealoc(T *ptr) \
+ { \
+ _DELETE_; \
+ } \
+ }; \
+ \
+ template<typename T> \
+ inline bool operator==(T* p, const _NAME_<T> &b) { \
+ return p == b.get(); \
+ } \
+ \
+ template<typename T> \
+ inline bool operator!=(T* p, const _NAME_<T> &b) { \
+ return p != b.get(); \
+ }
+
+DEFINE_SCOPED_TYPE(scoped_ptr, delete ptr)
+DEFINE_SCOPED_TYPE(scoped_array, delete[] ptr)
+DEFINE_SCOPED_TYPE(scoped_free, free(ptr))
+DEFINE_SCOPED_TYPE(scoped_mir_free, mir_free(ptr))
+
+
+#endif // __SCOPE_H__
diff --git a/plugins/Utils/templates.cpp b/plugins/Utils/templates.cpp new file mode 100644 index 0000000000..11a81d856e --- /dev/null +++ b/plugins/Utils/templates.cpp @@ -0,0 +1,476 @@ +#include "templates.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <tchar.h>
+
+extern "C"
+{
+#include <newpluginapi.h>
+#include <time.h>
+#include <win2k.h>
+#include <m_system.h>
+#include <m_plugins.h>
+#include <m_options.h>
+#include <m_langpack.h>
+#include <m_database.h>
+#include <m_utils.h>
+#include <m_protocols.h>
+
+#include <m_notify.h>
+
+#include "../utils/mir_memory.h"
+}
+
+
+const char *defaultVariables[] = { "%title%", "%text%" };
+const WCHAR *defaultVariablesW[] = { L"%title%", L"%text%" };
+
+const char *defaultVariableDescriptions[] = { "Notification Title", "Notification Text" };
+const WCHAR *defaultVariableDescriptionsW[] = { L"Notification Title", L"Notification Text" };
+
+
+#define MAX_REGS(_A_) ( sizeof(_A_) / sizeof(_A_[0]) )
+
+
+#define DATA_BLOCK 128
+
+
+// ASCII VERSIONS ///////////////////////////////////////////////////////////////////////
+
+struct StringHelper
+{
+ char *text;
+ size_t allocated;
+ size_t used;
+};
+
+
+int CopyData(StringHelper *str, const char *text, size_t len)
+{
+ if (len == 0)
+ return 0;
+
+ if (text == NULL)
+ return 0;
+
+ size_t totalSize = str->used + len + 1;
+
+ if (totalSize > str->allocated)
+ {
+ totalSize += DATA_BLOCK - (totalSize % DATA_BLOCK);
+
+ if (str->text != NULL)
+ {
+ char *tmp = (char *) mir_realloc(str->text, sizeof(char) * totalSize);
+
+ if (tmp == NULL)
+ {
+ mir_free(str->text);
+ return -1;
+ }
+
+ str->text = tmp;
+ }
+ else
+ {
+ str->text = (char *) mir_alloc(sizeof(char) * totalSize);
+
+ if (str->text == NULL)
+ {
+ return -2;
+ }
+ }
+
+ str->allocated = totalSize;
+ }
+
+ memmove(&str->text[str->used], text, sizeof(char) * len);
+ str->used += len;
+ str->text[str->used] = '\0';
+
+ return 0;
+}
+
+
+char * ParseText(const char *text,
+ const char **variables, size_t variablesSize,
+ const char **data, size_t dataSize)
+{
+ size_t length = strlen(text);
+ size_t nextPos = 0;
+ StringHelper ret = {0};
+
+ // length - 1 because a % in last char will be a % and point
+ for (size_t i = 0 ; i < length - 1 ; i++)
+ {
+ if (text[i] == '%')
+ {
+ bool found = false;
+
+ if (CopyData(&ret, &text[nextPos], i - nextPos))
+ return NULL;
+
+ if (text[i + 1] == '%')
+ {
+ if (CopyData(&ret, "%", 1))
+ return NULL;
+
+ i++;
+
+ found = true;
+ }
+ else
+ {
+ size_t size = min(variablesSize, dataSize);
+
+ // See if can find it
+ for(size_t j = 0 ; j < size ; j++)
+ {
+ size_t vlen = strlen(variables[j]);
+
+ if (strnicmp(&text[i], variables[j], vlen) == 0)
+ {
+ if (CopyData(&ret, data[j], strlen(data[j])))
+ return NULL;
+
+ i += vlen - 1;
+
+ found = true;
+
+ break;
+ }
+ }
+ }
+
+
+ if (found)
+ nextPos = i + 1;
+ else
+ nextPos = i;
+ }
+ }
+
+ if (nextPos < length)
+ if (CopyData(&ret, &text[nextPos], length - nextPos))
+ return NULL;
+
+ return ret.text;
+}
+
+
+// UNICODE VERSIONS /////////////////////////////////////////////////////////////////////
+
+struct StringHelperW
+{
+ WCHAR *text;
+ size_t allocated;
+ size_t used;
+};
+
+
+int CopyDataW(StringHelperW *str, const WCHAR *text, size_t len)
+{
+ if (len == 0)
+ return 0;
+
+ if (text == NULL)
+ return 0;
+
+ size_t totalSize = str->used + len + 1;
+
+ if (totalSize > str->allocated)
+ {
+ totalSize += DATA_BLOCK - (totalSize % DATA_BLOCK);
+
+ if (str->text != NULL)
+ {
+ WCHAR *tmp = (WCHAR *) mir_realloc(str->text, sizeof(WCHAR) * totalSize);
+
+ if (tmp == NULL)
+ {
+ mir_free(str->text);
+ return -1;
+ }
+
+ str->text = tmp;
+ }
+ else
+ {
+ str->text = (WCHAR *) mir_alloc(sizeof(WCHAR) * totalSize);
+
+ if (str->text == NULL)
+ {
+ return -2;
+ }
+ }
+
+ str->allocated = totalSize;
+ }
+
+ memmove(&str->text[str->used], text, sizeof(WCHAR) * len);
+ str->used += len;
+ str->text[str->used] = '\0';
+
+ return 0;
+}
+
+
+WCHAR * ParseTextW(const WCHAR *text,
+ const WCHAR **variables, size_t variablesSize,
+ const WCHAR **data, size_t dataSize)
+{
+ size_t length = lstrlenW(text);
+ size_t nextPos = 0;
+ StringHelperW ret = {0};
+
+ // length - 1 because a % in last char will be a % and point
+ for (size_t i = 0 ; i < length - 1 ; i++)
+ {
+ if (text[i] == L'%')
+ {
+ bool found = false;
+
+ if (CopyDataW(&ret, &text[nextPos], i - nextPos))
+ return NULL;
+
+ if (text[i + 1] == L'%')
+ {
+ if (CopyDataW(&ret, L"%", 1))
+ return NULL;
+
+ i++;
+
+ found = true;
+ }
+ else
+ {
+ size_t size = min(variablesSize, dataSize);
+
+ // See if can find it
+ for(size_t j = 0 ; j < size ; j++)
+ {
+ size_t vlen = lstrlenW(variables[j]);
+
+ if (_wcsnicmp(&text[i], variables[j], vlen) == 0)
+ {
+ if (CopyDataW(&ret, data[j], lstrlenW(data[j])))
+ return NULL;
+
+ i += vlen - 1;
+
+ found = true;
+
+ break;
+ }
+ }
+ }
+
+ if (found)
+ nextPos = i + 1;
+ else
+ nextPos = i;
+ }
+ }
+
+ if (nextPos < length)
+ if (CopyDataW(&ret, &text[nextPos], length - nextPos))
+ return NULL;
+
+ return ret.text;
+}
+
+
+// INTERFACE ////////////////////////////////////////////////////////////////////////////
+
+// In future maybe pre-parse here
+void MNotifySetTemplate(HANDLE notifyORtype, const char *name, const char *value)
+{
+ MNotifySetString(notifyORtype, name, value);
+}
+void MNotifySetWTemplate(HANDLE notifyORtype, const char *name, const WCHAR *value)
+{
+ MNotifySetWString(notifyORtype, name, value);
+}
+
+// Well, why not?
+const char *MNotifyGetTemplate(HANDLE notifyORtype, const char *name, const char *defValue)
+{
+ return MNotifyGetString(notifyORtype, name, defValue);
+}
+const WCHAR *MNotifyGetWTemplate(HANDLE notifyORtype, const char *name, const WCHAR *defValue)
+{
+ return MNotifyGetWString(notifyORtype, name, defValue);
+}
+
+// You must free the return with mir_sys_free
+char *MNotifyGetParsedTemplate(HANDLE notifyORtype, const char *name, const char *defValue)
+{
+ const char *temp = MNotifyGetString(notifyORtype, name, defValue);
+
+ if (MNotifyHasVariables(notifyORtype))
+ {
+ const char ** vars = (const char **) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_STRS, NULL);
+ size_t varsSize = (size_t) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_SIZE, 0);
+
+ const char ** data = (const char **) MNotifyGetDWord(notifyORtype, NFOPT_DATA_STRS, NULL);
+ size_t dataSize = (size_t) MNotifyGetDWord(notifyORtype, NFOPT_DATA_SIZE, 0);
+
+ return ParseText(temp, vars, varsSize, data, dataSize);
+ }
+ else
+ {
+ // Default values
+ const char * data[MAX_REGS(defaultVariables)];
+ data[0] = MNotifyGetString(notifyORtype, NFOPT_TITLE, NULL);
+ data[1] = MNotifyGetString(notifyORtype, NFOPT_TEXT, NULL);
+
+ return ParseText(temp, defaultVariables, MAX_REGS(defaultVariables), data, MAX_REGS(defaultVariables));
+ }
+}
+WCHAR *MNotifyGetWParsedTemplate(HANDLE notifyORtype, const char *name, const WCHAR *defValue)
+{
+ const WCHAR *temp = MNotifyGetWString(notifyORtype, name, defValue);
+
+ if (MNotifyHasWVariables(notifyORtype))
+ {
+ const WCHAR ** vars = (const WCHAR **) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_STRSW, NULL);
+ size_t varsSize = (size_t) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_SIZE, 0);
+
+ const WCHAR ** data = (const WCHAR **) MNotifyGetDWord(notifyORtype, NFOPT_DATA_STRSW, NULL);
+ size_t dataSize = (size_t) MNotifyGetDWord(notifyORtype, NFOPT_DATA_SIZE, 0);
+
+ return ParseTextW(temp, vars, varsSize, data, dataSize);
+ }
+ else
+ {
+ // Default values
+ const WCHAR * data[MAX_REGS(defaultVariablesW)];
+ data[0] = MNotifyGetWString(notifyORtype, NFOPT_TITLEW, NULL);
+ data[1] = MNotifyGetWString(notifyORtype, NFOPT_TEXTW, NULL);
+
+ return ParseTextW(temp, defaultVariablesW, MAX_REGS(defaultVariablesW), data, MAX_REGS(defaultVariablesW));
+ }
+}
+
+
+BOOL MNotifyHasVariables(HANDLE notifyORtype)
+{
+ return MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_STRS, NULL) != NULL &&
+ MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_SIZE, 0) != 0;
+}
+
+BOOL MNotifyHasWVariables(HANDLE notifyORtype)
+{
+ return MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_STRSW, NULL) != NULL &&
+ MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_SIZE, 0) != 0;
+}
+
+
+
+
+void MNotifyShowVariables(HANDLE notifyORtype)
+{
+ StringHelper ret = {0};
+
+ const char ** vars;
+ size_t varsSize;
+ const char ** descs;
+ size_t descsSize;
+
+ if (MNotifyHasVariables(notifyORtype))
+ {
+ vars = (const char **) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_STRS, NULL);
+ varsSize = (size_t) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_SIZE, 0);
+
+ descs = (const char **) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_DESCRIPTIONS_STRS, NULL);
+ descsSize = (size_t) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_DESCRIPTIONS_SIZE, 0);
+ }
+ else
+ {
+ // Default values
+ vars = defaultVariables;
+ varsSize = MAX_REGS(defaultVariables);
+
+ descs = defaultVariableDescriptions;
+ descsSize = MAX_REGS(defaultVariableDescriptions);
+ }
+
+ for(size_t i = 0 ; i < varsSize ; i++)
+ {
+ if (vars[i] != NULL)
+ {
+ if (CopyData(&ret, vars[i], strlen(vars[i])))
+ return;
+
+ if (i < descsSize && descs[i] != NULL && descs[i] != L'\0')
+ {
+ if (CopyData(&ret, " -> ", 4))
+ return;
+ if (CopyData(&ret, descs[i], strlen(descs[i])))
+ return;
+ }
+
+ if (CopyData(&ret, "\r\n", 2))
+ return;
+ }
+ }
+
+ MessageBoxA(NULL, ret.text, "Variables", MB_OK);
+
+ mir_free(ret.text);
+}
+
+void MNotifyShowWVariables(HANDLE notifyORtype)
+{
+ StringHelperW ret = {0};
+
+ const WCHAR ** vars;
+ size_t varsSize;
+ const WCHAR ** descs;
+ size_t descsSize;
+
+ if (MNotifyHasWVariables(notifyORtype))
+ {
+ vars = (const WCHAR **) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_STRSW, NULL);
+ varsSize = (size_t) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_SIZE, 0);
+
+ descs = (const WCHAR **) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_DESCRIPTIONS_STRSW, NULL);
+ descsSize = (size_t) MNotifyGetDWord(notifyORtype, NFOPT_VARIABLES_DESCRIPTIONS_SIZE, 0);
+ }
+ else
+ {
+ // Default values
+ vars = defaultVariablesW;
+ varsSize = MAX_REGS(defaultVariablesW);
+
+ descs = defaultVariableDescriptionsW;
+ descsSize = MAX_REGS(defaultVariableDescriptionsW);
+ }
+
+ for(size_t i = 0 ; i < varsSize ; i++)
+ {
+ if (vars[i] != NULL)
+ {
+ if (CopyDataW(&ret, vars[i], lstrlenW(vars[i])))
+ return;
+
+ if (i < descsSize && descs[i] != NULL && descs[i] != L'\0')
+ {
+ if (CopyDataW(&ret, L" -> ", 3))
+ return;
+ if (CopyDataW(&ret, descs[i], lstrlenW(descs[i])))
+ return;
+ }
+
+ if (CopyDataW(&ret, L"\r\n", 2))
+ return;
+ }
+ }
+
+ MessageBoxW(NULL, ret.text, L"Variables", MB_OK);
+
+ mir_free(ret.text);
+}
+
+
diff --git a/plugins/Utils/templates.h b/plugins/Utils/templates.h new file mode 100644 index 0000000000..e55fb7a50e --- /dev/null +++ b/plugins/Utils/templates.h @@ -0,0 +1,102 @@ +#ifndef __TEMPLATES_H__
+# define __TEMPLATES_H__
+
+
+#include <windows.h>
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+// Default templates to be set by using notifiers
+
+#define NFOPT_DEFTEMPL_TEXT "General/DefaultTemplate/Text"
+#define NFOPT_DEFTEMPL_TEXTW "General/DefaultTemplate/TextW"
+#define NFOPT_DEFTEMPL_TITLE "General/DefaultTemplate/Title"
+#define NFOPT_DEFTEMPL_TITLEW "General/DefaultTemplate/TitleW"
+
+
+
+
+// All of theese have to be stored as DWORDs
+
+#define NFOPT_VARIABLES_STRS "Variables/Strings" // char ** (each has to start and end with %)
+#define NFOPT_VARIABLES_DESCRIPTIONS_STRS "VariablesDescriptions/Strings" // char **
+#define NFOPT_DATA_STRS "Data/Strings" // char **
+
+#define NFOPT_VARIABLES_STRSW "Variables/StringsW" // WCHAR ** (each has to start and end with %)
+#define NFOPT_VARIABLES_DESCRIPTIONS_STRSW "VariablesDescriptions/StringsW"// WCHAR **
+#define NFOPT_DATA_STRSW "Data/StringsW" // WCHAR **
+
+#define NFOPT_VARIABLES_SIZE "Variables/Size" // size_t
+#define NFOPT_VARIABLES_DESCRIPTIONS_SIZE "VariablesDescriptions/Size" // size_t
+#define NFOPT_DATA_SIZE "Data/Size" // size_t
+
+
+// Default variables if none is provided by the plugin calling the notification
+// char *defaultVariables[] = { "%title%", "%text%" };
+
+
+void MNotifySetTemplate(HANDLE notifyORtype, const char *name, const char *value);
+void MNotifySetWTemplate(HANDLE notifyORtype, const char *name, const WCHAR *value);
+
+const char *MNotifyGetTemplate(HANDLE notifyORtype, const char *name, const char *defValue);
+const WCHAR *MNotifyGetWTemplate(HANDLE notifyORtype, const char *name, const WCHAR *defValue);
+
+// You must free the return with mir_sys_free
+char *MNotifyGetParsedTemplate(HANDLE notifyORtype, const char *name, const char *defValue);
+WCHAR *MNotifyGetWParsedTemplate(HANDLE notifyORtype, const char *name, const WCHAR *defValue);
+
+
+BOOL MNotifyHasVariables(HANDLE notifyORtype);
+BOOL MNotifyHasWVariables(HANDLE notifyORtype);
+
+void MNotifyShowVariables(HANDLE notifyORtype);
+void MNotifyShowWVariables(HANDLE notifyORtype);
+
+
+#ifdef _UNICODE
+
+# define MNotifyGetTString MNotifyGetWString
+# define MNotifyGetTTemplate MNotifyGetWTemplate
+# define MNotifySetTString MNotifySetWString
+# define MNotifySetTTemplate MNotifyGetWTemplate
+# define MNotifyGetTParsedTemplate MNotifyGetWParsedTemplate
+# define MNotifyHasTVariables MNotifyHasWVariables
+# define MNotifyShowTVariables MNotifyShowWVariables
+
+# define NFOPT_DEFTEMPL_TEXTT NFOPT_DEFTEMPL_TEXTW
+# define NFOPT_DEFTEMPL_TITLET NFOPT_DEFTEMPL_TITLEW
+
+# define NFOPT_VARIABLES_STRST NFOPT_VARIABLES_STRSW
+# define NFOPT_VARIABLES_DESCRIPTIONS_STRST NFOPT_VARIABLES_DESCRIPTIONS_STRSW
+# define NFOPT_DATA_STRST NFOPT_DATA_STRSW
+
+
+#else
+
+# define MNotifyGetTString MNotifyGetString
+# define MNotifyGetTTemplate MNotifyGetTemplate
+# define MNotifySetTString MNotifySetString
+# define MNotifySetTTemplate MNotifySetTemplate
+# define MNotifyGetTParsedTemplate MNotifyGetParsedTemplate
+# define MNotifyHasTVariables MNotifyHasVariables
+# define MNotifyShowTVariables MNotifyShowVariables
+
+# define NFOPT_DEFTEMPL_TEXTT NFOPT_DEFTEMPL_TEXT
+# define NFOPT_DEFTEMPL_TITLET NFOPT_DEFTEMPL_TITLE
+
+# define NFOPT_VARIABLES_STRST NFOPT_VARIABLES_STRS
+# define NFOPT_VARIABLES_DESCRIPTIONS_STRST NFOPT_VARIABLES_DESCRIPTIONS_STRS
+# define NFOPT_DATA_STRST NFOPT_DATA_STRS
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __TEMPLATES_H__
diff --git a/plugins/Utils/tstring.h b/plugins/Utils/tstring.h new file mode 100644 index 0000000000..fb340bcd03 --- /dev/null +++ b/plugins/Utils/tstring.h @@ -0,0 +1,14 @@ +#ifndef __TSTRING_H__
+# define __TSTRING_H__
+
+#include <windows.h>
+#include <tchar.h>
+#include <string>
+
+
+namespace std {
+ typedef basic_string<TCHAR, char_traits<TCHAR>, allocator<TCHAR> > tstring;
+}
+
+
+#endif // __TSTRING_H__
diff --git a/plugins/Utils/utf8_helpers.h b/plugins/Utils/utf8_helpers.h new file mode 100644 index 0000000000..3eaf0f4fe0 --- /dev/null +++ b/plugins/Utils/utf8_helpers.h @@ -0,0 +1,587 @@ +/*
+Copyright (C) 2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __UTF8_HELPERS_H__
+# define __UTF8_HELPERS_H__
+
+#include <windows.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+
+
+class TcharToUtf8
+{
+public:
+ TcharToUtf8(const char *str) : utf8(NULL)
+ {
+ int size = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+ if (size <= 0)
+ throw _T("Could not convert string to WCHAR");
+
+ WCHAR *tmp = (WCHAR *) mir_alloc(size * sizeof(WCHAR));
+ if (tmp == NULL)
+ throw _T("mir_alloc returned NULL");
+
+ MultiByteToWideChar(CP_ACP, 0, str, -1, tmp, size);
+
+ init(tmp);
+
+ mir_free(tmp);
+ }
+
+
+ TcharToUtf8(const WCHAR *str) : utf8(NULL)
+ {
+ init(str);
+ }
+
+
+ ~TcharToUtf8()
+ {
+ if (utf8 != NULL)
+ mir_free(utf8);
+ }
+
+ char *detach()
+ {
+ char *ret = utf8;
+ utf8 = NULL;
+ return ret;
+ }
+
+ const char * get() const
+ {
+ return utf8;
+ }
+
+ operator const char *() const
+ {
+ return utf8;
+ }
+
+ const char & operator[](int pos) const
+ {
+ return utf8[pos];
+ }
+
+private:
+ char *utf8;
+
+ void init(const WCHAR *str)
+ {
+ int size = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
+ if (size <= 0)
+ throw _T("Could not convert string to UTF8");
+
+ utf8 = (char *) mir_alloc(size);
+ if (utf8 == NULL)
+ throw _T("mir_alloc returned NULL");
+
+ WideCharToMultiByte(CP_UTF8, 0, str, -1, utf8, size, NULL, NULL);
+ }
+};
+
+
+
+class Utf8ToTchar
+{
+public:
+ Utf8ToTchar(const char *str) : tchar(NULL)
+ {
+ if (str == NULL)
+ return;
+
+ int size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+ if (size <= 0)
+ throw _T("Could not convert string to WCHAR");
+
+ WCHAR *tmp = (WCHAR *) mir_alloc(size * sizeof(WCHAR));
+ if (tmp == NULL)
+ throw _T("mir_alloc returned NULL");
+
+ MultiByteToWideChar(CP_UTF8, 0, str, -1, tmp, size);
+
+#ifdef UNICODE
+
+ tchar = tmp;
+
+#else
+
+ size = WideCharToMultiByte(CP_ACP, 0, tmp, -1, NULL, 0, NULL, NULL);
+ if (size <= 0)
+ {
+ mir_free(tmp);
+ throw _T("Could not convert string to ACP");
+ }
+
+ tchar = (TCHAR *) mir_alloc(size * sizeof(char));
+ if (tchar == NULL)
+ {
+ mir_free(tmp);
+ throw _T("mir_alloc returned NULL");
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, tmp, -1, tchar, size, NULL, NULL);
+
+ mir_free(tmp);
+
+#endif
+ }
+
+ ~Utf8ToTchar()
+ {
+ if (tchar != NULL)
+ mir_free(tchar);
+ }
+
+ TCHAR *detach()
+ {
+ TCHAR *ret = tchar;
+ tchar = NULL;
+ return ret;
+ }
+
+ TCHAR * get() const
+ {
+ return tchar;
+ }
+
+ operator TCHAR *() const
+ {
+ return tchar;
+ }
+
+ TCHAR & operator[](int pos)
+ {
+ return tchar[pos];
+ }
+
+private:
+ TCHAR *tchar;
+};
+
+
+class CharToTchar
+{
+public:
+ CharToTchar(const char *str) : tchar(NULL)
+ {
+ if (str == NULL)
+ return;
+
+#ifdef UNICODE
+
+ tchar = mir_a2u(str);
+
+#else
+
+ tchar = str;
+
+#endif
+ }
+
+
+ ~CharToTchar()
+ {
+#ifdef UNICODE
+ if (tchar != NULL)
+ mir_free(tchar);
+#endif
+ }
+
+ TCHAR *detach()
+ {
+#ifdef UNICODE
+ TCHAR *ret = tchar;
+#else
+ TCHAR *ret = (tchar == NULL ? NULL : mir_strdup(tchar));
+#endif
+
+ tchar = NULL;
+ return ret;
+ }
+
+ const TCHAR * get() const
+ {
+ return tchar;
+ }
+
+ operator const TCHAR *() const
+ {
+ return tchar;
+ }
+
+ const TCHAR & operator[](int pos) const
+ {
+ return tchar[pos];
+ }
+
+private:
+#ifdef UNICODE
+ TCHAR *tchar;
+#else
+ const TCHAR *tchar;
+#endif
+};
+
+
+class WcharToTchar
+{
+public:
+ WcharToTchar(const WCHAR *str) : tchar(NULL)
+ {
+ if (str == NULL)
+ return;
+
+#ifdef UNICODE
+
+ tchar = str;
+
+#else
+
+ tchar = mir_u2a(str);
+
+#endif
+ }
+
+
+ ~WcharToTchar()
+ {
+#ifndef UNICODE
+ if (tchar != NULL)
+ mir_free(tchar);
+#endif
+ }
+
+ TCHAR *detach()
+ {
+#ifdef UNICODE
+ TCHAR *ret = (tchar == NULL ? NULL : mir_wstrdup(tchar));
+#else
+ TCHAR *ret = tchar;
+#endif
+
+ tchar = NULL;
+ return ret;
+ }
+
+ const TCHAR * get() const
+ {
+ return tchar;
+ }
+
+ operator const TCHAR *() const
+ {
+ return tchar;
+ }
+
+ const TCHAR & operator[](int pos) const
+ {
+ return tchar[pos];
+ }
+
+private:
+#ifdef UNICODE
+ const TCHAR *tchar;
+#else
+ TCHAR *tchar;
+#endif
+};
+
+
+
+
+class CharToWchar
+{
+public:
+ CharToWchar(const char *str) : wchar(NULL)
+ {
+ if (str == NULL)
+ return;
+
+ wchar = mir_a2u(str);
+ }
+
+
+ ~CharToWchar()
+ {
+ if (wchar != NULL)
+ mir_free(wchar);
+ }
+
+ WCHAR *detach()
+ {
+ WCHAR *ret = wchar;
+ wchar = NULL;
+ return ret;
+ }
+
+ const WCHAR * get() const
+ {
+ return wchar;
+ }
+
+ operator const WCHAR *() const
+ {
+ return wchar;
+ }
+
+ const WCHAR & operator[](int pos) const
+ {
+ return wchar[pos];
+ }
+
+private:
+ WCHAR *wchar;
+};
+
+
+
+class TcharToChar
+{
+public:
+ TcharToChar(const TCHAR *str) : val(NULL)
+ {
+ if (str == NULL)
+ return;
+
+#ifdef UNICODE
+
+ val = mir_u2a(str);
+
+#else
+
+ val = str;
+
+#endif
+ }
+
+
+ ~TcharToChar()
+ {
+#ifdef UNICODE
+ if (val != NULL)
+ mir_free(val);
+#endif
+ }
+
+ char *detach()
+ {
+#ifdef UNICODE
+ char *ret = val;
+#else
+ char *ret = (val == NULL ? NULL : mir_strdup(val));
+#endif
+
+ val = NULL;
+ return ret;
+ }
+
+ const char * get() const
+ {
+ return val;
+ }
+
+ operator const char *() const
+ {
+ return val;
+ }
+
+ const char & operator[](int pos) const
+ {
+ return val[pos];
+ }
+
+private:
+#ifdef UNICODE
+ char *val;
+#else
+ const char *val;
+#endif
+};
+
+
+class TcharToWchar
+{
+public:
+ TcharToWchar(const TCHAR *str) : val(NULL)
+ {
+ if (str == NULL)
+ return;
+
+#ifdef UNICODE
+
+ val = str;
+
+#else
+
+ val = mir_a2u(str);
+
+#endif
+ }
+
+
+ ~TcharToWchar()
+ {
+#ifndef UNICODE
+ if (val != NULL)
+ mir_free(val);
+#endif
+ }
+
+ WCHAR *detach()
+ {
+#ifdef UNICODE
+ WCHAR *ret = (val == NULL ? NULL : mir_wstrdup(val));
+#else
+ WCHAR *ret = val;
+#endif
+
+ val = NULL;
+ return ret;
+ }
+
+ const WCHAR * get() const
+ {
+ return val;
+ }
+
+ operator const WCHAR *() const
+ {
+ return val;
+ }
+
+ const WCHAR & operator[](int pos) const
+ {
+ return val[pos];
+ }
+
+private:
+#ifdef UNICODE
+ const WCHAR *val;
+#else
+ WCHAR *val;
+#endif
+};
+
+
+
+
+class BstrToTchar
+{
+public:
+ BstrToTchar() : bstr(NULL)
+#ifndef UNICODE
+ , tchar(NULL)
+#endif
+ {
+ }
+
+ BstrToTchar(const WCHAR *str) : bstr(NULL)
+#ifndef UNICODE
+ , tchar(NULL)
+#endif
+ {
+ if (str == NULL)
+ return;
+
+ bstr = SysAllocString(str);
+ }
+
+ BstrToTchar(const char *str) : bstr(NULL)
+#ifndef UNICODE
+ , tchar(NULL)
+#endif
+ {
+ if (str == NULL)
+ return;
+
+ bstr = SysAllocString(CharToWchar(str));
+ }
+
+
+ ~BstrToTchar()
+ {
+ if (bstr != NULL)
+ SysFreeString(bstr);
+
+#ifndef UNICODE
+ freeTchar();
+#endif
+ }
+
+ BSTR detach()
+ {
+ BSTR ret = bstr;
+ bstr = NULL;
+ return ret;
+ }
+
+ operator const TCHAR *()
+ {
+#ifdef UNICODE
+
+ return bstr;
+
+#else
+
+ if (tchar == NULL)
+ tchar = mir_u2a(bstr);
+
+ return tchar;
+
+#endif
+ }
+
+ operator const BSTR() const
+ {
+ return bstr;
+ }
+
+ operator BSTR *()
+ {
+#ifndef UNICODE
+ freeTchar();
+#endif
+
+ return &bstr;
+ }
+
+private:
+ BSTR bstr;
+
+#ifndef UNICODE
+
+ TCHAR *tchar;
+
+ void freeTchar()
+ {
+ if (tchar != NULL)
+ {
+ mir_free(tchar);
+ tchar = NULL;
+ }
+ }
+
+#endif
+};
+
+
+#endif // __UTF8_HELPERS_H__
|