summaryrefslogtreecommitdiff
path: root/plugins/utils/templates.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/utils/templates.cpp')
-rw-r--r--plugins/utils/templates.cpp476
1 files changed, 476 insertions, 0 deletions
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);
+}
+
+