/* 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 . */ #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; irealCount; i++) pItemDestructor(pList->items[i]); List_Destroy(pList); mir_free(pList); } void li_RemoveDestruct(SortedList *pList, int index, ItemDestuctor pItemDestructor) { if (index>=0 && indexrealCount) { 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; irealCount-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; irealCount; 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;isl=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; }