summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Kulakov <panda75@bk.ru>2012-06-27 17:22:43 +0000
committerAlexey Kulakov <panda75@bk.ru>2012-06-27 17:22:43 +0000
commitf9eb107520e9dad37b06eb5c737b39d7bc15c751 (patch)
tree9a010a702ad582079966a6b3c2c162011d83b0d3
parentd193e0b6402c482b9c42016452c3ed219f4f5e35 (diff)
Added File As Message plugin
git-svn-id: http://svn.miranda-ng.org/main/trunk@655 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
-rw-r--r--plugins/FileAsMessage/IcoLib.h12
-rw-r--r--plugins/FileAsMessage/base64.c93
-rw-r--r--plugins/FileAsMessage/crc32.cpp29
-rw-r--r--plugins/FileAsMessage/dialog.cpp1366
-rw-r--r--plugins/FileAsMessage/dialog.h120
-rw-r--r--plugins/FileAsMessage/fileecho.dsp148
-rw-r--r--plugins/FileAsMessage/fileecho.dsw29
-rw-r--r--plugins/FileAsMessage/fileecho.optbin0 -> 54784 bytes
-rw-r--r--plugins/FileAsMessage/fileecho.vcproj236
-rw-r--r--plugins/FileAsMessage/m_Snapping_windows.h42
-rw-r--r--plugins/FileAsMessage/main.cpp359
-rw-r--r--plugins/FileAsMessage/main.h59
-rw-r--r--plugins/FileAsMessage/main.rc30
-rw-r--r--plugins/FileAsMessage/optionsdlg.cpp118
-rw-r--r--plugins/FileAsMessage/res/abort.icobin0 -> 2550 bytes
-rw-r--r--plugins/FileAsMessage/res/file.icobin0 -> 2550 bytes
-rw-r--r--plugins/FileAsMessage/res/pause.icobin0 -> 2550 bytes
-rw-r--r--plugins/FileAsMessage/res/play.icobin0 -> 2550 bytes
-rw-r--r--plugins/FileAsMessage/res/refresh.icobin0 -> 2550 bytes
-rw-r--r--plugins/FileAsMessage/resource.h45
-rw-r--r--plugins/FileAsMessage/resources.rc156
21 files changed, 2842 insertions, 0 deletions
diff --git a/plugins/FileAsMessage/IcoLib.h b/plugins/FileAsMessage/IcoLib.h
new file mode 100644
index 0000000000..77e8625c61
--- /dev/null
+++ b/plugins/FileAsMessage/IcoLib.h
@@ -0,0 +1,12 @@
+typedef struct {
+ int cbSize;
+ char *pszSection; //section name used to group icons
+ char *pszDescription; //description for options dialog
+ char *pszName; //name to refer to icon when playing and in db
+ char *pszDefaultFile; //default icon file to use
+ int iDefaultIndex;
+} SKINICONDESC;
+
+#define MS_SKIN2_ADDICON "Skin2/Icons/AddIcon"
+#define MS_SKIN2_GETICON "Skin2/Icons/GetIcon"
+#define ME_SKIN2_ICONSCHANGED "Skin2/IconsChanged"
diff --git a/plugins/FileAsMessage/base64.c b/plugins/FileAsMessage/base64.c
new file mode 100644
index 0000000000..220cd85027
--- /dev/null
+++ b/plugins/FileAsMessage/base64.c
@@ -0,0 +1,93 @@
+#define XNetlib_GetBase64DecodedBufferSize(cchEncoded) (((cchEncoded)>>2)*3)
+#define XNetlib_GetBase64EncodedBufferSize(cbDecoded) (((cbDecoded)*4+11)/12*4+1)
+
+static char base64chars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+int XNetlibBase64Encode(WPARAM wParam,LPARAM lParam)
+{
+ NETLIBBASE64 *nlb64=(NETLIBBASE64*)lParam;
+ int iIn;
+ char *pszOut;
+ PBYTE pbIn;
+
+ if(nlb64==NULL || nlb64->pszEncoded==NULL || nlb64->pbDecoded==NULL) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ if(nlb64->cchEncoded<XNetlib_GetBase64EncodedBufferSize(nlb64->cbDecoded)) {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return 0;
+ }
+ nlb64->cchEncoded=XNetlib_GetBase64EncodedBufferSize(nlb64->cbDecoded);
+ for(iIn=0,pbIn=nlb64->pbDecoded,pszOut=nlb64->pszEncoded;iIn<nlb64->cbDecoded;iIn+=3,pbIn+=3,pszOut+=4) {
+ pszOut[0]=base64chars[pbIn[0]>>2];
+ if(nlb64->cbDecoded-iIn==1) {
+ pszOut[1]=base64chars[(pbIn[0]&3)<<4];
+ pszOut[2]='=';
+ pszOut[3]='=';
+ pszOut+=4;
+ break;
+ }
+ pszOut[1]=base64chars[((pbIn[0]&3)<<4)|(pbIn[1]>>4)];
+ if(nlb64->cbDecoded-iIn==2) {
+ pszOut[2]=base64chars[(pbIn[1]&0xF)<<2];
+ pszOut[3]='=';
+ pszOut+=4;
+ break;
+ }
+ pszOut[2]=base64chars[((pbIn[1]&0xF)<<2)|(pbIn[2]>>6)];
+ pszOut[3]=base64chars[pbIn[2]&0x3F];
+ }
+ pszOut[0]='\0';
+ return 1;
+}
+
+BYTE Base64CharToInt(char c)
+{
+ if(c>='A' && c<='Z') return c-'A';
+ if(c>='a' && c<='z') return c-'a'+26;
+ if(c>='0' && c<='9') return c-'0'+52;
+ if(c=='+') return 62;
+ if(c=='/') return 63;
+ if(c=='=') return 64;
+ return 255;
+}
+
+int XNetlibBase64Decode(WPARAM wParam,LPARAM lParam)
+{
+ NETLIBBASE64 *nlb64=(NETLIBBASE64*)lParam;
+ char *pszIn;
+ PBYTE pbOut;
+ BYTE b1,b2,b3,b4;
+ int iIn;
+
+ if(nlb64==NULL || nlb64->pszEncoded==NULL || nlb64->pbDecoded==NULL) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ if(nlb64->cchEncoded&3) {
+ SetLastError(ERROR_INVALID_DATA);
+ return 0;
+ }
+ if(nlb64->cbDecoded<XNetlib_GetBase64DecodedBufferSize(nlb64->cchEncoded)) {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return 0;
+ }
+ nlb64->cbDecoded=XNetlib_GetBase64DecodedBufferSize(nlb64->cchEncoded);
+ for(iIn=0,pszIn=nlb64->pszEncoded,pbOut=nlb64->pbDecoded;iIn<nlb64->cchEncoded;iIn+=4,pszIn+=4,pbOut+=3) {
+ b1=Base64CharToInt(pszIn[0]);
+ b2=Base64CharToInt(pszIn[1]);
+ b3=Base64CharToInt(pszIn[2]);
+ b4=Base64CharToInt(pszIn[3]);
+ if(b1==255 || b1==64 || b2==255 || b2==64 || b3==255 || b4==255) {
+ SetLastError(ERROR_INVALID_DATA);
+ return 0;
+ }
+ pbOut[0]=(b1<<2)|(b2>>4);
+ if(b3==64) {nlb64->cbDecoded-=2; break;}
+ pbOut[1]=(b2<<4)|(b3>>2);
+ if(b4==64) {nlb64->cbDecoded--; break;}
+ pbOut[2]=b4|(b3<<6);
+ }
+ return 1;
+}
diff --git a/plugins/FileAsMessage/crc32.cpp b/plugins/FileAsMessage/crc32.cpp
new file mode 100644
index 0000000000..e75eb6446e
--- /dev/null
+++ b/plugins/FileAsMessage/crc32.cpp
@@ -0,0 +1,29 @@
+const ulong CRCPoly = 0xEDB88320;
+ulong CRC32Table[256];
+
+void InitCRC32()
+{
+ for (UINT32 i = 0; i < 256; i++)
+ {
+ UINT32 r = i;
+ for (int j = 0; j < 8; j++)
+ if (r & 1)
+ r = (r >> 1) ^ CRCPoly;
+ else
+ r >>= 1;
+ CRC32Table[i] = r;
+ }
+}
+
+const ulong INITCRC = -1L;
+
+inline ulong UpdateCRC32(uchar val, ulong crc)
+{
+ return CRC32Table[(uchar)crc^val] ^ (crc>>8);
+}
+
+ulong memcrc32(uchar *ptr, int size, ulong crc )
+{
+ while(size--) crc = UpdateCRC32(*ptr++, crc);
+ return crc;
+}
diff --git a/plugins/FileAsMessage/dialog.cpp b/plugins/FileAsMessage/dialog.cpp
new file mode 100644
index 0000000000..eb76e24c15
--- /dev/null
+++ b/plugins/FileAsMessage/dialog.cpp
@@ -0,0 +1,1366 @@
+#include"main.h"
+#include"dialog.h"
+#include"resource.h"
+
+#include "m_Snapping_windows.h"
+
+#include"crc32.cpp"
+
+char *szFEMode[] =
+{
+ "Recv file",
+ "Send file"
+};
+
+#define USE_BUILDIN_BASE64
+//
+// BASE64 encoding/decoding
+//
+#define Base64_GetDecodedBufferSize(cchEncoded) (((cchEncoded)>>2)*3)
+#define Base64_GetEncodedBufferSize(cbDecoded) (((cbDecoded)*4+11)/12*4+1)
+#ifdef USE_BUILDIN_BASE64
+#define Base64_Encode(nlb64) CallService(MS_NETLIB_BASE64ENCODE, 0, (LPARAM)nlb64)
+#define Base64_Decode(nlb64) CallService(MS_NETLIB_BASE64DECODE, 0, (LPARAM)nlb64)
+#else
+
+static char base64chars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#define Base64_Encode(nlb64) NetlibBase64Encode(0, (LPARAM)nlb64)
+#define Base64_Decode(nlb64) NetlibBase64Decode(0, (LPARAM)nlb64)
+
+int NetlibBase64Encode(WPARAM wParam,LPARAM lParam)
+{
+ NETLIBBASE64 *nlb64=(NETLIBBASE64*)lParam;
+ int iIn;
+ char *pszOut;
+ PBYTE pbIn;
+
+ if(nlb64==NULL || nlb64->pszEncoded==NULL || nlb64->pbDecoded==NULL) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ if(nlb64->cchEncoded<Netlib_GetBase64EncodedBufferSize(nlb64->cbDecoded)) {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return 0;
+ }
+ nlb64->cchEncoded=Netlib_GetBase64EncodedBufferSize(nlb64->cbDecoded);
+ for(iIn=0,pbIn=nlb64->pbDecoded,pszOut=nlb64->pszEncoded;iIn<nlb64->cbDecoded;iIn+=3,pbIn+=3,pszOut+=4) {
+ pszOut[0]=base64chars[pbIn[0]>>2];
+ if(nlb64->cbDecoded-iIn==1) {
+ pszOut[1]=base64chars[(pbIn[0]&3)<<4];
+ pszOut[2]='=';
+ pszOut[3]='=';
+ pszOut+=4;
+ break;
+ }
+ pszOut[1]=base64chars[((pbIn[0]&3)<<4)|(pbIn[1]>>4)];
+ if(nlb64->cbDecoded-iIn==2) {
+ pszOut[2]=base64chars[(pbIn[1]&0xF)<<2];
+ pszOut[3]='=';
+ pszOut+=4;
+ break;
+ }
+ pszOut[2]=base64chars[((pbIn[1]&0xF)<<2)|(pbIn[2]>>6)];
+ pszOut[3]=base64chars[pbIn[2]&0x3F];
+ }
+ pszOut[0]='\0';
+ return 1;
+}
+
+static BYTE Base64CharToInt(char c)
+{
+ if(c>='A' && c<='Z') return c-'A';
+ if(c>='a' && c<='z') return c-'a'+26;
+ if(c>='0' && c<='9') return c-'0'+52;
+ if(c=='+') return 62;
+ if(c=='/') return 63;
+ if(c=='=') return 64;
+ return 255;
+}
+
+int NetlibBase64Decode(WPARAM wParam,LPARAM lParam)
+{
+ NETLIBBASE64 *nlb64=(NETLIBBASE64*)lParam;
+ char *pszIn;
+ PBYTE pbOut;
+ BYTE b1,b2,b3,b4;
+ int iIn;
+
+ if(nlb64==NULL || nlb64->pszEncoded==NULL || nlb64->pbDecoded==NULL) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ if(nlb64->cchEncoded&3) {
+ SetLastError(ERROR_INVALID_DATA);
+ return 0;
+ }
+ if(nlb64->cbDecoded<Netlib_GetBase64DecodedBufferSize(nlb64->cchEncoded)) {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return 0;
+ }
+ nlb64->cbDecoded=Netlib_GetBase64DecodedBufferSize(nlb64->cchEncoded);
+ for(iIn=0,pszIn=nlb64->pszEncoded,pbOut=nlb64->pbDecoded;iIn<nlb64->cchEncoded;iIn+=4,pszIn+=4,pbOut+=3) {
+ b1=Base64CharToInt(pszIn[0]);
+ b2=Base64CharToInt(pszIn[1]);
+ b3=Base64CharToInt(pszIn[2]);
+ b4=Base64CharToInt(pszIn[3]);
+ if(b1==255 || b1==64 || b2==255 || b2==64 || b3==255 || b4==255) {
+ SetLastError(ERROR_INVALID_DATA);
+ return 0;
+ }
+ pbOut[0]=(b1<<2)|(b2>>4);
+ if(b3==64) {nlb64->cbDecoded-=2; break;}
+ pbOut[1]=(b2<<4)|(b3>>2);
+ if(b4==64) {nlb64->cbDecoded--; break;}
+ pbOut[2]=b4|(b3<<6);
+ }
+ return 1;
+}
+#endif
+
+char* ltoax(char* s, DWORD value)
+{
+ if(value == 0)
+ {
+ *s++ = '0';
+ }
+ uchar data;
+ int indx = 8;
+ while(indx && !(data = (uchar)(value >> 28) & 0x0F))
+ {
+ value <<= 4;
+ indx--;
+ }
+ while(indx)
+ {
+ data = (uchar)(value >> 28) & 0x0F;
+ if(data > 9) data += 'A' - 10;
+ else data += '0';
+ *s++ = data;
+ value <<= 4;
+ indx--;
+ }
+ return s;
+}
+uint atolx(char* &value)
+{
+ uint result = 0;
+ uchar ch;
+
+ while( *value && (ch = *value - '0') >= 0 )
+ {
+ if(ch > 9)
+ {
+ ch -= 'A' - '0';
+ if(ch > 5) break;
+ ch += 10;
+ }
+ result = result * 16 + ch;
+ value++;
+ }
+ return result;
+}
+
+char cCmdList[CMD_COUNT] =
+{
+ '?',
+ '+',
+ '-',
+
+ '*',
+
+ '>',
+ '!',
+ '.'
+};
+
+static int CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = PUGetContact(hWnd);
+ HWND hDlg = (HWND)PUGetPluginData(hWnd);
+/*
+ if(hContact)
+ {
+ CLISTEVENT *lpcle;
+ int indx = 0;
+ for(;;)
+ {
+ if((lpcle = (CLISTEVENT*)CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, indx)) == NULL)
+ break;
+ if(lstrcmp(lpcle->pszService, SERVICE_NAME "/FERecvFile") == 0)
+ {
+ lpcle->lParam = (LPARAM)hWnd;
+ break;
+ }
+ indx++;
+ }
+ }
+*/
+ switch(message) {
+ case WM_COMMAND:
+ {
+ PUDeletePopUp(hWnd);
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)0);
+
+ if(IsWindow(hDlg))
+ {
+ ShowWindow(hDlg, SW_SHOWNORMAL);
+ SetForegroundWindow(hDlg);
+ SetFocus(hDlg);
+ }
+
+ break;
+ }
+ case WM_CONTEXTMENU:
+ PUDeletePopUp(hWnd);
+ break;
+ case UM_FREEPLUGINDATA:
+ return TRUE; //TRUE or FALSE is the same, it gets ignored.
+ default:
+ break;
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+//
+// Just create simple Popup for specified contact
+//
+void MakePopupMsg(HWND hDlg, HANDLE hContact, char *msg)
+{
+ HWND hFocused = GetForegroundWindow();
+ if(hDlg == hFocused || hDlg == GetParent(hFocused)) return;
+
+ POPUPDATAEX ppd;
+ //
+ //The text for the second line. You could even make something like: char lpzText[128]; lstrcpy(lpzText, "Hello world!"); It's your choice.
+ //
+ ZeroMemory(&ppd, sizeof(ppd)); //This is always a good thing to do.
+ ppd.lchContact = (HANDLE)hContact; //Be sure to use a GOOD handle, since this will not be checked.
+ ppd.lchIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALLICON));
+ lstrcpy(ppd.lpzContactName, (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0));
+ lstrcpy(ppd.lpzText, msg);
+ ppd.colorBack = GetSysColor(COLOR_INFOBK);
+ ppd.colorText = GetSysColor(COLOR_INFOTEXT);
+ ppd.PluginWindowProc = (WNDPROC)PopupDlgProc;
+ ppd.PluginData = (void*)hDlg;
+ ppd.iSeconds = -1;
+
+ CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+}
+//
+// Get ID of string message
+//
+int getMsgId(char *msg)
+{
+ for(int indx = 0; indx < CMD_COUNT; indx++)
+ {
+ if(*msg == cCmdList[indx]) return indx;
+ }
+ return -1;
+};
+
+int RetrieveFileSize(char *filename)
+{
+ int handle = open(filename, O_RDONLY|O_BINARY,0);
+ if(handle != -1)
+ {
+ int size = filelength(handle);
+ close(handle);
+ return size;
+ }
+ return handle;
+}
+
+FILEECHO::FILEECHO(HANDLE Contact)
+{
+ hContact = Contact;
+ dwSendInterval = DBGetContactSettingDword(NULL, SERVICE_NAME, "SendDelay", 6000);
+ //dwChunkSize = DBGetContactSettingDword(NULL, SERVICE_NAME, "ChunkSize", 5000);
+
+ chunkMaxLen = DBGetContactSettingDword(NULL, SERVICE_NAME, "ChunkSize", 5000);
+ chunkCount = 0;
+ filename = NULL;
+
+ rgbRecv = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorRecv", RGB(64,255,64));
+ rgbSent = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorSent", RGB(255,255,64));
+ rgbUnSent = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorUnsent", RGB(128,128,128));
+ rgbToSend = DBGetContactSettingDword(NULL, SERVICE_NAME, "colorTosend", RGB(192,192,192));
+ asBinary = DBGetContactSettingDword(NULL, SERVICE_NAME, "base64", 1) == 0;
+}
+
+uint controlEnabled[][2] =
+{
+ IDC_PLAY,
+ STATE_OPERATE|STATE_PAUSED|STATE_PRERECV|STATE_ACKREQ|STATE_IDLE,
+ IDC_STOP,
+ STATE_OPERATE|STATE_PAUSED|STATE_PRERECV|STATE_REQSENT|STATE_ACKREQ,
+// IDC_FILENAME,
+// STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED,
+// IDC_BROWSE,
+// STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED,
+};
+/*
+char *stateMsg[][2] =
+{
+ (char*)STATE_IDLE,"Idle",
+ (char*)STATE_REQSENT,"ReqSent",
+ (char*)STATE_PRERECV,"PreRecv",
+ (char*)STATE_OPERATE,"Operate",
+ (char*)STATE_ACKREQ,"AckReq",
+ (char*)STATE_CANCELLED,"Cancelled",
+ (char*)STATE_FINISHED,"Finished",
+ (char*)STATE_PAUSED,"Paused"
+};
+*/
+
+char *hint_controls[4] = {
+ "Perform",
+ "Pause",
+ "Revive a transfer",
+ "Stop"
+};
+
+void FILEECHO::setState(DWORD state)
+{
+ iState = state;
+ int indx;
+
+ for(indx = 0; indx < ARRAY_SIZE(controlEnabled); indx++)
+ {
+ EnableWindow(GetDlgItem(hDlg, controlEnabled[indx][0]), (iState & controlEnabled[indx][1]) != 0);
+ }
+
+ if(!inSend) // recv
+ {
+ int kind;
+ SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (state != STATE_PRERECV), 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_BROWSE), (iState & (STATE_PRERECV|STATE_FINISHED)));
+ //SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (iState & STATE_PRERECV) == 0, 0);
+ //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState == STATE_PRERECV));
+ //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState & STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED) != 0);
+ if(state & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED|STATE_PRERECV))
+ kind = ICON_PLAY;
+ else
+ kind = ICON_REFRESH;
+ SendDlgItemMessage(hDlg, IDC_PLAY,BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[kind]);
+ SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[kind]),0);
+ }
+ else
+ {
+ SendDlgItemMessage(hDlg, IDC_FILENAME, EM_SETREADONLY, (iState & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED)) == 0, 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_BROWSE), (iState & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED)) != 0);
+ //EnableWindow(GetDlgItem(hDlg, IDC_FILENAME), (iState & STATE_IDLE|STATE_PRERECV|STATE_FINISHED|STATE_CANCELLED) != 0);
+ switch(state)
+ {
+ case STATE_FINISHED:
+ case STATE_CANCELLED:
+ case STATE_IDLE:
+ case STATE_PAUSED:
+ EnableWindow(GetDlgItem(hDlg, IDC_PLAY), TRUE);
+ SendDlgItemMessage(hDlg, IDC_PLAY, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_PLAY]);
+ SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[ICON_PLAY]),0);
+ break;
+ case STATE_OPERATE:
+ SendDlgItemMessage(hDlg, IDC_PLAY, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_PAUSE]);
+ SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[ICON_PAUSE]),0);
+ break;
+ }
+ }
+ updateProgress();
+}
+
+void FILEECHO::updateTitle()
+{
+ char newtitle[256], *contactName;
+
+ contactName=(char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0);
+ if(iState == STATE_OPERATE && chunkCount != 0)
+ _snprintf(newtitle,sizeof(newtitle),"%d%% - %s: %s",chunkSent * 100 / chunkCount, Translate(szFEMode[inSend]), contactName);
+ else
+ _snprintf(newtitle,sizeof(newtitle),"%s: %s",Translate(szFEMode[inSend]), contactName);
+ SetWindowText(hDlg, newtitle);
+}
+
+void BuildFreqTable(uchar *data, uint len, uint *freqTable)
+{
+ ZeroMemory(freqTable, 256*sizeof(uint));
+ for(uint indx = 0; indx < len; indx++)
+ freqTable[data[indx]]++;
+}
+
+int FILEECHO::createTransfer()
+{
+ uint LastError;
+ hFile = INVALID_HANDLE_VALUE;
+ hMapping = NULL;
+ lpData = NULL;
+#ifdef DEBUG
+ overhead = 0;
+#endif
+ hFile = CreateFile(filename, inSend?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE), inSend?FILE_SHARE_READ:0,
+ NULL, inSend?OPEN_EXISTING:(DBGetContactSettingByte(NULL,"SRFile","AutoAccept",0)?CREATE_ALWAYS:CREATE_NEW), FILE_ATTRIBUTE_NORMAL, NULL);
+ if(hFile == INVALID_HANDLE_VALUE && !inSend && GetLastError() == ERROR_FILE_EXISTS)
+ {
+ if(MessageBox(hDlg, Translate("File already exists. Overwrite?"),
+ Translate(SERVICE_TITLE),
+ MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) != IDYES) return 0;
+ hFile = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0,
+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ }
+ if(hFile == INVALID_HANDLE_VALUE) goto createTransfer_FAILED;
+ if(!inSend)
+ {
+ SetFilePointer(hFile, fileSize, NULL, FILE_CURRENT);
+ SetEndOfFile(hFile);
+ }
+ else
+ fileSize = GetFileSize(hFile, NULL);
+ hMapping = CreateFileMapping(hFile, NULL, inSend?PAGE_READONLY:PAGE_READWRITE,
+ 0, fileSize, NULL);
+ LastError = GetLastError();
+ if(hMapping == NULL) goto createTransfer_FAILED;
+ lpData = (uchar*)MapViewOfFile(hMapping, inSend?FILE_MAP_READ:FILE_MAP_WRITE, 0,0,0);
+ LastError = GetLastError();
+ if(lpData == NULL) goto createTransfer_FAILED;
+
+ if(inSend)
+ //
+ // frequency analysis of source file
+ // and building the table of offsets
+ //
+ {
+ if(asBinary)
+ {
+ uint freq_table[256];
+ uchar *data;
+ uint len, chunk_offset, chunk_size, out_size;
+ int chunk_count_limit;
+
+ codeSymb = 1;
+ //
+ // searching for symbol with lowest frequency: "codeSymb"
+ //
+ BuildFreqTable(lpData, fileSize, freq_table);
+ for(int indx = codeSymb+1; indx < 256; indx++)
+ {
+ if(freq_table[codeSymb] > freq_table[indx]) codeSymb = indx;
+ }
+ //DEBUG
+ //codeSymb = ':';
+
+ //
+ // calculating chunks sizes
+ // build table of chunks offsets: chunkPos
+ //
+ chunk_count_limit = 2*fileSize/chunkMaxLen+2;
+ chunkPos = (uint*)malloc(sizeof(uint)*chunk_count_limit);
+ data = lpData;
+ chunk_size = 0; out_size = 0; indx = 0; chunk_offset = 0;
+ for(len = fileSize; len; len--)
+ {
+ if(*data == 0 || *data == codeSymb)
+ out_size += 2;
+ else
+ out_size++;
+
+ data++; chunk_size++;
+ if(out_size >= chunkMaxLen-1)
+ {
+ chunkPos[indx] = chunk_offset; chunk_offset += chunk_size;
+ chunk_size = 0; out_size = 0;
+ indx++;
+ }
+ }
+ chunkPos[indx++] = chunk_offset; chunkCount = indx;
+ chunkPos = (uint*)realloc(chunkPos, sizeof(uint)*(chunkCount+1));
+ chunkPos[indx] = chunk_offset + chunk_size;
+ }
+ else
+ {
+ int EncodedMaxLen = Base64_GetEncodedBufferSize(Base64_GetDecodedBufferSize(chunkMaxLen));
+ int DecodedMaxLen = Base64_GetDecodedBufferSize(EncodedMaxLen);
+
+ codeSymb = '-';
+ chunkCount = (fileSize + DecodedMaxLen - 1) / DecodedMaxLen;
+ chunkPos = (uint*)malloc(sizeof(uint)*(chunkCount+1));
+ for(uint chunk_offset = 0, indx = 0; indx < chunkCount; indx++, chunk_offset += DecodedMaxLen)
+ chunkPos[indx] = chunk_offset;
+ chunkPos[indx] = chunkPos[indx-1] + fileSize%DecodedMaxLen;
+ }
+ }
+ else
+ chunkCount = chunkCountx;
+ chunkAck = (uchar*)malloc(sizeof(uchar)*chunkCount);
+ memset(chunkAck, 0, sizeof(uchar)*chunkCount);
+
+ chunkIndx = 0; chunkSent = 0;
+
+ return 1;
+createTransfer_FAILED:
+ if(lpData != NULL) UnmapViewOfFile(lpData);
+ if(hMapping != NULL) CloseHandle(hMapping);
+ if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
+ return 0;
+}
+
+void FILEECHO::destroyTransfer()
+{
+ if(chunkCount)
+ {
+ chunkCount = 0;
+ if(inSend)
+ free(chunkPos);
+ free(chunkAck);
+ if(lpData != NULL) UnmapViewOfFile(lpData);
+ if(hMapping != NULL) CloseHandle(hMapping);
+ if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
+ }
+ //setState(STATE_IDLE);
+ return;
+}
+
+void FILEECHO::sendReq()
+{
+
+ char sendbuf[MAX_PATH];
+
+ if(!createTransfer())
+ {
+ SetDlgItemText(hDlg, IDC_FILESIZE, Translate("Couldn't open a file"));
+ return;
+ }
+ ///!!!!!!!
+ char *p = filename + strlen(filename);
+ while(p != filename && *p != '\\')
+ p--;
+ if(*p == '\\')
+ strcpy(filename,p+1);
+
+ _snprintf(sendbuf, sizeof(sendbuf), Translate("Size: %d bytes"), fileSize);
+ SetDlgItemText(hDlg, IDC_FILESIZE, sendbuf);
+ _snprintf(sendbuf, sizeof(sendbuf), "?%c%c%d:%d " NOPLUGIN_MESSAGE, asBinary+'0', codeSymb, chunkCount, fileSize);
+ sendCmd(0, CMD_REQ, sendbuf, filename);
+
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Request sent. Awaiting of acceptance.."));
+ setState(STATE_REQSENT);
+}
+void FILEECHO::incomeRequest(char *param)
+{
+ // param: filename?cCOUNT:SIZE
+ char buf[MAX_PATH];
+ // param == &filename
+ char *p = strchr(param, '?');
+ if(p == NULL) return; *p++ = 0;
+ CallService(MS_FILE_GETRECEIVEDFILESFOLDER, (WPARAM)hContact, (LPARAM)buf);
+ strncat(buf, param, sizeof(buf));
+ if(filename) free(filename);
+ filename = strdup(buf);
+ // p == &c
+ if(*p == 0) return; asBinary = (*p++) != '0';
+ if(*p == 0) return; codeSymb = *p++;
+ // p == &COUNT
+ if(*p == 0) return; param = strchr(p, ':');
+ // param == &SIZE
+ if(param == NULL) return; *param++ = 0;
+ if(*param == 0) return;
+ chunkCountx = atoi(p);
+ fileSize = atoi(param);
+
+ _snprintf(buf, sizeof(buf), Translate("Size: %d bytes"), fileSize);
+ SetDlgItemText(hDlg, IDC_FILENAME, filename);
+ SetDlgItemText(hDlg, IDC_FILESIZE, buf);
+
+ setState(STATE_PRERECV);
+ inSend = FALSE;
+
+ SkinPlaySound("RecvFile");
+ int AutoMin = DBGetContactSettingByte(NULL,"SRFile","AutoMin",0);
+ if(DBGetContactSettingByte(NULL,"SRFile","AutoAccept",0) && !DBGetContactSettingByte((HANDLE)hContact,"CList","NotOnList",0))
+ {
+ PostMessage(hDlg, WM_COMMAND, IDC_PLAY, 0);
+ if(AutoMin)
+ ShowWindow(hDlg, SW_SHOWMINIMIZED);
+// ShowWindow(hDlg, SW_MINIMIZE);
+// UpdateWindow(hDlg);
+ }
+// else
+ if(!IsWindowVisible(hDlg) && !AutoMin)
+ {
+ CLISTEVENT cle;
+ ZeroMemory(&cle, sizeof(cle));
+ cle.cbSize = sizeof(cle);
+ cle.hContact = hContact;
+ cle.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALLICON));
+ cle.flags = CLEF_URGENT;
+ cle.hDbEvent = 0;
+ cle.pszService = SERVICE_NAME "/FERecvFile";
+ CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle);
+
+ MakePopupMsg(hDlg, hContact, "Incoming file...");
+ }
+}
+
+void FILEECHO::cmdACCEPT()
+{
+ if(chunkCount == 0) return;
+ setState(STATE_OPERATE);
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending..."));
+ lastTimestamp = GetTickCount();
+ //PostMessage(hDlg, WM_TIMER, 0,0);
+ //onSendTimer();
+ SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0);
+}
+
+void FILEECHO::updateProgress()
+{
+ InvalidateRect(GetDlgItem(hDlg, IDC_PROGRESS), NULL, TRUE);
+ updateTitle();
+}
+//
+// called in receive mode
+// used to transfer acknowledge
+//
+void FILEECHO::onRecvTimer()
+{
+ if(chunkCount == 0) return;
+ char *buffer = (char*)malloc(1024);
+ char *p = buffer;
+ uchar prev_value;
+ uint indx, jndx;
+
+ KillTimer(hDlg, TIMER_SEND);
+ //
+ // Build response about successfully received chunks
+ //
+ indx = jndx = 0; prev_value = chunkAck[jndx];
+ while(jndx < chunkCount)
+ {
+ if(chunkAck[jndx] != prev_value)
+ {
+ if(prev_value != CHUNK_ACK)
+ {
+ p = ltoax(p, indx);
+ if(indx != jndx-1)
+ {
+ *p++ = '-';
+ p = ltoax(p, jndx-1);
+ }
+ *p++ = ',';
+ }
+ indx = jndx;
+ prev_value = chunkAck[jndx];
+ }
+ jndx++;
+ }
+ if(prev_value != CHUNK_ACK)
+ {
+ p = ltoax(p, indx);
+ if(indx != jndx-1)
+ {
+ *p++ = '-';
+ p = ltoax(p, jndx-1);
+ }
+ }
+ *p = 0;
+ if(*buffer == 0)
+ {
+ char *msg = Translate("Received successfully");
+ SetDlgItemText(hDlg, IDC_STATUS, msg);
+ MakePopupMsg(hDlg, hContact, msg);
+ setState(STATE_FINISHED);
+ if(DBGetContactSettingByte(NULL,"SRFile","AutoClose",0))
+ {
+ PostMessage(hDlg, WM_CLOSE, 0,0);
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)0);
+ }
+ SkinPlaySound("FileDone");
+ destroyTransfer();
+ buffer[0] = 'x'; buffer[1] = 0;
+ }
+ sendCmd(0, CMD_DACK, buffer);
+ free(buffer);
+ //if(iState != STATE_FINISHED) SetTimer(hDlg, TIMER_SEND, lastDelay*2, 0);
+}
+//
+// called in sending mode
+// used to data transfer and
+// sending of scheduled commands
+//
+void FILEECHO::onSendTimer()
+{
+ if(chunkCount == 0) return;
+ //
+ // perform request of acknowledge, if scheduled
+ //
+ KillTimer(hDlg, TIMER_SEND);
+ //
+ // Search for next unsent chunk
+ //
+ while(chunkIndx < chunkCount && chunkAck[chunkIndx] != CHUNK_UNSENT) chunkIndx++;
+ if(iState == STATE_ACKREQ || chunkIndx == chunkCount)
+ {
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Requesting of missing chunks"));
+ setState(STATE_OPERATE);
+ sendCmd(0, CMD_END, "", NULL);
+ chunkIndx = chunkCount+1;
+ return;
+ }
+ if(chunkIndx > chunkCount) return;
+
+ uchar *buffer = (uchar*)malloc(chunkMaxLen*2);
+ uchar *p = buffer;
+ uchar *data = lpData + chunkPos[chunkIndx];
+ uchar *data_end = lpData + chunkPos[chunkIndx+1];
+ ulong chksum = memcrc32(data, data_end - data, INITCRC);
+
+ if(asBinary)
+ {
+ //
+ // Encoding data to transfer with symb. filtering
+ //
+ while(data < data_end)
+ {
+ uchar ch = *data++;
+ if(ch == 0)
+ {
+ *p++ = codeSymb; *p++ = '0';
+ }
+ else if (ch == codeSymb)
+ {
+ *p++ = codeSymb; *p++ = '+';
+ }
+ else
+ *p++ = ch;
+ }
+ *p = 0;
+ }
+ else
+ {
+ NETLIBBASE64 nlb;
+
+ nlb.pbDecoded = data;
+ nlb.cbDecoded = data_end - data;
+ nlb.pszEncoded = (char*)buffer;
+ nlb.cchEncoded = chunkMaxLen*2;
+
+ Base64_Encode(&nlb);
+ }
+
+ char prefix[128];
+ _snprintf(prefix, sizeof(prefix), "%X,%X,%X>", chunkIndx+1, chunkPos[chunkIndx], chksum);
+#ifdef DEBUG
+ overhead += lstrlen((char*)buffer);
+#endif
+ sendCmd(0, CMD_DATA, (char*)buffer, (char*)prefix);
+ chunkAck[chunkIndx] = CHUNK_SENT;
+
+ free(buffer);
+
+ chunkIndx++; chunkSent++;
+
+ if(chunkIndx == chunkCount)
+ setState(STATE_ACKREQ);
+ else
+ {
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending..."));
+ updateProgress();
+ }
+ SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0);
+}
+void FILEECHO::cmdDATA(char *param)
+{
+ if(chunkCount == 0) return;
+ chunkIndx = atolx(param); param++;
+ if(chunkIndx-- == 0) return;
+ uint filepos = atolx(param); param++;
+ if(filepos >= fileSize) return;
+
+ ulong chksum_local;
+ ulong chksum_remote = atolx(param); param++;
+
+ KillTimer(hDlg, TIMER_SEND);
+
+ //
+ // Decoding of incoming data
+ //
+ uchar *data = lpData + filepos;
+ uchar *data_end = lpData + fileSize;
+ if(asBinary)
+ {
+ uchar ch;
+ while(ch = *param++)
+ {
+ if(ch == codeSymb)
+ {
+ if((ch = *param++) == 0) goto cmdDATA_corrupted;
+ switch(ch)
+ {
+ case '+':
+ ch = codeSymb;
+ break;
+ case '0':
+ ch = 0;
+ break;
+ default:
+ goto cmdDATA_corrupted;
+ }
+ }
+ if(data > data_end) goto cmdDATA_corrupted;
+ *data++ = ch;
+ }
+ }
+ else
+ {
+ NETLIBBASE64 nlb;
+ uchar *temp_buffer;
+
+ nlb.pszEncoded = param;
+ nlb.cchEncoded = strlen(param);
+ temp_buffer = (uchar*)malloc(nlb.cchEncoded);
+ nlb.pbDecoded = temp_buffer;
+ nlb.cbDecoded = nlb.cchEncoded;
+
+ Base64_Decode(&nlb);
+ memcpy(data, temp_buffer, min(nlb.cbDecoded, data_end - data));
+ data += nlb.cbDecoded;
+ }
+ //
+ // let's check it up
+ //
+ chksum_local = memcrc32(lpData + filepos, data - (lpData + filepos), INITCRC);
+ if(chksum_local == chksum_remote)
+ {
+ if(chunkAck[chunkIndx] != CHUNK_ACK) chunkSent++;
+ chunkAck[chunkIndx] = CHUNK_ACK;
+ //chunkPos[chunkIndx++] = filepos;
+ }
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Receiving..."));
+ updateProgress();
+cmdDATA_corrupted:
+ //SetTimer(hDlg, TIMER_SEND, lastDelay*2, 0);
+ ;
+}
+void FILEECHO::cmdEND()
+{
+ SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0);
+}
+void FILEECHO::cmdDACK(char *param)
+{
+ uint indx, jndx;
+
+ if(chunkCount == 0) return;
+ memset(chunkAck, CHUNK_ACK, sizeof(uchar)*chunkCount);
+ if(*param == 'x')
+ //
+ // All chunks has been received successfully
+ //
+ {
+#ifdef DEBUG
+ char msg[100];
+
+ _snprintf(msg, sizeof(msg), "overhead: %d", overhead);
+ SetDlgItemText(hDlg, IDC_STATUS, msg);
+#else
+ char *msg = Translate("Sent successfully");
+ SetDlgItemText(hDlg, IDC_STATUS, msg);
+#endif
+ SkinPlaySound("FileDone");
+ destroyTransfer();
+ MakePopupMsg(hDlg, hContact, msg);
+ setState(STATE_FINISHED);
+ return;
+ }
+ chunkSent = chunkCount;
+ //
+ // Mark chunks to re-transfer,
+ // according received info
+ //
+ // format: chunk1, chunk3-chunk10, etc..
+ //
+ while(*param)
+ {
+ indx = atolx(param);
+ if(*param == '-')
+ {
+ param++; jndx = atolx(param);
+ }
+ else
+ jndx = indx;
+ if(*param == 0 || *param == ',')
+ {
+ for(uint p = indx; p <= jndx; p++)
+ {
+ if(p < chunkCount)
+ {
+ chunkAck[p] = CHUNK_UNSENT;
+ chunkSent--;
+ }
+ }
+ if(*param == ',')
+ param++;
+ }
+ }
+ updateProgress();
+
+ //
+ // retransfer some parts
+ //
+ chunkIndx = 0;
+ SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0);
+}
+
+void FILEECHO::perform(char *str)
+{
+ int msgId = getMsgId(str);
+ if(msgId == -1)
+ {
+ MakePopupMsg(hDlg, hContact, Translate("Unknown command for \"" SERVICE_TITLE "\" was received"));
+ return;
+ }
+ if(inSend)
+ switch(msgId)
+ {
+ case CMD_REQ:
+ if(MessageBox(hDlg, Translate("Incoming file request. Do you want proceed?"),
+ Translate(SERVICE_TITLE), MB_YESNO | MB_ICONWARNING) == IDYES)
+ {
+ SetDlgItemText(hDlg, IDC_STATUS, "");
+ SendMessage(hDlg, WM_COMMAND, IDC_STOP, 0);
+
+ incomeRequest(str+1);
+ updateTitle();
+ break;
+ }
+ break;
+ case CMD_ACCEPT:
+ cmdACCEPT();
+ break;
+ case CMD_CANCEL:
+ {
+ if(iState & (STATE_PRERECV|STATE_REQSENT|STATE_OPERATE|STATE_ACKREQ|STATE_PAUSED))
+ {
+ char *msg = Translate("Cancelled by remote user");
+ SetDlgItemText(hDlg, IDC_STATUS, msg);
+ MakePopupMsg(hDlg, hContact, msg);
+ destroyTransfer();
+ setState(STATE_CANCELLED);
+ }
+ break;
+ }
+ case CMD_DACK:
+ cmdDACK(str+1);
+ break;
+ }
+ else
+ switch(msgId)
+ {
+ case CMD_CANCEL:
+ {
+ if(iState & (STATE_PRERECV|STATE_REQSENT|STATE_OPERATE|STATE_ACKREQ|STATE_PAUSED))
+ {
+ char *msg = Translate("Cancelled by remote user");
+ SetDlgItemText(hDlg, IDC_STATUS, msg);
+ MakePopupMsg(hDlg, hContact, msg);
+ destroyTransfer();
+ setState(STATE_CANCELLED);
+ }
+ break;
+ }
+ case CMD_REQ:
+ if(chunkCount)
+ {
+ if(MessageBox(hDlg, Translate("New incoming file request. Do you want proceed?"),
+ Translate(SERVICE_TITLE), MB_YESNO | MB_ICONWARNING) != IDYES)
+ break;
+ //sendCmd(0, CMD_CANCEL, "", NULL);
+ destroyTransfer();
+ }
+ SetDlgItemText(hDlg, IDC_STATUS, "");
+ incomeRequest(str+1);
+ break;
+ case CMD_DATA:
+ cmdDATA(str+1);
+ break;
+ case CMD_END:
+ cmdEND();
+ break;
+ };
+};
+
+int FILEECHO::sendCmd(int id, int cmd, char *szParam, char *szPrefix)
+{
+ char *buf;
+ int retval;
+ int buflen = strlen(szServicePrefix) + strlen(szParam) + 2;
+ if(szPrefix != NULL)
+ buflen += strlen(szPrefix);
+
+ buf = (char*)malloc(buflen);
+ if(szPrefix == NULL)
+ _snprintf(buf,buflen,"%s%c%s", szServicePrefix, cCmdList[cmd], szParam);
+ else
+ _snprintf(buf,buflen,"%s%c%s%s", szServicePrefix, cCmdList[cmd], szPrefix, szParam);
+ retval = CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM)buf);
+ free(buf);
+ updateProgress();
+ return retval;
+}
+
+
+void CreateDirectoryTree(char *szDir)
+{
+ DWORD dwAttributes;
+ char *pszLastBackslash,szTestDir[MAX_PATH];
+
+ lstrcpyn(szTestDir,szDir,sizeof(szTestDir));
+ if((dwAttributes=GetFileAttributes(szTestDir))!=0xffffffff
+ && dwAttributes&FILE_ATTRIBUTE_DIRECTORY) return;
+ pszLastBackslash=strrchr(szTestDir,'\\');
+ if(pszLastBackslash==NULL) {GetCurrentDirectory(MAX_PATH,szDir); return;}
+ *pszLastBackslash='\0';
+ CreateDirectoryTree(szTestDir);
+ CreateDirectory(szTestDir,NULL);
+}
+
+void SubclassWnd(HWND hwnd, WNDPROC lpfnWndProc)
+{
+ SetWindowLong(hwnd, GWL_USERDATA, (LONG)GetWindowLong(hwnd, GWL_WNDPROC));
+ SetWindowLong(hwnd, GWL_WNDPROC, (LONG)lpfnWndProc);
+}
+#define CallSubclassed(hwnd, uMsg, wParam, lParam)\
+ CallWindowProc((WNDPROC)GetWindowLong(hwnd, GWL_USERDATA), hwnd, uMsg, wParam, lParam)
+
+LRESULT CALLBACK ProgressWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_NCPAINT:
+ return 0;
+ case WM_PAINT:
+ {
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT rc;
+ HRGN hrgn;
+ HBRUSH frameBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ struct FILEECHO *dat;
+
+ dat = (struct FILEECHO*)GetWindowLong(GetParent(hwnd), GWL_USERDATA);
+ //if(dat == NULL)
+ // return CallSubclassed(hwnd, uMsg, wParam, lParam);
+ GetClientRect(hwnd, &rc);
+ if(dat == NULL || dat->chunkCount == 0)
+ {
+ COLORREF colour;
+ HBRUSH hbr;
+
+ if(dat == NULL || dat->iState != STATE_FINISHED)
+ {
+ hbr = (HBRUSH)(COLOR_3DFACE+1);
+ }
+ else
+ {
+ colour = dat->rgbRecv;
+ hbr = CreateSolidBrush(colour);
+ }
+ hdc=BeginPaint(hwnd,&ps);
+ FillRect(hdc, &rc, hbr);
+ FrameRect(hdc, &rc, frameBrush);
+ if(hbr != (HBRUSH)(COLOR_3DFACE+1))
+ DeleteObject(hbr);
+ EndPaint(hwnd,&ps);
+ return 0;
+ }
+
+ hrgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
+
+ hdc=BeginPaint(hwnd,&ps);
+ SelectClipRgn(hdc, hrgn);
+
+ RECT rc2 = rc;
+ //uint sliceWidth = (rc.right - rc.left) / dat->chunkCount;
+ float sliceWidth = (float)((float)(rc.right - rc.left) / (float)dat->chunkCount);
+ float dx = (float)rc2.left;
+ for(uint indx = 0; indx < dat->chunkCount; indx++)
+ {
+ HBRUSH hbr;
+ COLORREF colour;
+ if(dat->inSend && indx == dat->chunkIndx)
+ colour = dat->rgbToSend;
+ else
+ switch(dat->chunkAck[indx])
+ {
+ case CHUNK_UNSENT:
+ colour = dat->rgbUnSent;
+ break;
+ case CHUNK_SENT:
+ colour = dat->rgbSent;
+ break;
+ case CHUNK_ACK:
+ colour = dat->rgbRecv;
+ break;
+ }
+ /*
+ if(indx == 5) colour = RGB(255,64,64);
+ else if(indx < 2) colour = RGB(64,255,64);
+ else if(indx < 4) colour = RGB(255,255,64);
+ else colour = RGB(128,128,128);
+ //*/
+ if(indx == dat->chunkCount-1)
+ rc2.right = rc.right;
+ hbr = CreateSolidBrush(colour);
+ rc2.left = (int)dx;
+ rc2.right = (int)(dx + sliceWidth);
+ FillRect(hdc, &rc2, hbr);
+ FrameRect(hdc, &rc2, frameBrush);
+ DeleteObject(hbr);
+ dx += sliceWidth-1;
+ }
+ if(rc2.right < rc.right)
+ {
+ rc2.left = rc2.right;
+ rc2.right = rc.right;
+ FillRect(hdc, &rc2, (HBRUSH)(COLOR_3DFACE+1));
+ }
+ //FrameRect(hdc, &rc, (HBRUSH)(COLOR_3DLIGHT+1));
+ //OffsetRect(&rc, 1,1);
+ //FrameRect(hdc, &rc, (HBRUSH)(COLOR_BTNTEXT+1));
+ //FrameRect(hdc, &rc, (HBRUSH)(COLOR_BTNTEXT+1));
+ EndPaint(hwnd,&ps);
+
+ DeleteObject(hrgn);
+
+ return 0;
+ }
+ }
+ return CallSubclassed(hwnd, uMsg, wParam, lParam);
+}
+
+LRESULT CALLBACK DialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ struct FILEECHO *dat;
+
+ dat = (struct FILEECHO*)GetWindowLong(hDlg, GWL_USERDATA);
+ CallSnappingWindowProc(hDlg,uMsg,wParam,lParam);
+ switch( uMsg )
+ {
+ case WM_INITDIALOG:
+ {
+ dat = (FILEECHO*)lParam;
+ dat->hDlg = hDlg;
+
+ dat->updateTitle();
+
+ CreateStatusWindow(WS_CHILD|WS_VISIBLE, "", hDlg, IDC_STATUS);
+ SetWindowLong(hDlg, GWL_USERDATA, (LONG)dat);
+ WindowList_Add(hFileList, hDlg, dat->hContact);
+ SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcons[ICON_MAIN]);
+ SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcons[ICON_MAIN]);
+ SendDlgItemMessage(hDlg, IDC_STOP, BUTTONADDTOOLTIP,(WPARAM)Translate(hint_controls[ICON_STOP]),0);
+
+ //SetDlgItemText(hDlg, IDC_FILENAME, "C:\\!Developer\\!Miranda\\miranda\\bin\\release\\emo\\biggrin.gif");
+
+ SubclassWnd(GetDlgItem(hDlg, IDC_PROGRESS), ProgressWndProc);
+
+ SendDlgItemMessage(hDlg, IDC_PLAY, BUTTONSETASFLATBTN,0,0);
+ SendDlgItemMessage(hDlg, IDC_PLAY, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_PLAY]);
+ SendDlgItemMessage(hDlg, IDC_STOP, BUTTONSETASFLATBTN,0,0);
+ SendDlgItemMessage(hDlg, IDC_STOP, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_STOP]);
+ dat->setState(STATE_IDLE);
+
+ //ShowWindow(hDlg, SW_HIDE);
+ //UpdateWindow(hDlg);
+
+ if(dat->inSend)
+ PostMessage(hDlg, WM_COMMAND, IDC_BROWSE, NULL);
+
+ return FALSE;
+ }
+ case WM_FE_MESSAGE:
+ {
+ dat->perform((char *)lParam);
+ delete (char *)lParam;
+
+ return TRUE;
+ }
+ case WM_FE_SKINCHANGE:
+ SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcons[ICON_MAIN]);
+ SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcons[ICON_MAIN]);
+ dat->setState(dat->iState);
+ SendDlgItemMessage(hDlg, IDC_STOP, BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcons[ICON_STOP]);
+
+ break;
+ case WM_FE_STATUSCHANGE:
+ {
+ char *szProto;
+ szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)dat->hContact,0);
+ if (szProto)
+ {
+ int dwStatus;
+ dwStatus = DBGetContactSettingWord(dat->hContact,szProto,"Status",ID_STATUS_OFFLINE);
+ if(dat->inSend && dwStatus != dat->contactStatus)
+ {
+ if(dat->contactStatus == ID_STATUS_OFFLINE)
+ {
+ dat->chunkIndx = dat->chunkCount;
+ }
+ else
+ if(dwStatus == ID_STATUS_OFFLINE)
+ {
+ if(dat->iState & (STATE_OPERATE|STATE_ACKREQ))
+ {
+ char *msg = Translate("Paused, 'coz connection dropped");
+ SetDlgItemText(hDlg, IDC_STATUS, msg);
+ MakePopupMsg(dat->hDlg, dat->hContact, msg);
+ dat->setState(STATE_PAUSED);
+ KillTimer(hDlg, TIMER_SEND);
+ }
+ }
+ }
+ dat->contactStatus = dwStatus;
+ }
+ return TRUE;
+ }
+ case WM_DESTROY:
+ WindowList_Remove(hFileList, hDlg);
+ delete dat;
+
+ return TRUE;
+
+ case WM_TIMER:
+ if(dat->inSend)
+ dat->onSendTimer();
+ else
+ dat->onRecvTimer();
+ break;
+ case WM_COMMAND:
+ switch(wParam)
+ {
+ case IDC_PLAY:
+ {
+ if(dat->iState & (STATE_IDLE|STATE_FINISHED|STATE_CANCELLED|STATE_PRERECV))
+ {
+ int len = GetWindowTextLength(GetDlgItem(hDlg, IDC_FILENAME))+1;
+ if(dat->filename) free(dat->filename);
+ dat->filename = (char*)malloc(len);
+ GetDlgItemText(hDlg, IDC_FILENAME, dat->filename, len);
+ if(dat->inSend)
+ // Send offer to remote side
+ {
+ dat->sendReq();
+ }
+ else
+ // Send the accept and starting to receive
+ {
+ char buff[MAX_PATH];
+ char *bufname;
+
+ GetFullPathName(dat->filename, sizeof(buff), buff, &bufname);
+ *bufname = 0;
+ CreateDirectoryTree(buff);
+ if(!dat->createTransfer())
+ {
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Failed on file initialization"));
+ break;
+ }
+ dat->sendCmd(0, CMD_ACCEPT, "");
+ dat->lastTimestamp = GetTickCount();
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Receiving..."));
+ dat->setState(STATE_OPERATE);
+ }
+ }
+ else
+ {
+ if(dat->inSend)
+ {
+ if(dat->iState == STATE_OPERATE)
+ {
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Paused..."));
+ dat->setState(STATE_PAUSED);
+ KillTimer(hDlg, TIMER_SEND);
+ }
+ else
+ {
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Sending..."));
+ if(dat->chunkIndx < dat->chunkCount)
+ dat->setState(STATE_OPERATE);
+ else
+ dat->setState(STATE_ACKREQ);
+ PostMessage(hDlg, WM_TIMER, 0,0);
+ //dat->onRecvTimer();
+ //SetTimer(hDlg, TIMER_SEND, dwSendInterval, NULL);
+ }
+ }
+ else
+ {
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Synchronizing..."));
+ dat->setState(STATE_ACKREQ);
+ PostMessage(hDlg, WM_TIMER, 0,0);
+ //dat->onRecvTimer();
+ //SetTimer(hDlg, TIMER_SEND, dwSendInterval, 0);
+ }
+ break;
+ }
+ break;
+ }
+ case IDC_BROWSE:
+ {
+ char str[MAX_PATH];
+ OPENFILENAME ofn;
+
+ ZeroMemory(&ofn, sizeof(ofn));
+ *str = 0;
+ GetDlgItemText(hDlg, IDC_FILENAME, str, sizeof(str));
+ //ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hDlg;
+ //ofn.lpstrFilter = "*.*";
+ ofn.lpstrFile = str;
+ ofn.Flags = dat->inSend?OFN_FILEMUSTEXIST:0;
+ ofn.lpstrTitle = dat->inSend?Translate("Select a file"):Translate("Save as");
+ ofn.nMaxFile = sizeof(str);
+ ofn.nMaxFileTitle = MAX_PATH;
+ if(!GetOpenFileName(&ofn)) break;
+ if(!dat->inSend && dat->iState == STATE_FINISHED) break;
+ SetDlgItemText(hDlg, IDC_FILENAME, str);
+
+ int size = RetrieveFileSize(str);
+ if(size != -1)
+ _snprintf(str, sizeof(str), Translate("Size: %d bytes"), size);
+ else
+ _snprintf(str, sizeof(str), Translate("Can't get a file size"), size);
+ SetDlgItemText(hDlg, IDC_FILESIZE, str);
+
+ break;
+ }
+
+ case IDC_STOP:
+ case IDCANCEL:
+ if(dat->iState == STATE_PRERECV)
+ {
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Cancelled by user"));
+ dat->sendCmd(0, CMD_CANCEL, "", NULL);
+ dat->setState(STATE_CANCELLED);
+ }
+ if(dat->chunkCount)
+ {
+ if(MessageBox(hDlg, Translate("Transfer is in progress. Do you really want to close?"),
+ Translate(SERVICE_TITLE), MB_ICONWARNING|MB_YESNO|MB_DEFBUTTON2) == IDYES)
+ {
+ SetDlgItemText(hDlg, IDC_STATUS, Translate("Cancelled by user"));
+ dat->setState(STATE_CANCELLED);
+ dat->sendCmd(0, CMD_CANCEL, "", NULL);
+ dat->destroyTransfer();
+ if(wParam == IDCANCEL)
+ DestroyWindow(hDlg);
+ }
+ }
+ else
+ if(wParam == IDCANCEL)
+ DestroyWindow(hDlg);
+ break;//return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/plugins/FileAsMessage/dialog.h b/plugins/FileAsMessage/dialog.h
new file mode 100644
index 0000000000..ab5795dc0f
--- /dev/null
+++ b/plugins/FileAsMessage/dialog.h
@@ -0,0 +1,120 @@
+#include<io.h>
+#include<fcntl.h>
+#include<commctrl.h>
+extern HINSTANCE hInst;
+
+int getMsgId(char *msg);
+
+LRESULT CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+#ifdef _DEBUG
+ #define CHECKPOINT
+#else
+ #define CHECKPOINT error
+#endif
+
+#define TIMER_SEND 100
+
+typedef unsigned int uint;
+typedef unsigned char uchar;
+typedef unsigned long ulong;
+enum
+{
+ CMD_REQ,
+ CMD_ACCEPT,
+ CMD_CANCEL,
+
+ CMD_NEXT,
+
+ CMD_DATA,
+ CMD_DACK,
+ CMD_END,
+
+ CMD_COUNT
+};
+
+extern char cFECmd[CMD_COUNT];
+
+#define STATE_IDLE 0x100 // idle, no operation
+#define STATE_REQSENT 0x02 // request sent, awaiting of response
+#define STATE_PRERECV 0x04 // incoming request, awaiting of user
+#define STATE_OPERATE 0x08 // operating mode
+#define STATE_ACKREQ 0x10 // ACK-request scheduled
+#define STATE_CANCELLED 0x20 // operation aborted
+#define STATE_FINISHED 0x40 // ... finished successfully
+#define STATE_PAUSED 0x80 // ... paused
+
+#define CHUNK_UNSENT 0x00
+#define CHUNK_SENT 0x01
+#define CHUNK_ACK 0x02
+
+#define ICON_PLAY 0
+#define ICON_PAUSE 1
+#define ICON_REFRESH 2
+#define ICON_STOP 3
+#define ICON_MAIN 4
+
+struct FILEECHO
+{
+public:
+ HANDLE hContact;
+ HWND hDlg;
+
+ bool inSend;
+ int iState;
+ int contactStatus;
+
+ HANDLE hFile, hMapping;
+ uchar *lpData;
+
+ char *filename;
+ uint chunkIndx; // next chunk to send
+ uint chunkCount; // count of chunks
+ uint chunkSent;
+ uint chunkCountx;
+ uint *chunkPos; // offsets of chunks in file
+ uchar *chunkAck; // acknowledge of incoming chunks
+
+ uchar codeSymb; // symb for replace NUL-symb.
+
+ uint fileSize;
+ uint chunkMaxLen; // limit for outgoing chunk
+
+ DWORD lastTimestamp;
+ DWORD lastDelay;
+ bool asBinary;
+
+ // settings
+ uint dwSendInterval;
+ //uint dwChunkSize;
+
+ COLORREF rgbSent, rgbRecv, rgbUnSent, rgbToSend;
+#ifdef DEBUG
+ uint overhead;
+#endif
+
+ FILEECHO(HANDLE Contact);
+
+ void setState(DWORD state);
+ void updateProgress();
+ void updateTitle();
+
+ void perform(char *str);
+ void cmdACCEPT();
+ void cmdDACK(char *data);
+ void sendReq();
+ int sendCmd(int id, int cmd, char *szParam, char *szPrefix = NULL);
+
+ void cmdDATA(char *data);
+ void cmdEND();
+
+ int createTransfer();
+ void destroyTransfer();
+
+ void onSendTimer();
+ void onRecvTimer();
+ void incomeRequest(char *data);
+
+};
+
+void InitCRC32();
diff --git a/plugins/FileAsMessage/fileecho.dsp b/plugins/FileAsMessage/fileecho.dsp
new file mode 100644
index 0000000000..7bf64445c3
--- /dev/null
+++ b/plugins/FileAsMessage/fileecho.dsp
@@ -0,0 +1,148 @@
+# Microsoft Developer Studio Project File - Name="fileecho" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=fileecho - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "fileecho.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "fileecho.mak" CFG="fileecho - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "fileecho - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "fileecho - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "fileecho - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FILEECHO_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O1 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FILEECHO_EXPORTS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /dll /pdb:none /machine:I386 /out:"E:\Miranda IM\Plugins\disabled\FileAsMessage.dll"
+
+!ELSEIF "$(CFG)" == "fileecho - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FILEECHO_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /Gi /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FILEECHO_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/release/plugins/fileAsMessage.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "fileecho - Win32 Release"
+# Name "fileecho - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\dialog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\optionsdlg.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\dialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\res\abort.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\file.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\pause.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\play.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\refresh.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\resources.rc
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/plugins/FileAsMessage/fileecho.dsw b/plugins/FileAsMessage/fileecho.dsw
new file mode 100644
index 0000000000..a2f435f46d
--- /dev/null
+++ b/plugins/FileAsMessage/fileecho.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "fileecho"=".\fileecho.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/plugins/FileAsMessage/fileecho.opt b/plugins/FileAsMessage/fileecho.opt
new file mode 100644
index 0000000000..c53a9eee75
--- /dev/null
+++ b/plugins/FileAsMessage/fileecho.opt
Binary files differ
diff --git a/plugins/FileAsMessage/fileecho.vcproj b/plugins/FileAsMessage/fileecho.vcproj
new file mode 100644
index 0000000000..fef4b7301e
--- /dev/null
+++ b/plugins/FileAsMessage/fileecho.vcproj
@@ -0,0 +1,236 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="fileecho"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FILEECHO_EXPORTS"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/fileecho.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib"
+ OutputFile="E:\Miranda IM\Plugins\disabled\FileAsMessage.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\Release/fileAsMessage.pdb"
+ ImportLibrary=".\Release/fileAsMessage.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/fileecho.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1049"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FILEECHO_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/fileecho.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib"
+ OutputFile="../../bin/release/plugins/fileAsMessage.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/fileAsMessage.pdb"
+ ImportLibrary=".\Debug/fileAsMessage.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/fileecho.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1049"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="dialog.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;FILEECHO_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;FILEECHO_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="main.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;FILEECHO_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;FILEECHO_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="optionsdlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;FILEECHO_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;FILEECHO_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="dialog.h">
+ </File>
+ <File
+ RelativePath="main.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ <File
+ RelativePath="res\abort.ico">
+ </File>
+ <File
+ RelativePath="file.ico">
+ </File>
+ <File
+ RelativePath="res\pause.ico">
+ </File>
+ <File
+ RelativePath="res\play.ico">
+ </File>
+ <File
+ RelativePath="res\refresh.ico">
+ </File>
+ <File
+ RelativePath="resources.rc">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/plugins/FileAsMessage/m_Snapping_windows.h b/plugins/FileAsMessage/m_Snapping_windows.h
new file mode 100644
index 0000000000..3aa505fe74
--- /dev/null
+++ b/plugins/FileAsMessage/m_Snapping_windows.h
@@ -0,0 +1,42 @@
+#ifndef SNAPPING_WINDOWS_H
+#define SNAPPING_WINDOWS_H
+
+/*
+If you want to use SnappingWindows in you plugin you should add this code in WindowProc:
+
+BOOL CALLBACK YouWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CallSnappingWindowProc(hwnd,msg,wParam,lParam);
+ //
+ switch (msg)
+ {
+ case:.....
+ ...........
+ }
+ return ......
+}
+
+
+*/
+
+struct SnapWindowProc_t
+{
+ HWND hWnd;
+ //
+ SIZE m_szMoveOffset;
+ WPARAM wParam;
+ LPARAM lParam;
+ //
+ int Reserved1;
+ int Reserved2;
+ int Reserved3;
+};
+
+#define CallSnappingWindowProc(hwnd,nMessage,wParam,lParam) {static struct SnapWindowProc_t SnapInfo;\
+ if ((nMessage == WM_MOVING) || (nMessage == WM_NCLBUTTONDOWN) || (nMessage == WM_SYSCOMMAND)){\
+ SnapInfo.hWnd = hwnd;\
+ SnapInfo.wParam = wParam;\
+ SnapInfo.lParam = lParam;\
+ CallService("Utils/SnapWindowProc",(WPARAM)&SnapInfo,nMessage);}}
+
+#endif //SNAPPING_WINDOWS_H \ No newline at end of file
diff --git a/plugins/FileAsMessage/main.cpp b/plugins/FileAsMessage/main.cpp
new file mode 100644
index 0000000000..a1a9aaba3f
--- /dev/null
+++ b/plugins/FileAsMessage/main.cpp
@@ -0,0 +1,359 @@
+#include "main.h"
+#include "dialog.h"
+#include "resource.h"
+
+#include "IcoLib.h"
+
+#include <stdio.h>
+#include <time.h>
+
+PLUGINLINK *pluginLink;
+PLUGININFO pluginInfo =
+{
+ sizeof( PLUGININFO ),
+ SERVICE_TITLE,
+ PLUGIN_MAKE_VERSION( 0,0,2,4 ),
+ "file tranfer by using the messaging services - as plain text",
+ "Denis Stanishevskiy // StDenis",
+ "stdenformiranda(at)fromru(dot)com",
+ "Copyright (c) 2004, Denis Stanishevskiy",
+ PLUGIN_URL,
+ 0, 0
+};
+
+HANDLE hFileList;
+HINSTANCE hInst;
+
+char *szServiceTitle = SERVICE_TITLE;
+char *szServicePrefix = SERVICE_PREFIX;
+HANDLE hHookDbSettingChange, hHookContactAdded, hHookSkinIconsChanged;
+
+extern LRESULT CALLBACK OptionsDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+int idIcons[5] = {IDI_PLAY, IDI_PAUSE, IDI_REFRESH, IDI_STOP, IDI_SMALLICON};
+HICON hIcons[5];
+
+char *szIconId[5] =
+{
+ "FePlay",
+ "FePause",
+ "FeRefresh",
+ "FeStop",
+ "FeMain"
+};
+char *szIconName[5] =
+{
+ "Play",
+ "Pause",
+ "Revive",
+ "Stop",
+ "Main"
+};
+/*
+char *szIconGroup[5] =
+{
+ "gr1",
+ "gr3",
+ "gr2",
+ "gr3",
+ "gr1"
+};
+*/
+int iIconId[5] = {3,2,4,1,0};
+
+//
+// wParam - Section name
+// lParam - Icon ID
+//
+int OnSkinIconsChanged(WPARAM wParam,LPARAM lParam)
+{
+ int indx;
+/*
+ if(lParam == NULL)
+ return 0;
+ for(indx = 0; indx < ARRAY_SIZE(hIcons); indx++)
+ {
+ if(strcmp((char*)lParam, szIconId[indx]) == 0)
+ {
+ hIcons[indx] = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szIconId[indx]);
+ break;
+ }
+ }
+*/
+ for(indx = 0; indx < ARRAY_SIZE(hIcons); indx++)
+ hIcons[indx] = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szIconId[indx]);
+
+ WindowList_Broadcast(hFileList, WM_FE_SKINCHANGE, 0,0);
+
+ return 0;
+}
+
+int OnSettingChanged(WPARAM wParam,LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *cws=(DBCONTACTWRITESETTING*)lParam;
+ HWND hwnd;
+
+ hwnd = WindowList_Find(hFileList,(HANDLE)wParam);
+ PostMessage(hwnd, WM_FE_STATUSCHANGE, 0,0);
+ //OnSkinIconsChanged(0,0);
+ //PostMessage(hwnd, WM_FE_SKINCHANGE, 0,0);
+
+ return 0;
+}
+
+int OnContactAdded(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MS_PROTO_ADDTOCONTACT, wParam, (LPARAM)SERVICE_NAME);
+ return 0;
+}
+
+int OnRecvFile(WPARAM wParam, LPARAM lParam)
+{
+ HWND hwnd;
+ CLISTEVENT *clev = (CLISTEVENT*)lParam;
+
+ hwnd = WindowList_Find(hFileList,(HANDLE)clev->hContact);
+ if(IsWindow(hwnd))
+ {
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+ SetForegroundWindow(hwnd);
+ SetFocus(hwnd);
+ }
+ /*
+ else
+ {
+ if(hwnd != 0) WindowList_Remove(hFileList, hwnd);
+ FILEECHO *fe = new FILEECHO((HANDLE)clev->hContact);
+ fe->inSend = FALSE;
+ hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)DialogProc, (LPARAM)fe);
+ if(hwnd == NULL)
+ {
+ delete fe;
+ return 0;
+ }
+ //SendMessage(hwnd, WM_FE_SERVICE, 0, TRUE);
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+ }
+ */
+ return 1;
+}
+
+int OnSendFile(WPARAM wParam, LPARAM lParam)
+{
+ HWND hwnd;
+
+ hwnd = WindowList_Find(hFileList,(HANDLE)wParam);
+ if(IsWindow(hwnd))
+ {
+ SetForegroundWindow(hwnd);
+ SetFocus(hwnd);
+ }
+ else
+ {
+ if(hwnd != 0) WindowList_Remove(hFileList, hwnd);
+ FILEECHO *fe = new FILEECHO((HANDLE)wParam);
+ fe->inSend = TRUE;
+ hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)DialogProc, (LPARAM)fe);
+ if(hwnd == NULL)
+ {
+ delete fe;
+ return 0;
+ }
+ //SendMessage(hwnd, WM_FE_SERVICE, 0, TRUE);
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+ }
+ return 1;
+}
+
+int OnRecvMessage( WPARAM wParam, LPARAM lParam )
+{
+ CCSDATA *pccsd = (CCSDATA *)lParam;
+ PROTORECVEVENT *ppre = ( PROTORECVEVENT * )pccsd->lParam;
+ HWND hwnd;
+
+ if(strncmp(ppre->szMessage, szServicePrefix, strlen(szServicePrefix)))
+ return CallService( MS_PROTO_CHAINRECV, wParam, lParam );
+
+ hwnd = (HWND)WindowList_Find(hFileList, (HANDLE)pccsd->hContact);
+ if(!IsWindow(hwnd))
+ {
+ if(hwnd != 0) WindowList_Remove(hFileList, hwnd);
+ FILEECHO *fe = new FILEECHO((HANDLE)pccsd->hContact);
+ fe->inSend = FALSE;
+ hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)DialogProc, (LPARAM)fe);
+ if(hwnd == NULL)
+ {
+ delete fe;
+ return 0;
+ }
+ }
+ char *msg = strdup(ppre->szMessage + strlen(szServicePrefix));
+ PostMessage(hwnd, WM_FE_MESSAGE, (WPARAM)pccsd->hContact, (LPARAM)msg);
+
+ return 0;
+}
+
+int OnOptInitialise(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+
+ ZeroMemory(&odp, sizeof(odp));
+
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS);
+ odp.pszTitle = Translate(SERVICE_TITLE);
+ odp.pszGroup = Translate("Plugins");
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = (DLGPROC)OptionsDlgProc;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+
+ return 0;
+}
+
+//
+// MirandaPluginInfo()
+// Called by Miranda to get Version
+//
+PLUGININFO *MirandaPluginInfo( DWORD dwVersion )
+{
+/*
+ if(MessageBox(0,
+ "Achtung! This plugin is technology demo only. It didn't tested carefully.\n"
+ "Do you want to continue usage of this plugin?", SERVICE_TITLE,
+ MB_YESNO) != IDYES) return 0;
+//*/
+ if( dwVersion < PLUGIN_MAKE_VERSION( 0,3,3,0 ))return 0;
+ return &pluginInfo;
+}
+/*
+DWORD CreateSetting(char *name, DWORD defvalue)
+{
+ if(DBGetContactSettingDword(NULL, SERVICE_NAME, name, -1) == -1)
+ DBWriteContactSettingDword(NULL, SERVICE_NAME, name, defvalue);
+ else
+ defvalue = DBGetContactSettingDword(NULL, SERVICE_NAME, name, defvalue);
+ return defvalue;
+}
+*/
+
+int OnModulesLoaded(WPARAM wparam,LPARAM lparam)
+{
+ if(!ServiceExists(MS_SKIN2_ADDICON))
+ {
+ for(int indx = 0; indx < ARRAY_SIZE(hIcons); indx++)
+ hIcons[indx] = (HICON)LoadImage(hInst,MAKEINTRESOURCE(idIcons[indx]),IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0);
+ }
+ else
+ {
+ int indx;
+ SKINICONDESC sid;
+ char ModuleName[MAX_PATH];
+
+ ZeroMemory(&sid, sizeof(sid));
+ sid.cbSize = sizeof(sid);
+ sid.pszSection = Translate("fileAsMessage");
+ GetModuleFileName(hInst, ModuleName, sizeof(ModuleName));
+ for(indx = 0; indx < ARRAY_SIZE(hIcons); indx++)
+ {
+ //sid.pszSection = szIconGroup[indx];
+ sid.pszName = szIconId[indx];
+ sid.pszDescription = szIconName[indx];
+ sid.pszDefaultFile = ModuleName;
+ sid.iDefaultIndex = iIconId[indx];
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+ for(indx = 0; indx < ARRAY_SIZE(hIcons); indx++)
+ hIcons[indx] = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)szIconId[indx]);
+
+ hHookSkinIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, OnSkinIconsChanged);
+ }
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while(hContact)
+ {
+ if(!CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM)hContact, (LPARAM)SERVICE_NAME))
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)SERVICE_NAME);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+
+ CLISTMENUITEM mi;
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(CLISTMENUITEM);
+ mi.position = 200011;
+ mi.hIcon = hIcons[ICON_MAIN];
+ mi.pszName = Translate("File As Message...");
+ mi.pszService = SERVICE_NAME "/FESendFile";
+ mi.pszContactOwner = NULL;
+ mi.flags = CMIF_NOTOFFLINE;
+ CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, ( LPARAM )&mi);
+
+ return 0;
+}
+
+//
+// Startup initializing
+//
+int Load( PLUGINLINK *link )
+{
+ pluginLink = link;
+
+ InitCRC32();
+
+// for(int indx = 0; indx < ARRAY_SIZE(hIcons); indx++)
+// hIcons[indx] = (HICON)LoadImage(hInst,MAKEINTRESOURCE(idIcons[indx]),IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0);
+
+ hFileList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+
+ //CreateServiceFunction( SERVICE_NAME PS_GETCAPS, FEGetCaps );
+ CreateServiceFunction(SERVICE_NAME PSR_MESSAGE, OnRecvMessage);
+ CreateServiceFunction(SERVICE_NAME "/FESendFile", OnSendFile);
+ CreateServiceFunction(SERVICE_NAME "/FERecvFile", OnRecvFile);
+
+ PROTOCOLDESCRIPTOR pd;
+ memset(&pd, 0, sizeof( PROTOCOLDESCRIPTOR));
+ pd.cbSize = sizeof(PROTOCOLDESCRIPTOR);
+ pd.szName = SERVICE_NAME;
+ pd.type = PROTOTYPE_FILTER;
+ CallService(MS_PROTO_REGISTERMODULE, 0, ( LPARAM ) &pd);
+
+ HookEvent(ME_OPT_INITIALISE, OnOptInitialise);
+ HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+ hHookDbSettingChange = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, OnSettingChanged);
+ hHookContactAdded = HookEvent(ME_DB_CONTACT_ADDED, OnContactAdded);
+ hHookSkinIconsChanged = NULL;
+
+ return 0;
+}
+
+//
+// Unload()
+// Called by Miranda when Plugin is unloaded.
+//
+int Unload( void )
+{
+// if(hFileList)
+// WindowList_Broadcast(hFileList, WM_CLOSE, 0,0);
+ if(!ServiceExists(MS_SKIN2_ADDICON))
+ for(int indx = 0; indx < ARRAY_SIZE(hIcons); indx++)
+ DestroyIcon(hIcons[indx]);
+
+ if(hHookSkinIconsChanged != NULL)
+ UnhookEvent(hHookSkinIconsChanged);
+ UnhookEvent(hHookDbSettingChange);
+ UnhookEvent(hHookContactAdded);
+
+ return 0;
+}
+
+//
+// DllMain()
+//
+int WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID pReserved )
+{
+ hInst = hInstance;
+
+ if( dwReason == DLL_PROCESS_ATTACH )
+ DisableThreadLibraryCalls(hInstance);
+
+ return 1;
+}
diff --git a/plugins/FileAsMessage/main.h b/plugins/FileAsMessage/main.h
new file mode 100644
index 0000000000..66de382a63
--- /dev/null
+++ b/plugins/FileAsMessage/main.h
@@ -0,0 +1,59 @@
+//#include "AggressiveOptimize.h"
+
+#define _WIN32_WINNT 0x0501
+#include <windows.h>
+#include <stdio.h>
+
+#include "../../include/newpluginapi.h"
+#include "../../include/m_system.h"
+#include "../../include/m_database.h"
+#include "../../include/m_protomod.h"
+#include "../../include/m_protosvc.h"
+#include "../../include/m_langpack.h"
+#include "../../include/m_clist.h"
+#include "../../include/m_options.h"
+#include "../../include/m_clui.h"
+#include "../../include/m_clc.h"
+#include "../../include/m_utils.h"
+#include "../../include/m_skin.h"
+#include "../../include/m_popup.h"
+#include "../../include/m_message.h"
+#include "../../include/m_button.h"
+#include "../../include/m_netlib.h"
+#include "../../include/m_file.h"
+#include "../../include/win2k.h"
+
+#define ARRAY_SIZE(n) (sizeof(n)/sizeof(n[0]))
+
+#define MAXBUFSIZE 4096
+#define SERVICE_TITLE "file As Message"
+#define SERVICE_NAME "FileAsMessage"
+
+#define SERVICE_PREFIX "<%fAM-0023%>"
+
+#define PLUGIN_URL "http://miranda-im.org/download/details.php?action=viewfile&id=1811"
+#define NOPLUGIN_MESSAGE "\nIf you see this \"garbage\", probably you "\
+ "have no \"fileAsMessage\" plugin installed, see "\
+ PLUGIN_URL " for more information and download."
+extern char *szServiceTitle;
+extern char *szServicePrefix;
+
+#define WM_FE_MESSAGE WM_USER+100
+#define WM_FE_STATUSCHANGE WM_USER+101
+#define WM_FE_SKINCHANGE WM_USER+102
+
+extern HINSTANCE hInst;
+extern HANDLE hFileList;
+extern HANDLE hEventNewFile;
+
+extern HICON hIcons[5];
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int __declspec(dllexport) Load( PLUGINLINK *link );
+int __declspec(dllexport) Unload( void );
+ __declspec(dllexport) PLUGININFO *MirandaPluginInfo( DWORD dwVersion );
+#ifdef __cplusplus
+}
+#endif
diff --git a/plugins/FileAsMessage/main.rc b/plugins/FileAsMessage/main.rc
new file mode 100644
index 0000000000..73be51abff
--- /dev/null
+++ b/plugins/FileAsMessage/main.rc
@@ -0,0 +1,30 @@
+#include "windows.h"
+#include "resource.h"
+IDD_OPTIONS DIALOGEX 0,0,210,164
+FONT 8,"MS Shell Dlg"
+STYLE 0x50000008
+EXSTYLE 0x00010000
+BEGIN
+ CONTROL "Hide delay",IDC_STATIC,"Static",0x50020002,15,135,88,8,0x00000000
+ CONTROL "",IDC_HIDEDELAY,"Edit",0x50010080,108,132,45,14,0x00000200
+ CONTROL "ms",IDC_STATIC,"Static",0x50020000,155,117,33,8,0x00000000
+ CONTROL "Show delay",IDC_STATIC,"Static",0x50020002,15,117,88,8,0x00000000
+ CONTROL "",IDC_SHOWDELAY,"Edit",0x50010080,108,114,45,14,0x00000200
+ CONTROL "ms",IDC_STATIC,"Static",0x50020000,155,135,40,8,0x00000000
+ CONTROL "Screen position",IDC_STATIC,"Button",0x50000007,7,6,198,90,0x00000000
+ CONTROL "",IDC_DISABLED,"MButtonClass",0x10010000,100,46,16,14,0x00000000
+ CONTROL "",IDC_LEFT,"MButtonClass",0x10010000,14,46,16,14,0x00000000
+ CONTROL "",IDC_UPLEFT,"MButtonClass",0x10010000,14,17,16,14,0x00000000
+ CONTROL "",IDC_DOWNLEFT,"MButtonClass",0x10010000,14,76,16,14,0x00000000
+ CONTROL "",IDC_RIGHT,"MButtonClass",0x10010000,182,46,16,14,0x00000000
+ CONTROL "",IDC_UPRIGHT,"MButtonClass",0x10010000,182,17,16,14,0x00000000
+ CONTROL "",IDC_DOWNRIGHT,"MButtonClass",0x10010000,182,76,16,14,0x00000000
+ CONTROL "Delays",IDC_STATIC,"Button",0x50000007,8,99,198,59,0x00000000
+END
+IDI_DISABLED ICON DISCARDABLE "res/Disabled.ico"
+IDI_LEFT ICON DISCARDABLE "res/Left.ico"
+IDI_RIGHT ICON DISCARDABLE "res/Right.ico"
+IDI_UPLEFT ICON DISCARDABLE "res/LeftUp.ico"
+IDI_UPRIGHT ICON DISCARDABLE "res/RightUp.ico"
+IDI_DOWNLEFT ICON DISCARDABLE "res/LeftDown.ico"
+IDI_DOWNRIGHT ICON DISCARDABLE "res/RightDown.ico"
diff --git a/plugins/FileAsMessage/optionsdlg.cpp b/plugins/FileAsMessage/optionsdlg.cpp
new file mode 100644
index 0000000000..e39c574df2
--- /dev/null
+++ b/plugins/FileAsMessage/optionsdlg.cpp
@@ -0,0 +1,118 @@
+#include "main.h"
+#include "resource.h"
+
+#include <commctrl.h>
+
+#pragma comment(lib, "comctl32.lib")
+
+
+DWORD settingDefault[] =
+{
+ RGB(64,255,64),
+ RGB(255,255,64),
+ RGB(128,128,128),
+ RGB(192,192,192),
+
+ 6000,
+ 5000
+};
+char *settingName[] =
+{
+ "colorRecv",
+ "colorSent",
+ "colorUnsent",
+ "colorTosend",
+
+ "SendDelay",
+ "ChunkSize"
+};
+int settingId[] =
+{
+ IDC_RECV,
+ IDC_SENT,
+ IDC_UNSENT,
+ IDC_TOSEND,
+
+ -IDC_SENDDELAY,
+ -IDC_CHUNKSIZE
+};
+//
+// OptionsDlgProc()
+// this handles the options page
+// verwaltet die Optionsseite
+//
+LRESULT CALLBACK OptionsDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ switch( uMsg )
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ for(int indx = 0; indx < ARRAY_SIZE(settingId); indx++)
+ if(settingId[indx] > 0)
+ SendDlgItemMessage(hwndDlg, settingId[indx], CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, SERVICE_NAME, settingName[indx], settingDefault[indx]));
+ else
+ SetDlgItemInt(hwndDlg, -settingId[indx], DBGetContactSettingDword(NULL, SERVICE_NAME, settingName[indx], settingDefault[indx]), FALSE);
+
+ CheckDlgButton(hwndDlg, IDC_ALPHANUM, DBGetContactSettingDword(NULL, SERVICE_NAME, "base64", 1)?BST_CHECKED:BST_UNCHECKED);
+
+ return TRUE;
+
+ }
+ case WM_COMMAND:
+ {
+ if(//MAKEWPARAM(IDC_AUTO, BN_CLICKED) != wParam ||
+ MAKEWPARAM(IDC_ALPHANUM, BN_CLICKED) != wParam)
+ {
+ for(int indx = 0; indx < ARRAY_SIZE(settingId); indx++)
+ {
+ if(LOWORD(wParam) == abs(settingId[indx]))
+ {
+ if(settingId[indx] > 0)
+ {
+ if(HIWORD(wParam) != CPN_COLOURCHANGED) return FALSE;
+ }
+ else
+ {
+ if(HIWORD(wParam) != EN_CHANGE) return FALSE;
+ if((HWND)lParam != GetFocus()) return FALSE;
+ }
+ }
+ }
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0,0);
+ break;
+ }
+ case WM_DESTROY:
+ return FALSE;
+
+ case WM_NOTIFY:
+ {
+ if((((NMHDR*)lParam)->idFrom == 0) && (((LPNMHDR)lParam)->code == PSN_APPLY))
+ {
+ int value;
+ BOOL succ;
+
+ for(int indx = 0; indx < ARRAY_SIZE(settingId); indx++)
+ {
+ if(settingId[indx] > 0)
+ value = SendDlgItemMessage(hwndDlg, settingId[indx], CPM_GETCOLOUR, 0, 0);
+ else
+ {
+ value = GetDlgItemInt(hwndDlg, -settingId[indx], &succ, FALSE);
+ if(!succ) value = settingDefault[indx];
+ }
+ DBWriteContactSettingDword(NULL,SERVICE_NAME,settingName[indx], value);
+ }
+ DBWriteContactSettingDword(NULL,SERVICE_NAME, "base64", (IsDlgButtonChecked(hwndDlg, IDC_ALPHANUM) == BST_CHECKED)?1:0);
+
+ return TRUE;
+ }
+ break;
+ }
+
+ }
+
+ return FALSE;
+}
diff --git a/plugins/FileAsMessage/res/abort.ico b/plugins/FileAsMessage/res/abort.ico
new file mode 100644
index 0000000000..4b92cd4d1a
--- /dev/null
+++ b/plugins/FileAsMessage/res/abort.ico
Binary files differ
diff --git a/plugins/FileAsMessage/res/file.ico b/plugins/FileAsMessage/res/file.ico
new file mode 100644
index 0000000000..2649b435ef
--- /dev/null
+++ b/plugins/FileAsMessage/res/file.ico
Binary files differ
diff --git a/plugins/FileAsMessage/res/pause.ico b/plugins/FileAsMessage/res/pause.ico
new file mode 100644
index 0000000000..f99a5e147a
--- /dev/null
+++ b/plugins/FileAsMessage/res/pause.ico
Binary files differ
diff --git a/plugins/FileAsMessage/res/play.ico b/plugins/FileAsMessage/res/play.ico
new file mode 100644
index 0000000000..4e37108cba
--- /dev/null
+++ b/plugins/FileAsMessage/res/play.ico
Binary files differ
diff --git a/plugins/FileAsMessage/res/refresh.ico b/plugins/FileAsMessage/res/refresh.ico
new file mode 100644
index 0000000000..ceb0317065
--- /dev/null
+++ b/plugins/FileAsMessage/res/refresh.ico
Binary files differ
diff --git a/plugins/FileAsMessage/resource.h b/plugins/FileAsMessage/resource.h
new file mode 100644
index 0000000000..b6a254dcf7
--- /dev/null
+++ b/plugins/FileAsMessage/resource.h
@@ -0,0 +1,45 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resources.rc
+//
+#define IDC_PLAY 1
+#define IDD_DIALOG1 101
+#define IDD_MAIN 101
+#define IDI_SMALLICON 102
+#define IDD_OPTIONS 103
+#define IDI_STOP 104
+#define IDI_PAUSE 105
+#define IDI_PLAY 106
+#define IDI_REFRESH 107
+#define IDC_FILENAME 1001
+#define IDC_BROWSE 1002
+#define IDC_STOP 1003
+#define IDC_REFRESH 1004
+#define IDC_PROGRESS 1005
+#define IDC_STATUS 1006
+#define IDC_FILESIZE 1008
+#define IDC_LIST1 1020
+#define IDC_ALPHANUM 1022
+#define IDC_HIDEDELAY 1051
+#define IDC_CHUNKSIZE 1051
+#define IDC_SHOWDELAY 1052
+#define IDC_SENDDELAY 1052
+#define IDC_SENTCOLOR 1053
+#define IDC_UNSENT 1053
+#define IDC_SENTCOLOR2 1054
+#define IDC_SENT 1054
+#define IDC_SENTCOLOR3 1055
+#define IDC_TOSEND 1055
+#define IDC_SENTCOLOR4 1056
+#define IDC_RECV 1056
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 108
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1022
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/FileAsMessage/resources.rc b/plugins/FileAsMessage/resources.rc
new file mode 100644
index 0000000000..cbca7fcacc
--- /dev/null
+++ b/plugins/FileAsMessage/resources.rc
@@ -0,0 +1,156 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Russian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+#ifdef _WIN32
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_MAIN DIALOGEX 0, 0, 252, 75
+STYLE DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION |
+ WS_SYSMENU
+CAPTION "fileAsMessage"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "Filename:",IDC_STATIC,7,7,31,8
+ EDITTEXT IDC_FILENAME,7,16,221,14,ES_AUTOHSCROLL
+ LTEXT "Size:",IDC_FILESIZE,7,32,238,8
+ PUSHBUTTON "...",IDC_BROWSE,232,16,13,14
+ LTEXT "",IDC_PROGRESS,43,44,202,14,0,WS_EX_STATICEDGE
+ CONTROL "",IDC_PLAY,"MButtonClass",WS_TABSTOP,7,44,16,14
+ CONTROL "",IDC_STOP,"MButtonClass",WS_TABSTOP,25,44,16,14
+END
+
+IDD_OPTIONS DIALOGEX 0, 0, 241, 181
+STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "",IDC_UNSENT,"ColourPicker",WS_GROUP | WS_TABSTOP,124,
+ 106,39,12,WS_EX_NOPARENTNOTIFY
+ RTEXT "Chunk size",IDC_STATIC,9,41,92,8
+ EDITTEXT IDC_CHUNKSIZE,123,39,41,14,ES_AUTOHSCROLL | NOT
+ WS_BORDER,WS_EX_CLIENTEDGE
+ LTEXT "ms",IDC_STATIC,170,23,28,8
+ RTEXT "Delays between sends",IDC_STATIC,9,23,93,8
+ EDITTEXT IDC_SENDDELAY,123,20,41,14,ES_AUTOHSCROLL | NOT
+ WS_BORDER,WS_EX_CLIENTEDGE
+ LTEXT "bytes",IDC_STATIC,170,41,28,8
+ GROUPBOX "Transfer settings",IDC_STATIC,5,5,230,67
+ GROUPBOX "Appearance",IDC_STATIC,5,75,230,100
+ CONTROL "",IDC_SENT,"ColourPicker",WS_GROUP | WS_TABSTOP,124,124,
+ 39,12,WS_EX_NOPARENTNOTIFY
+ CONTROL "",IDC_TOSEND,"ColourPicker",WS_GROUP | WS_TABSTOP,124,
+ 141,39,12,WS_EX_NOPARENTNOTIFY
+ CONTROL "",IDC_RECV,"ColourPicker",WS_GROUP | WS_TABSTOP,124,89,
+ 39,12,WS_EX_NOPARENTNOTIFY
+ RTEXT "Unsent",IDC_STATIC,15,108,86,8
+ RTEXT "Sent",IDC_STATIC,15,126,86,8
+ RTEXT "To send",IDC_STATIC,15,143,86,8
+ RTEXT "Received",IDC_STATIC,15,91,86,8
+ CONTROL "Use only alphanumeric encoding on transfer",
+ IDC_ALPHANUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,57,
+ 217,10
+ LTEXT "Extra options: Events » File Transfers, ""Receiving files"" group",
+ IDC_STATIC,10,160,220,8
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_MAIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 245
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 58
+ END
+
+ IDD_OPTIONS, DIALOG
+ BEGIN
+ RIGHTMARGIN, 221
+ BOTTOMMARGIN, 163
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_SMALLICON ICON DISCARDABLE "res\\file.ico"
+IDI_STOP ICON DISCARDABLE "res\\abort.ico"
+IDI_PAUSE ICON DISCARDABLE "res\\pause.ico"
+IDI_PLAY ICON DISCARDABLE "res\\play.ico"
+IDI_REFRESH ICON DISCARDABLE "res\\refresh.ico"
+#endif // Russian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+