summaryrefslogtreecommitdiff
path: root/Plugins/emoticons/emoticons.cpp
diff options
context:
space:
mode:
authorpescuma <pescuma@c086bb3d-8645-0410-b8da-73a8550f86e7>2008-03-17 01:25:20 +0000
committerpescuma <pescuma@c086bb3d-8645-0410-b8da-73a8550f86e7>2008-03-17 01:25:20 +0000
commitb1bcfe11e40f2eb7e53ef0f8d992df0fb179b173 (patch)
tree636f4cf1261e469e708f200800880a2a805e1c9b /Plugins/emoticons/emoticons.cpp
parentd99eb14835a65e3cf3a97683f215dfb83565b844 (diff)
Allow URLs in emoticon packs
Flash emoticons Added Skype and Sametime emoticons Option to select which frame to show in selection window (for animated gif and swf) git-svn-id: http://pescuma.googlecode.com/svn/trunk/Miranda@70 c086bb3d-8645-0410-b8da-73a8550f86e7
Diffstat (limited to 'Plugins/emoticons/emoticons.cpp')
-rw-r--r--Plugins/emoticons/emoticons.cpp380
1 files changed, 359 insertions, 21 deletions
diff --git a/Plugins/emoticons/emoticons.cpp b/Plugins/emoticons/emoticons.cpp
index 54f8175..c964fd5 100644
--- a/Plugins/emoticons/emoticons.cpp
+++ b/Plugins/emoticons/emoticons.cpp
@@ -30,7 +30,7 @@ PLUGININFOEX pluginInfo={
#else
"Emoticons",
#endif
- PLUGIN_MAKE_VERSION(0,0,1,5),
+ PLUGIN_MAKE_VERSION(0,0,1,6),
"Emoticons",
"Ricardo Pescuma Domenecci",
"",
@@ -797,7 +797,7 @@ int RestoreInput(RichEditCtrl &rec, int start = 0, int end = -1)
ITooltipData *ttd = NULL;
hr = reObj.poleobj->QueryInterface(__uuidof(ITooltipData), (void**) &ttd);
reObj.poleobj->Release();
- if (SUCCEEDED(hr) && ttd == NULL)
+ if (FAILED(hr) || ttd == NULL)
continue;
BSTR hint = NULL;
@@ -1276,7 +1276,7 @@ void LoadModules()
}
}
-void HandleEmoLine(Module *m, char *tmp)
+void HandleEmoLine(Module *m, char *tmp, char *group)
{
int len = strlen(tmp);
int state = 0;
@@ -1328,6 +1328,7 @@ void HandleEmoLine(Module *m, char *tmp)
case 1:
e = new Emoticon();
e->name = mir_t2a(txt);
+ e->group = group;
MIR_FREE(txt);
break;
case 3:
@@ -1358,6 +1359,7 @@ BOOL LoadModule(Module *m)
char tmp[1024];
char c;
int pos = 0;
+ char *group = NULL;
do
{
c = fgetc(file);
@@ -1365,7 +1367,24 @@ BOOL LoadModule(Module *m)
if (c == '\n' || c == '\r' || c == EOF || pos >= MAX_REGS(tmp) - 1)
{
tmp[pos] = 0;
- HandleEmoLine(m, tmp);
+ strtrim(tmp);
+ size_t len = strlen(tmp);
+
+ if (tmp[0] == '#')
+ {
+ // Do nothing
+ }
+ else if (tmp[0] == '[' && tmp[len-1] == ']')
+ {
+ tmp[len-1] = '\0';
+ strtrim(&tmp[1]);
+ group = mir_strdup(&tmp[1]);
+ }
+ else
+ {
+ HandleEmoLine(m, tmp, group);
+ }
+
pos = 0;
}
else
@@ -1427,7 +1446,7 @@ BOOL isValidExtension(char *name)
&& strcmp(p, ".jpeg") != 0
&& strcmp(p, ".gif") != 0
&& strcmp(p, ".png") != 0
- /*&& strcmp(p, ".swf") != 0*/)
+ && strcmp(p, ".swf") != 0)
return FALSE;
return TRUE;
}
@@ -1443,7 +1462,7 @@ BOOL isValidExtension(WCHAR *name)
&& lstrcmpW(p, L".jpeg") != 0
&& lstrcmpW(p, L".gif") != 0
&& lstrcmpW(p, L".png") != 0
- /*&& lstrcmpW(p, L".swf") != 0*/)
+ && lstrcmpW(p, L".swf") != 0)
return FALSE;
return TRUE;
}
@@ -1456,10 +1475,11 @@ EmoticonImage * HandleMepLine(EmoticonPack *p, char *line)
int state = 0;
int pos;
int module_pos = -1;
+ BOOL noDelimiter;
EmoticonImage *img = NULL;
- for(int i = 0; i < len && state < 4; i++)
+ for(int i = 0; i <= len && state < 6; i++)
{
char c = line[i];
if (c == ' ')
@@ -1467,19 +1487,38 @@ EmoticonImage * HandleMepLine(EmoticonPack *p, char *line)
if ((state % 2) == 0)
{
- if (c != '"')
+ if (c == '"')
+ {
+ state ++;
+ pos = i+1;
+ noDelimiter = FALSE;
+ }
+ else if (c != '=' && c != ',' && c != ' ' && c != '\t' && c != '\r' && c != '\n')
+ {
+ state ++;
+ pos = i;
+ noDelimiter = TRUE;
+ }
+ else
+ {
continue;
-
- state ++;
- pos = i+1;
+ }
}
else
{
if (state == 1 && c == '\\') // Module name
module_pos = i;
- if (c != '"')
- continue;
+ if (noDelimiter)
+ {
+ if (c != ' ' && c != ',' && c != '=' && c != '\0')
+ continue;
+ }
+ else
+ {
+ if (c != '"')
+ continue;
+ }
line[i] = 0;
@@ -1503,12 +1542,15 @@ EmoticonImage * HandleMepLine(EmoticonPack *p, char *line)
switch(state)
{
case 1:
+ {
img = new EmoticonImage();
img->pack = p;
img->name = txt;
img->module = module;
break;
+ }
case 3:
+ {
if (!isValidExtension(txt))
{
delete img;
@@ -1536,6 +1578,13 @@ EmoticonImage * HandleMepLine(EmoticonPack *p, char *line)
img->relPath = txt;
}
break;
+ }
+ case 5:
+ {
+ img->selectionFrame = max(0, atoi(txt) - 1);
+ mir_free(txt);
+ break;
+ }
}
state++;
@@ -1596,7 +1645,11 @@ BOOL LoadPack(EmoticonPack *pack)
tmp[pos] = 0;
strtrim(tmp);
- if (strnicmp("Name:", tmp, 5) == 0)
+ if (tmp[0] == '#')
+ {
+ // Do nothing
+ }
+ else if (strnicmp("Name:", tmp, 5) == 0)
{
char *name = strtrim(&tmp[5]);
if (name[0] != '\0')
@@ -1770,10 +1823,7 @@ void FillModuleImages(EmoticonPack *pack)
if (e->img != NULL)
continue;
- TCHAR err[1024];
- mir_sntprintf(err, MAX_REGS(err), _T(" *** The pack '%s' does not have the emoticon '") _T(TCHAR_STR_PARAM) _T("' needed by ") _T(TCHAR_STR_PARAM) _T("\n"),
- pack->description, e->name, m->name);
- OutputDebugString(err);
+ log(" *** The pack '" TCHAR_STR_PARAM "' does not have the emoticon '%s' needed by %s\n", pack->description, e->name, m->name);
}
}
}
@@ -2015,10 +2065,286 @@ void EmoticonImage::Download()
if (FileExists(tmp))
return;
- downloadQueue->AddIfDontHave(0, (HANDLE) this);
+ downloadQueue->AddIfDontHave(1000, (HANDLE) this);
+}
+
+struct ANIMATED_GIF_DATA
+{
+ FIMULTIBITMAP *multi;
+ FIBITMAP *dib;
+ int frameCount;
+ RGBQUAD background;
+ int width;
+ int height;
+ BOOL transparent;
+
+ struct {
+ int top;
+ int left;
+ int width;
+ int height;
+ int disposal_method;
+ } frame;
+};
+
+BOOL AnimatedGifGetData(ANIMATED_GIF_DATA &ag)
+{
+ FIBITMAP *page = fei->FI_LockPage(ag.multi, 0);
+ if (page == NULL)
+ return FALSE;
+
+ // Get info
+ FITAG *tag = NULL;
+ if (!fei->FI_GetMetadata(FIMD_ANIMATION, page, "LogicalWidth", &tag))
+ goto ERR;
+ ag.width = *(WORD *)fei->FI_GetTagValue(tag);
+
+ if (!fei->FI_GetMetadata(FIMD_ANIMATION, page, "LogicalHeight", &tag))
+ goto ERR;
+ ag.height = *(WORD *)fei->FI_GetTagValue(tag);
+
+ if (fei->FI_HasBackgroundColor(page))
+ fei->FI_GetBackgroundColor(page, &ag.background);
+
+ fei->FI_UnlockPage(ag.multi, page, FALSE);
+ return TRUE;
+
+ERR:
+ fei->FI_UnlockPage(ag.multi, page, FALSE);
+ return FALSE;
+}
+
+
+void AnimatedGifMountFrame(ANIMATED_GIF_DATA &ag, int page)
+{
+ FIBITMAP *dib = fei->FI_LockPage(ag.multi, page);
+ if (dib == NULL)
+ return;
+
+ FITAG *tag = NULL;
+ if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "FrameLeft", &tag))
+ ag.frame.left = *(WORD *)fei->FI_GetTagValue(tag);
+ else
+ ag.frame.left = 0;
+
+ if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "FrameTop", &tag))
+ ag.frame.top = *(WORD *)fei->FI_GetTagValue(tag);
+ else
+ ag.frame.top = 0;
+
+ if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "DisposalMethod", &tag))
+ ag.frame.disposal_method = *(BYTE *)fei->FI_GetTagValue(tag);
+ else
+ ag.frame.disposal_method = 0;
+
+ ag.frame.width = fei->FI_GetWidth(dib);
+ ag.frame.height = fei->FI_GetHeight(dib);
+
+
+ //decode page
+ int palSize = fei->FI_GetColorsUsed(dib);
+ RGBQUAD *pal = fei->FI_GetPalette(dib);
+ BOOL have_transparent = FALSE;
+ int transparent_color = -1;
+ if( fei->FI_IsTransparent(dib) ) {
+ int count = fei->FI_GetTransparencyCount(dib);
+ BYTE *table = fei->FI_GetTransparencyTable(dib);
+ for( int i = 0; i < count; i++ ) {
+ if( table[i] == 0 ) {
+ ag.transparent = TRUE;
+ have_transparent = TRUE;
+ transparent_color = i;
+ break;
+ }
+ }
+ }
+
+ //copy page data into logical buffer, with full alpha opaqueness
+ for( int y = 0; y < ag.frame.height; y++ ) {
+ RGBQUAD *scanline = (RGBQUAD *)fei->FI_GetScanLine(ag.dib, ag.height - (y + ag.frame.top) - 1) + ag.frame.left;
+ BYTE *pageline = fei->FI_GetScanLine(dib, ag.frame.height - y - 1);
+ for( int x = 0; x < ag.frame.width; x++ ) {
+ if( !have_transparent || *pageline != transparent_color ) {
+ *scanline = pal[*pageline];
+ scanline->rgbReserved = 255;
+ }
+ scanline++;
+ pageline++;
+ }
+ }
+
+ fei->FI_UnlockPage(ag.multi, dib, FALSE);
}
+
+HBITMAP LoadAnimatedGifFrame(char *filename, int frame, DWORD *transp)
+{
+ HBITMAP ret = NULL;
+ ANIMATED_GIF_DATA ag = {0};
+ int x, y, i;
+
+ FREE_IMAGE_FORMAT fif = fei->FI_GetFileType(filename, 0);
+ if(fif == FIF_UNKNOWN)
+ fif = fei->FI_GetFIFFromFilename(filename);
+
+ ag.multi = fei->FI_OpenMultiBitmap(fif, filename, FALSE, TRUE, FALSE, GIF_LOAD256);
+ if (ag.multi == NULL)
+ return NULL;
+
+ ag.frameCount = fei->FI_GetPageCount(ag.multi);
+ if (ag.frameCount <= 1)
+ goto ERR;
+
+ if (!AnimatedGifGetData(ag))
+ goto ERR;
+
+ //allocate entire logical area
+ ag.dib = fei->FI_Allocate(ag.width, ag.height, 32, 0, 0, 0);
+ if (ag.dib == NULL)
+ goto ERR;
+
+ //fill with background color to start
+ for (y = 0; y < ag.height; y++)
+ {
+ RGBQUAD *scanline = (RGBQUAD *) fei->FI_GetScanLine(ag.dib, y);
+ for (x = 0; x < ag.width; x++)
+ *scanline++ = ag.background;
+ }
+
+ for (i = 0; i <= frame && i < ag.frameCount; i++)
+ AnimatedGifMountFrame(ag, i);
+
+ ret = fei->FI_CreateHBITMAPFromDIB(ag.dib);
+
+ if (transp != NULL)
+ *transp = ag.transparent;
+
+ERR:
+ if (ag.multi != NULL)
+ fei->FI_CloseMultiBitmap(ag.multi, 0);
+ if (ag.dib != NULL)
+ fei->FI_Unload(ag.dib);
+
+ return ret;
+}
+
+
+HBITMAP LoadFlashBitmap(char *filename, int frame = 0)
+{
+ typedef HRESULT (WINAPI *LPAtlAxAttachControl)(IUnknown* pControl, HWND hWnd, IUnknown** ppUnkContainer);
+ static LPAtlAxAttachControl AtlAxAttachControl3 = NULL;
+
+ if (AtlAxAttachControl3 == (LPAtlAxAttachControl) -1)
+ {
+ return NULL;
+ }
+ else if (AtlAxAttachControl3 == NULL)
+ {
+ HMODULE atl = LoadLibrary(_T("atl"));
+ if (atl == NULL)
+ {
+ AtlAxAttachControl3 = (LPAtlAxAttachControl) -1;
+ return NULL;
+ }
+ void* init = GetProcAddress(atl, "AtlAxWinInit");
+ AtlAxAttachControl3 = (LPAtlAxAttachControl) GetProcAddress(atl, "AtlAxAttachControl");
+ if (init == NULL || AtlAxAttachControl3 == NULL)
+ {
+ AtlAxAttachControl3 = (LPAtlAxAttachControl) -1;
+ return NULL;
+ }
+ _asm call init;
+ }
+
+ int width = 40;
+ int height = 40;
+ IShockwaveFlash *flash = NULL;
+ IViewObjectEx *viewObject = NULL;
+ HRESULT hr;
+ HWND hWindow = NULL;
+ HBITMAP hBmp = NULL;
+ HDC hdc = NULL;
+ BOOL succeded = FALSE;
+ double val;
+
+ hWindow = CreateWindow(_T("AtlAxWin"), _T(""), WS_POPUP, 0, 0, width, height, NULL, (HMENU) 0, hInst, NULL);
+ if (hWindow == NULL) goto err;
+
+ hr = CoCreateInstance(__uuidof(ShockwaveFlash), 0, CLSCTX_INPROC_SERVER, __uuidof(IShockwaveFlash), (void **) &flash);
+ if (FAILED(hr)) goto err;
+
+ hr = AtlAxAttachControl3(flash, hWindow, 0);
+ if (FAILED(hr)) goto err;
+
+ {
+ WCHAR *tmp = mir_a2u(filename);
+ BSTR url = SysAllocString(tmp);
+
+ hr = flash->LoadMovie(0, url);
+
+ SysFreeString(url);
+ mir_free(tmp);
+ }
+
+ if (FAILED(hr)) goto err;
+
+ hr = flash->TGetPropertyAsNumber(L"/", 8, &val);
+ if (FAILED(hr)) goto err;
+ width = (int)(val + 0.5);
+
+ hr = flash->TGetPropertyAsNumber(L"/", 9, &val);
+ if (FAILED(hr)) goto err;
+ height = (int)(val + 0.5);
+
+ MoveWindow(hWindow, 0, 0, width, height, FALSE);
+
+ hr = flash->GotoFrame(frame);
+ if (FAILED(hr)) goto err;
+
+ hr = flash->QueryInterface(__uuidof(IViewObjectEx), (void **)&viewObject);
+ if (FAILED(hr)) goto err;
+
+ hBmp = CreateBitmap32(width, height);
+
+ hdc = CreateCompatibleDC(NULL);
+ SelectObject(hdc, hBmp);
+ SetBkMode(hdc, TRANSPARENT);
+
+ {
+ RECTL rectl = { 0, 0, width, height };
+ hr = viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdc, &rectl, &rectl, NULL, NULL);
+ if (FAILED(hr)) goto err;
+ }
+
+ succeded = TRUE;
+
+err:
+ if (hdc != NULL)
+ DeleteDC(hdc);
+
+ if (viewObject != NULL)
+ viewObject->Release();
+
+ if (flash != NULL)
+ flash->Release();
+
+ if (hWindow != NULL)
+ DestroyWindow(hWindow);
+
+ if (succeded)
+ {
+ return hBmp;
+ }
+ else
+ {
+ if (hBmp != NULL)
+ DeleteObject(hBmp);
+
+ return NULL;
+ }
+}
+
void EmoticonImage::Load(int &max_height, int &max_width)
{
if (img != NULL)
@@ -2033,11 +2359,23 @@ void EmoticonImage::Load(int &max_height, int &max_width)
}
DWORD transp;
-
char tmp[1024];
mir_snprintf(tmp, MAX_REGS(tmp), "%s\\%s", pack->path, relPath);
- img = (HBITMAP) CallService(MS_AV_LOADBITMAP32, (WPARAM) &transp, (LPARAM) tmp);
+ if (strcmp(&tmp[strlen(tmp)-4], ".swf") == 0)
+ {
+ img = LoadFlashBitmap(tmp, selectionFrame);
+ transp = TRUE;
+ }
+ else
+ {
+ // Try to get a frame
+ if (selectionFrame > 1)
+ img = LoadAnimatedGifFrame(tmp, selectionFrame, &transp);
+
+ if (img == NULL)
+ img = (HBITMAP) CallService(MS_AV_LOADBITMAP32, (WPARAM) &transp, (LPARAM) tmp);
+ }
if (img == NULL)
return;