/* Miranda IM Country Flags Plugin Copyright (C) 2006-1007 H. Herkenrath This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (Flags-License.txt); if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "flags.h" /************************* Buffered Functions *********************/ struct BufferedCallData { DWORD startTick; UINT uElapse; BUFFEREDPROC pfnBuffProc; LPARAM lParam; #ifdef _DEBUG const char *pszProcName; #endif }; static UINT idBufferedTimer; static struct BufferedCallData *callList; static int nCallListCount; // always gets called in main message loop static void CALLBACK BufferedProcTimer(HWND hwnd,UINT msg,UINT_PTR idTimer,DWORD currentTick) { struct BufferedCallData *buf; UINT uElapsed,uElapseNext=USER_TIMER_MAXIMUM; BUFFEREDPROC pfnBuffProc; LPARAM lParam; #ifdef _DEBUG char szDbgLine[256]; const char *pszProcName; #endif for(int i=0; i < nCallListCount; ++i) { /* find elapsed procs */ uElapsed=currentTick-callList[i].startTick; /* wraparound works */ if ((uElapsed+USER_TIMER_MINIMUM)>=callList[i].uElapse) { /* call elapsed proc */ pfnBuffProc=callList[i].pfnBuffProc; lParam=callList[i].lParam; #ifdef _DEBUG pszProcName=callList[i].pszProcName; #endif /* resize storage array */ if ((i+1)<nCallListCount) MoveMemory(&callList[i],&callList[i+1],((nCallListCount-i-1)*sizeof(struct BufferedCallData))); --nCallListCount; --i; /* reiterate current */ if (nCallListCount) { buf=(struct BufferedCallData*)mir_realloc(callList,nCallListCount*sizeof(struct BufferedCallData)); if (buf != NULL) callList=buf; } else { mir_free(callList); callList=NULL; } #ifdef _DEBUG mir_snprintf(szDbgLine,sizeof(szDbgLine),"buffered call: %s(0x%X)\n",pszProcName,lParam); /* all ascii */ OutputDebugStringA(szDbgLine); #endif CallFunctionAsync((void (CALLBACK *)(void*))pfnBuffProc,(void*)lParam); /* compatible */ } /* find next timer delay */ else if ((callList[i].uElapse-uElapsed)<uElapseNext) uElapseNext=callList[i].uElapse-uElapsed; } /* set next timer */ if (nCallListCount) { #ifdef _DEBUG mir_snprintf(szDbgLine,sizeof(szDbgLine),"next buffered timeout: %ums\n",uElapseNext); /* all ascii */ OutputDebugStringA(szDbgLine); #endif idBufferedTimer=SetTimer(hwnd,idBufferedTimer,uElapseNext,BufferedProcTimer); /* will be reset */ } else { KillTimer(hwnd,idTimer); idBufferedTimer=0; #ifdef _DEBUG OutputDebugStringA("empty buffered queue\n"); #endif } } // assumes to be called in context of main thread #ifdef _DEBUG void _CallFunctionBuffered(BUFFEREDPROC pfnBuffProc,const char *pszProcName,LPARAM lParam,BOOL fAccumulateSameParam,UINT uElapse) #else void _CallFunctionBuffered(BUFFEREDPROC pfnBuffProc,LPARAM lParam,BOOL fAccumulateSameParam,UINT uElapse) #endif { struct BufferedCallData *data=NULL; int i; /* find existing */ for(i=0;i<nCallListCount;++i) if (callList[i].pfnBuffProc == pfnBuffProc) if (!fAccumulateSameParam || callList[i].lParam == lParam) { data=&callList[i]; break; } /* append new */ if (data == NULL) { /* resize storage array */ data=(struct BufferedCallData*)mir_realloc(callList,(nCallListCount+1)*sizeof(struct BufferedCallData)); if (data == NULL) return; callList=data; data=&callList[nCallListCount]; ++nCallListCount; } /* set delay */ data->startTick=GetTickCount(); data->uElapse=uElapse; data->lParam=lParam; data->pfnBuffProc=pfnBuffProc; #ifdef _DEBUG { char szDbgLine[256]; data->pszProcName=pszProcName; mir_snprintf(szDbgLine,sizeof(szDbgLine),"buffered queue: %s(0x%X)\n",pszProcName,lParam); /* all ascii */ OutputDebugStringA(szDbgLine); if (!idBufferedTimer) { mir_snprintf(szDbgLine,sizeof(szDbgLine),"next buffered timeout: %ums\n",uElapse); /* all ascii */ OutputDebugStringA(szDbgLine); } } #endif /* set next timer */ if (idBufferedTimer) uElapse=USER_TIMER_MINIMUM; /* will get recalculated */ idBufferedTimer=SetTimer(NULL,idBufferedTimer,uElapse,BufferedProcTimer); } // assumes to be called in context of main thread void PrepareBufferedFunctions(void) { idBufferedTimer=0; nCallListCount=0; callList=NULL; } // assumes to be called in context of main thread void KillBufferedFunctions(void) { if (idBufferedTimer) KillTimer(NULL,idBufferedTimer); nCallListCount=0; mir_free(callList); /* does NULL check */ }