summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorRozhuk Ivan <rozhuk.im@gmail.com>2014-11-26 17:36:16 +0000
committerRozhuk Ivan <rozhuk.im@gmail.com>2014-11-26 17:36:16 +0000
commitb50174e6291e7baf81601a224b736e72c00e752e (patch)
treec5e34fd14e8823ef3b0dcf143f2110e536394a4b /plugins
parent071796c791c3c3e3ba0c964966d108efb054ddf2 (diff)
QuickMessages code clean, fix mem leaks.
git-svn-id: http://svn.miranda-ng.org/main/trunk@11098 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins')
-rw-r--r--plugins/QuickMessages/src/Utils.cpp1182
1 files changed, 577 insertions, 605 deletions
diff --git a/plugins/QuickMessages/src/Utils.cpp b/plugins/QuickMessages/src/Utils.cpp
index a32da0453b..f41c866600 100644
--- a/plugins/QuickMessages/src/Utils.cpp
+++ b/plugins/QuickMessages/src/Utils.cpp
@@ -1,605 +1,577 @@
-/*
-Quick Messages plugin for Miranda IM
-
-Copyright (C) 2008 Danil Mozhar
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "quickmessages.h"
-
-ListData* ButtonsList[100];
-
-SortedList* QuickList=NULL;
-
-typedef void (*ItemDestuctor)(void*);
-
-int sstSortButtons(const void * vmtbi1, const void * vmtbi2)
-{
- ButtonData * mtbi1=(ButtonData *)*((ButtonData ** )vmtbi1);
- ButtonData * mtbi2=(ButtonData *)*((ButtonData ** )vmtbi2);
- if (mtbi1==NULL || mtbi2==NULL) return (mtbi1-mtbi2);
- return mtbi1->dwPos-mtbi2->dwPos;
-}
-
-int sstQuickSortButtons(const void * vmtbi1, const void * vmtbi2)
-{
- QuickData * mtbi1=(QuickData *)*((QuickData ** )vmtbi1);
- QuickData * mtbi2=(QuickData *)*((QuickData ** )vmtbi2);
- if (mtbi1==NULL || mtbi2==NULL) return (mtbi1-mtbi2);
- return mtbi1->dwPos-mtbi2->dwPos;
-}
-
-
-int sstOpSortButtons(const void * vmtbi1, const void * vmtbi2)
-{
- ButtonData * mtbi1=(ButtonData *)*((ButtonData ** )vmtbi1);
- ButtonData * mtbi2=(ButtonData *)*((ButtonData ** )vmtbi2);
- if (mtbi1==NULL || mtbi2==NULL) return (mtbi1-mtbi2);
- return mtbi1->dwOPPos-mtbi2->dwOPPos;
-}
-
-
-void li_ListDestruct(SortedList *pList, ItemDestuctor pItemDestructor)
-{
- int i=0;
- if (!pList) return;
- for (i=0; i<pList->realCount; i++) pItemDestructor(pList->items[i]);
- List_Destroy(pList);
- mir_free(pList);
-}
-
-void li_RemoveDestruct(SortedList *pList, int index, ItemDestuctor pItemDestructor)
-{
- if (index>=0 && index<pList->realCount)
- {
- pItemDestructor(pList->items[index]);
- List_Remove(pList, index);
- }
-}
-
-void li_RemovePtrDestruct(SortedList *pList, void * ptr, ItemDestuctor pItemDestructor)
-{
- if (List_RemovePtr(pList, ptr))
- pItemDestructor(ptr);
-}
-
-void li_SortList(SortedList *pList, FSortFunc pSortFunct)
-{
- FSortFunc pOldSort=pList->sortFunc;
- int i;
- if (!pSortFunct) pSortFunct=pOldSort;
- pList->sortFunc=NULL;
- for (i=0; i<pList->realCount-1; i++)
- if (pOldSort(pList->items[i],pList->items[i+1])<0)
- {
- void * temp=pList->items[i];
- pList->items[i]=pList->items[i+1];
- pList->items[i+1]=temp;
- i--;
- if (i>0) i--;
- }
- pList->sortFunc=pOldSort;
-}
-
-void li_ZeroQuickList(SortedList *pList)
-{
- int i;
- for (i=0; i<pList->realCount; i++)
- {
- QuickData * qd=(QuickData *)pList->items[i];
- qd->dwPos=0;
- qd->bIsService=0;
- qd->ptszValue=NULL;
- qd->ptszValueName=NULL;
- List_Remove(pList, i);
- i--;
- }
-}
-
-static void listdestructor(void * input)
-{
- ButtonData * cbdi=(ButtonData *)input;
-
- if(cbdi->pszName!=cbdi->pszOpName)
- {
- if(cbdi->pszOpName)
- mir_free(cbdi->pszOpName);
- if(cbdi->pszName)
- mir_free(cbdi->pszName);
- }
- else if(cbdi->pszName)
- mir_free(cbdi->pszName);
-
- if(cbdi->pszValue!=cbdi->pszOpValue)
- {
- if(cbdi->pszOpValue)
- mir_free(cbdi->pszOpValue);
- if(cbdi->pszValue)
- mir_free(cbdi->pszValue);
- }
- else if(cbdi->pszValue)
- mir_free(cbdi->pszValue);
-
- mir_free(cbdi);
-}
-
-void RemoveMenuEntryNode(SortedList *pList, int index)
-{
- li_RemoveDestruct(pList,index,listdestructor);
-}
-
-void DestroyButton(int listnum)
-{
- int i=listnum;
- ListData* ld=ButtonsList[listnum];
-
- if(ld->ptszButtonName) mir_free(ld->ptszButtonName);
-
- if(ld->ptszOPQValue!=ld->ptszQValue)
- if(ld->ptszOPQValue) mir_free(ld->ptszOPQValue);
-
- if (ld->ptszQValue) mir_free(ld->ptszQValue);
-
- li_ListDestruct((SortedList*)ld->sl,listdestructor);
-
-
- mir_free(ld);
- ButtonsList[i]=NULL;
- while(ButtonsList[i+1])
- {
- ButtonsList[i]=ButtonsList[i+1];
- ButtonsList[i+1]=NULL;
- i++;
- }
-}
-
-
-void SaveModuleSettings(int buttonnum,ButtonData* bd)
-{
- char szMEntry[256]={'\0'};
-
- mir_snprintf(szMEntry,255,"EntryName_%u_%u",buttonnum,bd->dwPos);
- db_set_ts(NULL, PLGNAME,szMEntry,bd->pszName );
-
- mir_snprintf(szMEntry,255,"EntryValue_%u_%u",buttonnum,bd->dwPos);
- if(bd->pszValue)
- db_set_ts(NULL, PLGNAME,szMEntry,bd->pszValue );
- else
- db_unset(NULL, PLGNAME,szMEntry);
-
- mir_snprintf(szMEntry,255,"EntryRel_%u_%u",buttonnum,bd->dwPos);
- db_set_b(NULL, PLGNAME,szMEntry,bd->fEntryType );
-
- mir_snprintf(szMEntry,255,"EntryToQMenu_%u_%u",buttonnum,bd->dwPos);
- db_set_b(NULL, PLGNAME,szMEntry,bd->bInQMenu);
-
- mir_snprintf(szMEntry,255,"EntryIsServiceName_%u_%u",buttonnum,bd->dwPos);
- db_set_b(NULL, PLGNAME,szMEntry,bd->bIsServName);
-}
-
-void CleanSettings(int buttonnum,int from)
-{
- char szMEntry[256]={'\0'};
- DBVARIANT dbv = {0};
- if(from==-1){
- mir_snprintf(szMEntry,255,"ButtonName_%u",buttonnum);
- db_unset(NULL, PLGNAME,szMEntry);
- mir_snprintf(szMEntry,255,"ButtonValue_%u",buttonnum);
- db_unset(NULL, PLGNAME,szMEntry);
- mir_snprintf(szMEntry,255,"RCEntryIsServiceName_%u",buttonnum);
- db_unset(NULL, PLGNAME,szMEntry);
- }
-
- mir_snprintf(szMEntry,255,"EntryName_%u_%u",buttonnum,from);
- while(!db_get_ts(NULL, PLGNAME,szMEntry,&dbv)) {
- db_unset(NULL, PLGNAME,szMEntry);
- mir_snprintf(szMEntry,255,"EntryValue_%u_%u",buttonnum,from);
- db_unset(NULL, PLGNAME,szMEntry);
- mir_snprintf(szMEntry,255,"EntryRel_%u_%u",buttonnum,from);
- db_unset(NULL, PLGNAME,szMEntry);
- mir_snprintf(szMEntry,255,"EntryToQMenu_%u_%u",buttonnum,from);
- db_unset(NULL, PLGNAME,szMEntry);
- mir_snprintf(szMEntry,255,"EntryIsServiceName_%u_%u",buttonnum,from);
- db_unset(NULL, PLGNAME,szMEntry);
-
- mir_snprintf(szMEntry,255,"EntryName_%u_%u",buttonnum,++from);
- }
- db_free(&dbv);
-}
-
-BYTE getEntryByte(int buttonnum,int entrynum,BOOL mode)
-{
- char szMEntry[256]={'\0'};
- if (mode==0)
- mir_snprintf(szMEntry,255,"EntryToQMenu_%u_%u",buttonnum,entrynum);
- else if (mode==1)
- mir_snprintf(szMEntry,255,"EntryRel_%u_%u",buttonnum,entrynum);
- else if (mode==2)
- mir_snprintf(szMEntry,255,"EntryIsServiceName_%u_%u",buttonnum,entrynum);
- else if (mode==3)
- mir_snprintf(szMEntry,255,"RCEntryIsServiceName_%u",buttonnum);
- return db_get_b(NULL, PLGNAME,szMEntry, 0);
-}
-
-static HANDLE AddIcon(char* szIcoName)
-{
- TCHAR tszPath[MAX_PATH];
- GetModuleFileName(hinstance, tszPath, SIZEOF(tszPath));
-
- SKINICONDESC sid = { sizeof(sid) };
- sid.flags = SIDF_PATH_TCHAR;
- sid.pszSection = "Quick Messages";
- sid.cx = sid.cy = 16;
- sid.pszDescription = szIcoName;
- sid.pszName = szIcoName;
- sid.ptszDefaultFile = tszPath;
- sid.iDefaultIndex = -IDI_QICON;
- return Skin_AddIcon(&sid);
-}
-
-DWORD BalanceButtons(int buttonsWas, int buttonsNow)
-{
- if ( !ServiceExists(MS_BB_ADDBUTTON)) {
- BBButton bb = { sizeof(bb) };
- bb.pszModuleName = PLGNAME;
-
- while (buttonsWas > buttonsNow) {
- bb.dwButtonID = --buttonsWas;
- CallService(MS_BB_REMOVEBUTTON, 0, (LPARAM)&bb);
- }
-
- while (buttonsWas < buttonsNow) {
- if (ServiceExists(MS_BB_ADDBUTTON)) {
- char iconname[40];
- mir_snprintf(iconname, SIZEOF(iconname), LPGEN("Quick Messages Button %u"), buttonsWas);
- bb.bbbFlags = BBBF_ISIMBUTTON | BBBF_ISCHATBUTTON | BBBF_ISLSIDEBUTTON;
- bb.dwButtonID = buttonsWas++;
- bb.dwDefPos = 300+buttonsWas;
- bb.hIcon = AddIcon(iconname);
- CallService(MS_BB_ADDBUTTON, 0, (LPARAM)&bb);
- }
- }
- }
- return buttonsNow;
-}
-
-
-void InitButtonsList()
-{
- int i,j,k=0;
- QuickList=List_Create(0,1);
- for(i=0;i<g_iButtonsCount;i++)
- {
- TCHAR* pszBName=NULL;
- ListData* ld=NULL;
- if (!(pszBName=getMenuEntry(i,0,3))) {
- g_iButtonsCount=i;
- db_set_b(NULL, PLGNAME,"ButtonsCount", (BYTE)g_iButtonsCount);
- break;}
-
- ld = (ListData *)mir_alloc(sizeof(ListData));
- ButtonsList[i]=ld;
- ld->sl=List_Create(0,1);
- ld->ptszQValue=ld->ptszOPQValue=getMenuEntry(i,0,2);
- ld->ptszButtonName=pszBName;
- ld->dwPos=ld->dwOPPos=i;
- ld->dwOPFlags=0;
- ld->bIsServName=ld->bIsOpServName=getEntryByte(i,0,3);
- for(j=0;;j++)
- {
- TCHAR* pszEntry=NULL;
- ButtonData *bd=NULL;
-
- if (!(pszEntry=getMenuEntry(i,j,0)))
- break;
-
- bd = (ButtonData *)mir_alloc(sizeof(ButtonData));
- memset(bd,0,sizeof(ButtonData));
-
- bd->dwPos=bd->dwOPPos=j;
- bd->pszName=bd->pszOpName=pszEntry;
- bd->pszValue=bd->pszOpValue=getMenuEntry(i,j,1);
- bd->fEntryType=bd->fEntryOpType=getEntryByte(i,j,1);
- bd->bInQMenu=bd->bOpInQMenu=getEntryByte(i,j,0);
- bd->bIsServName=bd->bIsOpServName=getEntryByte(i,j,2);
- if(bd->bInQMenu){
- QuickData* qd = (QuickData *)mir_alloc(sizeof(QuickData));
- qd->dwPos=k++;
- qd->ptszValue=bd->pszValue;
- qd->ptszValueName=bd->pszName;
- List_InsertPtr(QuickList,qd);
- }
- List_InsertPtr((SortedList*)ld->sl,bd);
- }
- }
-}
-
-void DestructButtonsList()
-{
- int i=0;
- // for ( i=0; i < g_iButtonsCount; i++ )
- while(ButtonsList[i])
- {
- li_ListDestruct(ButtonsList[i]->sl,listdestructor);
- mir_free(ButtonsList[i]->ptszButtonName);
- if(ButtonsList[i]->ptszOPQValue!=ButtonsList[i]->ptszQValue)
- if (ButtonsList[i]->ptszOPQValue) mir_free(ButtonsList[i]->ptszOPQValue);
- if (ButtonsList[i]->ptszQValue) mir_free(ButtonsList[i]->ptszQValue);
- i++;
- }
- if(QuickList)
- {
- li_ZeroQuickList(QuickList);
- List_Destroy(QuickList);
- }
-}
-
-TCHAR* getMenuEntry(int buttonnum,int entrynum,BYTE mode)
-{
- TCHAR* buffer=NULL;
- char szMEntry[256]={'\0'};
- DBVARIANT dbv = {0};
-
- if(mode==0)
- mir_snprintf(szMEntry,255,"EntryName_%u_%u",buttonnum,entrynum);
- else if (mode==1)
- mir_snprintf(szMEntry,255,"EntryValue_%u_%u",buttonnum,entrynum);
- else if (mode==2)
- mir_snprintf(szMEntry,255,"ButtonValue_%u",buttonnum);
- else if (mode==3)
- mir_snprintf(szMEntry,255,"ButtonName_%u",buttonnum);
-
-
- db_get_ts(NULL, PLGNAME,szMEntry, &dbv);
-
- if(dbv.ptszVal&&_tcslen(dbv.ptszVal))
- {
- buffer=mir_tstrdup(dbv.ptszVal);
- db_free(&dbv);
- }
-
- return buffer;
-}
-
-int RegisterCustomButton(WPARAM wParam,LPARAM lParam)
-{
- if ( !ServiceExists(MS_BB_ADDBUTTON))
- return 1;
-
- for (int i=0; i < g_iButtonsCount; i++) {
- ListData* ld = ButtonsList[i];
-
- char iconname[40];
- mir_snprintf(iconname, SIZEOF(iconname), LPGEN("Quick Messages Button %u"), i);
-
- BBButton bbd = { sizeof(bbd) };
- bbd.bbbFlags = BBBF_ISIMBUTTON | BBBF_ISCHATBUTTON | BBBF_ISLSIDEBUTTON;
- bbd.dwButtonID = i;
- bbd.dwDefPos = 320+i;
- bbd.hIcon = AddIcon(iconname);
- bbd.pszModuleName = PLGNAME;
- bbd.ptszTooltip = ld->ptszButtonName;
- CallService(MS_BB_ADDBUTTON, 0, (LPARAM)&bbd);
- }
- return 0;
-}
-
-TCHAR* ParseString(MCONTACT hContact,TCHAR* ptszQValIn,TCHAR* ptszText,TCHAR* ptszClip,int QVSize,int TextSize ,int ClipSize)
-{
- int i=0,iOffset=0,iCount=0;
- TCHAR* tempPointer=NULL;
- TCHAR* ptszQValue=_tcsdup(ptszQValIn);
- TCHAR* tempQValue=ptszQValue;
- TCHAR varstr=_T('%');
-
- if(TextSize&&ptszText[TextSize-1]=='\0') TextSize--;
- if(ClipSize&&ptszClip[ClipSize-1]=='\0') ClipSize--;
-
- if (!_tcschr(ptszQValue,varstr))
- return ptszQValue;
-
- while(ptszQValue[i]) {
- if(ptszQValue[i]=='%') {
- switch(ptszQValue[i+1]) {
- case 't':
- {
- TCHAR* p=NULL;
- p = (TCHAR *)realloc(tempQValue, (QVSize + TextSize+1)*sizeof(TCHAR));
- if(p){
- int test=0;
- i=iOffset;
- tempQValue=ptszQValue=p;
-
- tempPointer = (TCHAR *)memmove(ptszQValue + i + TextSize, ptszQValue + i + 2, (QVSize - i - 1)*sizeof(TCHAR));
-
- if(TextSize) memcpy(ptszQValue+i, ptszText, TextSize*sizeof(TCHAR));
-
- QVSize+=(TextSize-2);
-
- ptszQValue[QVSize]='\0';
-
- if (!_tcschr(ptszQValue,varstr))
- return ptszQValue;
-
- ptszQValue=tempPointer;
- iOffset+=TextSize-1;
- i=-1;
- }
- }break;
-
- case 'c':
- {
- TCHAR* p=NULL;
- p = (TCHAR *)realloc(tempQValue, (QVSize + ClipSize + 1)*sizeof(TCHAR));
- if(p){
- i=iOffset;
- tempQValue=ptszQValue=p;
-
- tempPointer = (TCHAR *)memmove(ptszQValue + i + ClipSize, ptszQValue + i + 2, (QVSize - i - 1)*sizeof(TCHAR));
- if(ClipSize) memcpy(ptszQValue+i, ptszClip, ClipSize*sizeof(TCHAR));
- QVSize+=(ClipSize-2);
-
- ptszQValue[QVSize]='\0';
-
- if (!_tcschr(ptszQValue,varstr))
- return ptszQValue;
-
- ptszQValue=tempPointer;
- iOffset+=ClipSize-1;
- i=-1;
- }
- }break;
-
- case 'P':
- {
- TCHAR* p=NULL;
- int NameLenght=0;
- TCHAR* ptszName=NULL;
-
- ptszName=mir_a2u(GetContactProto(hContact));
-
- NameLenght=(int)_tcslen(ptszName);
-
- p = (TCHAR *)realloc(tempQValue, (QVSize + NameLenght + 1)*sizeof(TCHAR));
- if(p){
- i=iOffset;
- tempQValue=ptszQValue=p;
-
- tempPointer = (TCHAR *)memmove(ptszQValue + i + NameLenght, ptszQValue + i + 2, (QVSize - i - 1)*sizeof(TCHAR));
- if(NameLenght) memcpy(ptszQValue+i, ptszName, NameLenght*sizeof(TCHAR));
- QVSize+=(NameLenght-2);
-
- ptszQValue[QVSize]='\0';
- if(ptszName) mir_free(ptszName);
-
- if (!_tcschr(ptszQValue,varstr))
- return ptszQValue;
-
- ptszQValue=tempPointer;
- iOffset+=NameLenght-1;
- i=-1;
- }
- }break;
-
- case 'n':
- {
- TCHAR* p=NULL;
- int NameLenght=0;
- TCHAR* ptszName=NULL;
-
- ptszName=(TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR);
- NameLenght=(int)_tcslen(ptszName);
- p = (TCHAR *)realloc(tempQValue, (QVSize + NameLenght + 1)*sizeof(TCHAR));
- if(p){
- i=iOffset;
- tempQValue=ptszQValue=p;
-
- tempPointer = (TCHAR *)memmove(ptszQValue + i + NameLenght, ptszQValue + i + 2, (QVSize - i - 1)*sizeof(TCHAR));
- if(NameLenght)memcpy(ptszQValue+i, ptszName, NameLenght*sizeof(TCHAR));
- QVSize+=(NameLenght-2);
-
- //if(ptszName) mir_free(ptszName);
-
- ptszQValue[QVSize]='\0';
-
- if (!_tcschr(ptszQValue,varstr))
- return ptszQValue;
-
- ptszQValue=tempPointer;
- iOffset+=NameLenght-1;
- i=-1;
- }
- }break;
- case 'F':
- {
- TCHAR* p=NULL;
- int NameLenght=0;
- TCHAR* ptszName=NULL;
- CONTACTINFO ci;
- ZeroMemory(&ci,sizeof(CONTACTINFO));
- ci.cbSize = sizeof(CONTACTINFO);
- ci.hContact = hContact;
-
- ci.dwFlag =CNF_FIRSTNAME|CNF_UNICODE;
-
- ci.szProto=GetContactProto(hContact);
- if (!CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)&&ci.pszVal){
- NameLenght=(int)_tcslen(ci.pszVal);
- ptszName=ci.pszVal;
- }
- p = (TCHAR *)realloc(tempQValue, (QVSize + NameLenght + 1)*sizeof(TCHAR));
- if(p){
- i=iOffset;
- tempQValue=ptszQValue=p;
-
- tempPointer = (TCHAR *)memmove(ptszQValue + i + NameLenght, ptszQValue + i + 2, (QVSize - i - 1)*sizeof(TCHAR));
- if(NameLenght)memcpy(ptszQValue+i, ptszName, NameLenght*sizeof(TCHAR));
- QVSize+=(NameLenght-2);
-
- if(ptszName) mir_free(ptszName);
-
- ptszQValue[QVSize]='\0';
-
- if (!_tcschr(ptszQValue,varstr))
- return ptszQValue;
-
- ptszQValue=tempPointer;
- iOffset+=NameLenght-1;
- i=-1;
- }
- }break;
- case 'L':
- {
- TCHAR* p=NULL;
- int NameLenght=0;
- TCHAR* ptszName=NULL;
- CONTACTINFO ci;
- ZeroMemory(&ci,sizeof(CONTACTINFO));
- ci.cbSize = sizeof(CONTACTINFO);
- ci.hContact = hContact;
- ci.szProto=GetContactProto(hContact);
-
- ci.dwFlag =CNF_LASTNAME|CNF_UNICODE;
-
- if (!CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)&&ci.pszVal){
- NameLenght=(int)_tcslen(ci.pszVal);
- ptszName=ci.pszVal;
- }
- p = (TCHAR *)realloc(tempQValue, (QVSize + NameLenght + 1)*sizeof(TCHAR));
- if(p){
- i=iOffset;
- tempQValue=ptszQValue=p;
-
- tempPointer = (TCHAR *)memmove(ptszQValue + i + NameLenght, ptszQValue + i + 2, (QVSize - i - 1)*sizeof(TCHAR));
- if(NameLenght)memcpy(ptszQValue+i, ptszName, NameLenght*sizeof(TCHAR));
- QVSize+=(NameLenght-2);
-
- ptszQValue[QVSize]='\0';
-
- if (!_tcschr(ptszQValue,varstr))
- return ptszQValue;
-
- ptszQValue=tempPointer;
- iOffset+=NameLenght-1;
- i=-1;
- }
- }break;
- }
- }
- iOffset++;
- i++;
- }
- return ptszQValue;
-}
+/*
+Quick Messages plugin for Miranda IM
+
+Copyright (C) 2008 Danil Mozhar
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "quickmessages.h"
+
+ListData* ButtonsList[100];
+
+SortedList* QuickList=NULL;
+
+typedef void (*ItemDestuctor)(void*);
+
+int sstSortButtons(const void * vmtbi1, const void * vmtbi2)
+{
+ ButtonData * mtbi1=(ButtonData *)*((ButtonData ** )vmtbi1);
+ ButtonData * mtbi2=(ButtonData *)*((ButtonData ** )vmtbi2);
+ if (mtbi1==NULL || mtbi2==NULL) return (mtbi1-mtbi2);
+ return mtbi1->dwPos-mtbi2->dwPos;
+}
+
+int sstQuickSortButtons(const void * vmtbi1, const void * vmtbi2)
+{
+ QuickData * mtbi1=(QuickData *)*((QuickData ** )vmtbi1);
+ QuickData * mtbi2=(QuickData *)*((QuickData ** )vmtbi2);
+ if (mtbi1==NULL || mtbi2==NULL) return (mtbi1-mtbi2);
+ return mtbi1->dwPos-mtbi2->dwPos;
+}
+
+
+int sstOpSortButtons(const void * vmtbi1, const void * vmtbi2)
+{
+ ButtonData * mtbi1=(ButtonData *)*((ButtonData ** )vmtbi1);
+ ButtonData * mtbi2=(ButtonData *)*((ButtonData ** )vmtbi2);
+ if (mtbi1==NULL || mtbi2==NULL) return (mtbi1-mtbi2);
+ return mtbi1->dwOPPos-mtbi2->dwOPPos;
+}
+
+
+void li_ListDestruct(SortedList *pList, ItemDestuctor pItemDestructor)
+{
+ int i=0;
+ if (!pList)
+ return;
+ for (i=0; i<pList->realCount; i++)
+ pItemDestructor(pList->items[i]);
+ List_Destroy(pList);
+ mir_free(pList);
+}
+
+void li_RemoveDestruct(SortedList *pList, int index, ItemDestuctor pItemDestructor)
+{
+ if (index>=0 && index<pList->realCount)
+ {
+ pItemDestructor(pList->items[index]);
+ List_Remove(pList, index);
+ }
+}
+
+void li_RemovePtrDestruct(SortedList *pList, void * ptr, ItemDestuctor pItemDestructor)
+{
+ if (List_RemovePtr(pList, ptr))
+ pItemDestructor(ptr);
+}
+
+void li_SortList(SortedList *pList, FSortFunc pSortFunct)
+{
+ FSortFunc pOldSort=pList->sortFunc;
+ int i;
+ if (!pSortFunct) pSortFunct=pOldSort;
+ pList->sortFunc=NULL;
+ for (i=0; i<pList->realCount-1; i++)
+ if (pOldSort(pList->items[i],pList->items[i+1])<0)
+ {
+ void * temp=pList->items[i];
+ pList->items[i]=pList->items[i+1];
+ pList->items[i+1]=temp;
+ i--;
+ if (i>0) i--;
+ }
+ pList->sortFunc=pOldSort;
+}
+
+void li_ZeroQuickList(SortedList *pList)
+{
+ int i;
+ for (i=0; i<pList->realCount; i++)
+ {
+ QuickData * qd=(QuickData *)pList->items[i];
+ qd->dwPos=0;
+ qd->bIsService=0;
+ qd->ptszValue=NULL;
+ qd->ptszValueName=NULL;
+ List_Remove(pList, i);
+ i--;
+ }
+}
+
+static void listdestructor(void * input)
+{
+ ButtonData * cbdi = (ButtonData *)input;
+
+ if(cbdi->pszName != cbdi->pszOpName)
+ mir_free(cbdi->pszOpName);
+ mir_free(cbdi->pszName);
+
+ if(cbdi->pszValue != cbdi->pszOpValue)
+ mir_free(cbdi->pszOpValue);
+ mir_free(cbdi->pszValue);
+
+ mir_free(cbdi);
+}
+
+void RemoveMenuEntryNode(SortedList *pList, int index)
+{
+ li_RemoveDestruct(pList,index,listdestructor);
+}
+
+void DestroyButton(int listnum)
+{
+ int i=listnum;
+ ListData* ld=ButtonsList[listnum];
+
+ mir_free(ld->ptszButtonName);
+ if(ld->ptszOPQValue != ld->ptszQValue)
+ mir_free(ld->ptszOPQValue);
+ mir_free(ld->ptszQValue);
+
+ li_ListDestruct((SortedList*)ld->sl,listdestructor);
+
+ mir_free(ld);
+ ButtonsList[i]=NULL;
+ while(ButtonsList[i+1])
+ {
+ ButtonsList[i]=ButtonsList[i+1];
+ ButtonsList[i+1]=NULL;
+ i++;
+ }
+}
+
+
+void SaveModuleSettings(int buttonnum,ButtonData* bd)
+{
+ char szMEntry[256]={'\0'};
+
+ mir_snprintf(szMEntry,sizeof(szMEntry),"EntryName_%u_%u",buttonnum,bd->dwPos);
+ db_set_ts(NULL, PLGNAME,szMEntry,bd->pszName );
+
+ mir_snprintf(szMEntry,sizeof(szMEntry),"EntryValue_%u_%u",buttonnum,bd->dwPos);
+ if(bd->pszValue)
+ db_set_ts(NULL, PLGNAME,szMEntry,bd->pszValue );
+ else
+ db_unset(NULL, PLGNAME,szMEntry);
+
+ mir_snprintf(szMEntry,sizeof(szMEntry),"EntryRel_%u_%u",buttonnum,bd->dwPos);
+ db_set_b(NULL, PLGNAME,szMEntry,bd->fEntryType );
+
+ mir_snprintf(szMEntry,sizeof(szMEntry),"EntryToQMenu_%u_%u",buttonnum,bd->dwPos);
+ db_set_b(NULL, PLGNAME,szMEntry,bd->bInQMenu);
+
+ mir_snprintf(szMEntry,sizeof(szMEntry),"EntryIsServiceName_%u_%u",buttonnum,bd->dwPos);
+ db_set_b(NULL, PLGNAME,szMEntry,bd->bIsServName);
+}
+
+void CleanSettings(int buttonnum,int from)
+{
+ char szMEntry[256]={'\0'};
+ DBVARIANT dbv = {0};
+ if(from==-1){
+ mir_snprintf(szMEntry,sizeof(szMEntry),"ButtonName_%u",buttonnum);
+ db_unset(NULL, PLGNAME,szMEntry);
+ mir_snprintf(szMEntry,sizeof(szMEntry),"ButtonValue_%u",buttonnum);
+ db_unset(NULL, PLGNAME,szMEntry);
+ mir_snprintf(szMEntry,sizeof(szMEntry),"RCEntryIsServiceName_%u",buttonnum);
+ db_unset(NULL, PLGNAME,szMEntry);
+ }
+
+ mir_snprintf(szMEntry,sizeof(szMEntry),"EntryName_%u_%u",buttonnum,from);
+ while(!db_get_ts(NULL, PLGNAME,szMEntry,&dbv)) {
+ db_unset(NULL, PLGNAME,szMEntry);
+ mir_snprintf(szMEntry,sizeof(szMEntry),"EntryValue_%u_%u",buttonnum,from);
+ db_unset(NULL, PLGNAME,szMEntry);
+ mir_snprintf(szMEntry,sizeof(szMEntry),"EntryRel_%u_%u",buttonnum,from);
+ db_unset(NULL, PLGNAME,szMEntry);
+ mir_snprintf(szMEntry,sizeof(szMEntry),"EntryToQMenu_%u_%u",buttonnum,from);
+ db_unset(NULL, PLGNAME,szMEntry);
+ mir_snprintf(szMEntry,sizeof(szMEntry),"EntryIsServiceName_%u_%u",buttonnum,from);
+ db_unset(NULL, PLGNAME,szMEntry);
+
+ mir_snprintf(szMEntry,sizeof(szMEntry),"EntryName_%u_%u",buttonnum,++from);
+ }
+ db_free(&dbv);
+}
+
+BYTE getEntryByte(int buttonnum,int entrynum,BOOL mode)
+{
+ char szMEntry[256] = {'\0'};
+
+ switch (mode) {
+ case 0:
+ mir_snprintf(szMEntry, sizeof(szMEntry), "EntryToQMenu_%u_%u", buttonnum, entrynum);
+ break;
+ case 1:
+ mir_snprintf(szMEntry, sizeof(szMEntry), "EntryRel_%u_%u", buttonnum, entrynum);
+ break;
+ case 2:
+ mir_snprintf(szMEntry, sizeof(szMEntry), "EntryIsServiceName_%u_%u", buttonnum, entrynum);
+ break;
+ case 3:
+ mir_snprintf(szMEntry, sizeof(szMEntry), "RCEntryIsServiceName_%u", buttonnum);
+ break;
+ }
+ return db_get_b(NULL, PLGNAME, szMEntry, 0);
+}
+
+static HANDLE AddIcon(char* szIcoName)
+{
+ TCHAR tszPath[MAX_PATH];
+ GetModuleFileName(hinstance, tszPath, SIZEOF(tszPath));
+
+ SKINICONDESC sid = { sizeof(sid) };
+ sid.flags = SIDF_PATH_TCHAR;
+ sid.pszSection = "Quick Messages";
+ sid.cx = sid.cy = 16;
+ sid.pszDescription = szIcoName;
+ sid.pszName = szIcoName;
+ sid.ptszDefaultFile = tszPath;
+ sid.iDefaultIndex = -IDI_QICON;
+ return Skin_AddIcon(&sid);
+}
+
+DWORD BalanceButtons(int buttonsWas, int buttonsNow)
+{
+ if ( !ServiceExists(MS_BB_ADDBUTTON)) {
+ BBButton bb = { sizeof(bb) };
+ bb.pszModuleName = PLGNAME;
+
+ while (buttonsWas > buttonsNow) {
+ bb.dwButtonID = --buttonsWas;
+ CallService(MS_BB_REMOVEBUTTON, 0, (LPARAM)&bb);
+ }
+
+ while (buttonsWas < buttonsNow) {
+ if (ServiceExists(MS_BB_ADDBUTTON)) {
+ char iconname[40];
+ mir_snprintf(iconname, SIZEOF(iconname), LPGEN("Quick Messages Button %u"), buttonsWas);
+ bb.bbbFlags = BBBF_ISIMBUTTON | BBBF_ISCHATBUTTON | BBBF_ISLSIDEBUTTON;
+ bb.dwButtonID = buttonsWas++;
+ bb.dwDefPos = 300+buttonsWas;
+ bb.hIcon = AddIcon(iconname);
+ CallService(MS_BB_ADDBUTTON, 0, (LPARAM)&bb);
+ }
+ }
+ }
+ return buttonsNow;
+}
+
+
+void InitButtonsList()
+{
+ int i,j,k=0;
+ QuickList=List_Create(0,1);
+ for(i=0;i<g_iButtonsCount;i++)
+ {
+ TCHAR* pszBName=NULL;
+ ListData* ld=NULL;
+ if (!(pszBName=getMenuEntry(i,0,3))) {
+ g_iButtonsCount=i;
+ db_set_b(NULL, PLGNAME,"ButtonsCount", (BYTE)g_iButtonsCount);
+ break;}
+
+ ld = (ListData *)mir_alloc(sizeof(ListData));
+ ButtonsList[i]=ld;
+ ld->sl=List_Create(0,1);
+ ld->ptszQValue=ld->ptszOPQValue=getMenuEntry(i,0,2);
+ ld->ptszButtonName=pszBName;
+ ld->dwPos=ld->dwOPPos=i;
+ ld->dwOPFlags=0;
+ ld->bIsServName=ld->bIsOpServName=getEntryByte(i,0,3);
+ for(j=0;;j++)
+ {
+ TCHAR* pszEntry=NULL;
+ ButtonData *bd=NULL;
+
+ if (!(pszEntry=getMenuEntry(i,j,0)))
+ break;
+
+ bd = (ButtonData *)mir_alloc(sizeof(ButtonData));
+ memset(bd,0,sizeof(ButtonData));
+
+ bd->dwPos=bd->dwOPPos=j;
+ bd->pszName=bd->pszOpName=pszEntry;
+ bd->pszValue=bd->pszOpValue=getMenuEntry(i,j,1);
+ bd->fEntryType=bd->fEntryOpType=getEntryByte(i,j,1);
+ bd->bInQMenu=bd->bOpInQMenu=getEntryByte(i,j,0);
+ bd->bIsServName=bd->bIsOpServName=getEntryByte(i,j,2);
+ if(bd->bInQMenu){
+ QuickData* qd = (QuickData *)mir_alloc(sizeof(QuickData));
+ qd->dwPos=k++;
+ qd->ptszValue=bd->pszValue;
+ qd->ptszValueName=bd->pszName;
+ List_InsertPtr(QuickList,qd);
+ }
+ List_InsertPtr((SortedList*)ld->sl,bd);
+ }
+ }
+}
+
+void DestructButtonsList()
+{
+ int i=0;
+ // for ( i=0; i < g_iButtonsCount; i++ )
+ while(ButtonsList[i])
+ {
+ li_ListDestruct(ButtonsList[i]->sl,listdestructor);
+ mir_free(ButtonsList[i]->ptszButtonName);
+ if(ButtonsList[i]->ptszOPQValue!=ButtonsList[i]->ptszQValue)
+ if (ButtonsList[i]->ptszOPQValue) mir_free(ButtonsList[i]->ptszOPQValue);
+ if (ButtonsList[i]->ptszQValue) mir_free(ButtonsList[i]->ptszQValue);
+ i++;
+ }
+ if(QuickList)
+ {
+ li_ZeroQuickList(QuickList);
+ List_Destroy(QuickList);
+ }
+}
+
+TCHAR* getMenuEntry(int buttonnum, int entrynum, BYTE mode)
+{
+ TCHAR* buffer = NULL;
+ char szMEntry[256] = {'\0'};
+ DBVARIANT dbv = {0};
+
+ switch (mode) {
+ case 0:
+ mir_snprintf(szMEntry, sizeof(szMEntry), "EntryName_%u_%u", buttonnum, entrynum);
+ break;
+ case 1:
+ mir_snprintf(szMEntry, sizeof(szMEntry), "EntryValue_%u_%u", buttonnum, entrynum);
+ break;
+ case 2:
+ mir_snprintf(szMEntry, sizeof(szMEntry), "ButtonValue_%u", buttonnum);
+ break;
+ case 3:
+ mir_snprintf(szMEntry, sizeof(szMEntry), "ButtonName_%u", buttonnum);
+ break;
+ }
+
+ if (!db_get_ts(NULL, PLGNAME, szMEntry, &dbv)) {
+ if (_tcslen(dbv.ptszVal))
+ buffer = mir_tstrdup(dbv.ptszVal);
+ db_free(&dbv);
+ }
+
+ return buffer;
+}
+
+int RegisterCustomButton(WPARAM wParam,LPARAM lParam)
+{
+ if ( !ServiceExists(MS_BB_ADDBUTTON))
+ return 1;
+
+ for (int i=0; i < g_iButtonsCount; i++) {
+ ListData* ld = ButtonsList[i];
+
+ char iconname[40];
+ mir_snprintf(iconname, SIZEOF(iconname), LPGEN("Quick Messages Button %u"), i);
+
+ BBButton bbd = { sizeof(bbd) };
+ bbd.bbbFlags = BBBF_ISIMBUTTON | BBBF_ISCHATBUTTON | BBBF_ISLSIDEBUTTON;
+ bbd.dwButtonID = i;
+ bbd.dwDefPos = 320+i;
+ bbd.hIcon = AddIcon(iconname);
+ bbd.pszModuleName = PLGNAME;
+ bbd.ptszTooltip = ld->ptszButtonName;
+ CallService(MS_BB_ADDBUTTON, 0, (LPARAM)&bbd);
+ }
+ return 0;
+}
+
+TCHAR* ParseString(MCONTACT hContact,TCHAR* ptszQValIn,TCHAR* ptszText,TCHAR* ptszClip,int QVSize,int TextSize ,int ClipSize)
+{
+ int i = 0, iOffset = 0, iCount = 0;
+ TCHAR* tempPointer = NULL;
+ TCHAR* ptszQValue = _tcsdup(ptszQValIn);
+ TCHAR* tempQValue = ptszQValue;
+ TCHAR varstr = _T('%');
+ TCHAR* p = NULL;
+ int NameLenght = 0;
+ TCHAR* ptszName = NULL;
+ CONTACTINFO ci;
+
+ if (!_tcschr(ptszQValue,varstr))
+ return ptszQValue;
+
+ if(TextSize && ptszText[TextSize - 1] == '\0')
+ TextSize --;
+ if(ClipSize && ptszClip[ClipSize - 1] == '\0')
+ ClipSize --;
+
+ while (ptszQValue[i]) {
+ if (ptszQValue[i] != '%')
+ goto move_next;
+ NameLenght = 0;
+ ptszName = NULL;
+
+ switch (ptszQValue[i + 1]) {
+ case 't':
+ p = (TCHAR *)realloc(tempQValue, (QVSize + TextSize + 1) * sizeof(TCHAR));
+ if (!p)
+ break;
+ i = iOffset;
+ tempQValue = ptszQValue = p;
+
+ tempPointer = (TCHAR *)memmove(ptszQValue + i + TextSize, ptszQValue + i + 2, (QVSize - i - 1) * sizeof(TCHAR));
+ memcpy(ptszQValue + i, ptszText, TextSize * sizeof(TCHAR));
+ QVSize += (TextSize - 2);
+ ptszQValue[QVSize] = '\0';
+
+ if (!_tcschr(ptszQValue, varstr))
+ return ptszQValue;
+
+ ptszQValue = tempPointer;
+ iOffset += TextSize - 1;
+ i = -1;
+ break;
+ case 'c':
+ p = (TCHAR *)realloc(tempQValue, (QVSize + ClipSize + 1) * sizeof(TCHAR));
+ if (!p)
+ break;
+ i = iOffset;
+ tempQValue = ptszQValue = p;
+
+ tempPointer = (TCHAR *)memmove(ptszQValue + i + ClipSize, ptszQValue + i + 2, (QVSize - i - 1) * sizeof(TCHAR));
+ memcpy(ptszQValue + i, ptszClip, ClipSize * sizeof(TCHAR));
+ QVSize += (ClipSize - 2);
+ ptszQValue[QVSize] = '\0';
+
+ if (!_tcschr(ptszQValue, varstr))
+ return ptszQValue;
+
+ ptszQValue = tempPointer;
+ iOffset += ClipSize - 1;
+ i = -1;
+ break;
+ case 'P':
+ ptszName = mir_a2u(GetContactProto(hContact));
+ NameLenght = (int)_tcslen(ptszName);
+ p = (TCHAR *)realloc(tempQValue, (QVSize + NameLenght + 1) * sizeof(TCHAR));
+ if (!p) {
+ mir_free(ptszName);
+ break;
+ }
+ i = iOffset;
+ tempQValue = ptszQValue = p;
+
+ tempPointer = (TCHAR *)memmove(ptszQValue + i + NameLenght, ptszQValue + i + 2, (QVSize - i - 1) * sizeof(TCHAR));
+ memcpy(ptszQValue + i, ptszName, NameLenght * sizeof(TCHAR));
+ QVSize += (NameLenght - 2);
+ mir_free(ptszName);
+ ptszQValue[QVSize] = '\0';
+
+ if (!_tcschr(ptszQValue, varstr))
+ return ptszQValue;
+
+ ptszQValue = tempPointer;
+ iOffset += NameLenght - 1;
+ i = -1;
+ break;
+
+ case 'n':
+ ptszName = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR);
+ NameLenght = (int)_tcslen(ptszName);
+ p = (TCHAR *)realloc(tempQValue, (QVSize + NameLenght + 1) * sizeof(TCHAR));
+ if (!p)
+ break;
+ i = iOffset;
+ tempQValue = ptszQValue = p;
+
+ tempPointer = (TCHAR *)memmove(ptszQValue + i + NameLenght, ptszQValue + i + 2, (QVSize - i - 1) * sizeof(TCHAR));
+ memcpy(ptszQValue + i, ptszName, NameLenght * sizeof(TCHAR));
+ QVSize += (NameLenght - 2);
+ ptszQValue[QVSize] = '\0';
+
+ if (!_tcschr(ptszQValue, varstr))
+ return ptszQValue;
+
+ ptszQValue = tempPointer;
+ iOffset += NameLenght - 1;
+ i = -1;
+ break;
+ case 'F':
+ ZeroMemory(&ci, sizeof(CONTACTINFO));
+ ci.cbSize = sizeof(CONTACTINFO);
+ ci.hContact = hContact;
+ ci.dwFlag = CNF_FIRSTNAME | CNF_UNICODE;
+ ci.szProto = GetContactProto(hContact);
+
+ if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci))
+ break;
+ NameLenght = (int)_tcslen(ci.pszVal);
+ ptszName = ci.pszVal;
+ p = (TCHAR *)realloc(tempQValue, (QVSize + NameLenght + 1) * sizeof(TCHAR));
+ if (!p) {
+ mir_free(ptszName);
+ break;
+ }
+ i = iOffset;
+ tempQValue = ptszQValue = p;
+
+ tempPointer = (TCHAR *)memmove(ptszQValue + i + NameLenght, ptszQValue + i + 2, (QVSize - i - 1) * sizeof(TCHAR));
+ memcpy(ptszQValue + i, ptszName, NameLenght * sizeof(TCHAR));
+ QVSize += (NameLenght - 2);
+ mir_free(ptszName);
+ ptszQValue[QVSize] = '\0';
+
+ if (!_tcschr(ptszQValue, varstr))
+ return ptszQValue;
+
+ ptszQValue = tempPointer;
+ iOffset += NameLenght - 1;
+ i = -1;
+ break;
+ case 'L':
+ ZeroMemory(&ci, sizeof(CONTACTINFO));
+ ci.cbSize = sizeof(CONTACTINFO);
+ ci.hContact = hContact;
+ ci.dwFlag = CNF_LASTNAME | CNF_UNICODE;
+ ci.szProto = GetContactProto(hContact);
+
+ if (CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci))
+ break;
+ NameLenght = (int)_tcslen(ci.pszVal);
+ ptszName = ci.pszVal;
+ p = (TCHAR *)realloc(tempQValue, (QVSize + NameLenght + 1) * sizeof(TCHAR));
+ if (!p) {
+ mir_free(ptszName);
+ break;
+ }
+ i = iOffset;
+ tempQValue = ptszQValue = p;
+
+ tempPointer = (TCHAR *)memmove(ptszQValue + i + NameLenght, ptszQValue + i + 2, (QVSize - i - 1) * sizeof(TCHAR));
+ memcpy(ptszQValue + i, ptszName, NameLenght * sizeof(TCHAR));
+ QVSize += (NameLenght - 2);
+ mir_free(ptszName);
+ ptszQValue[QVSize] = '\0';
+
+ if (!_tcschr(ptszQValue,varstr))
+ return ptszQValue;
+
+ ptszQValue = tempPointer;
+ iOffset += NameLenght - 1;
+ i = -1;
+ break;
+ }
+move_next:
+ iOffset ++;
+ i ++;
+ }
+ return ptszQValue;
+}