summaryrefslogtreecommitdiff
path: root/plugins/FloatingContacts/src
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-07-18 07:52:13 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-07-18 07:52:13 +0000
commit70d04c9b21955c34070ee466693403e2b00870e1 (patch)
treea891633004c655fbc3448803cffa0d62855409d0 /plugins/FloatingContacts/src
parent2b556a0908dfa1c12400ec9ac22a00b39bc17136 (diff)
FirstRun, FlashAvatars, FloatingContacts: changed folder structure
git-svn-id: http://svn.miranda-ng.org/main/trunk@1008 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/FloatingContacts/src')
-rw-r--r--plugins/FloatingContacts/src/bitmap_funcs.cpp1234
-rw-r--r--plugins/FloatingContacts/src/bitmap_funcs.h127
-rw-r--r--plugins/FloatingContacts/src/filedrop.cpp368
-rw-r--r--plugins/FloatingContacts/src/filedrop.h26
-rw-r--r--plugins/FloatingContacts/src/fltcont.h191
-rw-r--r--plugins/FloatingContacts/src/main.cpp1268
-rw-r--r--plugins/FloatingContacts/src/options.cpp1171
-rw-r--r--plugins/FloatingContacts/src/resource.h75
-rw-r--r--plugins/FloatingContacts/src/stdhdr.h64
-rw-r--r--plugins/FloatingContacts/src/thumbs.cpp1013
-rw-r--r--plugins/FloatingContacts/src/thumbs.h74
-rw-r--r--plugins/FloatingContacts/src/version.h23
12 files changed, 5634 insertions, 0 deletions
diff --git a/plugins/FloatingContacts/src/bitmap_funcs.cpp b/plugins/FloatingContacts/src/bitmap_funcs.cpp
new file mode 100644
index 0000000000..334bf98abe
--- /dev/null
+++ b/plugins/FloatingContacts/src/bitmap_funcs.cpp
@@ -0,0 +1,1234 @@
+/*
+Popup Plus plugin for Miranda IM
+
+Copyright © 2002 Luca Santarelli,
+ © 2004-2007 Victor Pavlychko
+
+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; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdhdr.h"
+#include "bitmap_funcs.h"
+
+#include <m_png.h>
+#include <math.h>
+
+#define PU_FONT_THRESHOLD 96
+#define PU_BMP_ACCURATE_ARITHMETICS
+
+#ifdef PU_BMP_ACCURATE_ARITHMETICS
+ #define PU_DIV255(x) ((x)/255)
+ #define PU_DIV128(x) ((x)/128)
+ typedef float pu_koef;
+#else
+ #define PU_DIV255(x) ((x)>>8)
+ #define PU_DIV128(x) ((x)>>7)
+ typedef long pu_koef;
+#endif
+
+MyBitmap::MyBitmap()
+{
+ dcBmp = 0;
+ hBmp = 0;
+ bits = 0;
+ width = height = 0;
+ bitsSave = 0;
+}
+
+MyBitmap::MyBitmap(int w, int h)
+{
+ dcBmp = 0;
+ hBmp = 0;
+ bits = 0;
+ width = height = 0;
+ bitsSave = 0;
+ allocate(w,h);
+}
+
+MyBitmap::MyBitmap(const char *fn, const char *fnAlpha)
+{
+ dcBmp = 0;
+ hBmp = 0;
+ bits = 0;
+ width = height = 0;
+ bitsSave = 0;
+ loadFromFile(fn, fnAlpha);
+}
+
+MyBitmap::~MyBitmap()
+{
+ if (bitsSave)
+ delete [] bitsSave;
+ free();
+}
+
+void MyBitmap::setAlpha(BYTE level)
+{
+ if (!bits) return;
+
+ GdiFlush();
+ for (int i = 0; i < width*height; i++)
+ {
+ if (bits[i] & 0xff000000)
+ {
+ bits[i] = rgba(getr(bits[i])*level/255, getg(bits[i])*level/255, getb(bits[i])*level/255, geta(bits[i])*level/255);
+ } else
+ {
+ bits[i] = rgba(getr(bits[i])*level/255, getg(bits[i])*level/255, getb(bits[i])*level/255, level);
+ }
+ }
+}
+
+void MyBitmap::setAlphaRect(int x1, int y1, int x2, int y2, BYTE level)
+{
+ if (!bits) return;
+
+ GdiFlush();
+ for (int i = y1; i < y2; i++)
+ for (int j = x1; j < x2; j++) {
+ int idx = i * width + j;
+ if (bits[idx] & 0xff000000)
+ bits[idx] = rgba(getr(bits[idx])*level/255, getg(bits[idx])*level/255, getb(bits[idx])*level/255, geta(bits[idx])*level/255);
+ else
+ bits[idx] = rgba(getr(bits[idx])*level/255, getg(bits[idx])*level/255, getb(bits[idx])*level/255, level);
+ }
+}
+
+void MyBitmap::makeOpaque()
+{
+ if (!bits) return;
+
+ GdiFlush();
+ for (int i = 0; i < width*height; i++)
+ bits[i] |= 0xff000000;
+}
+
+void MyBitmap::makeOpaqueRect(int x1, int y1, int x2, int y2)
+{
+ if (!bits) return;
+
+ GdiFlush();
+ for (int i = y1; i < y2; i++)
+ for (int j = x1; j < x2; j++) {
+ int idx = i * width + j;
+ bits[idx] |= 0xff000000;
+ }
+}
+
+void MyBitmap::saveAlpha(int x, int y, int w, int h)
+{
+ if (bitsSave)
+ delete [] bitsSave;
+
+ GdiFlush();
+
+ if (!w) w = width;
+ if (!h) h = height;
+
+ bitsSave = new COLOR32[w*h];
+ COLOR32 *p1 = bitsSave;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ COLOR32 *p2 = bits + (y+i)*width + x;
+ p1 = bitsSave + i*w;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ *p1++=*p2++;
+ }
+ }
+}
+
+void MyBitmap::restoreAlpha(int x, int y, int w, int h)
+{
+ if (!bitsSave)
+ return;
+
+ GdiFlush();
+
+ if (!w) w = width;
+ if (!h) h = height;
+
+ COLOR32 *p1 = bitsSave;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ COLOR32 *p2 = bits + (y+i)*width + x;
+ p1 = bitsSave + i*w;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ if ((*p1&0x00ffffff) != (*p2&0x00ffffff))
+ {
+ *p2 |= 0xff000000;
+ } else
+ {
+ *p2 = (*p2&0x00ffffff) | (*p1&0xff000000);
+ }
+ ++p1;
+ ++p2;
+ }
+ }
+
+ delete [] bitsSave;
+ bitsSave = 0;
+}
+
+void MyBitmap::DrawBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h)
+{
+ if (!(bits && inbits)) return;
+
+ GdiFlush();
+
+ float kx = (float)inw / w;
+ float ky = (float)inh / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ bits[(i+y)*width + (j+x)] = inbits[int(i*ky)*inw + int(j*kx)];
+ }
+ }
+}
+
+void MyBitmap::BlendBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h)
+{
+ if (!(bits && inbits)) return;
+
+ GdiFlush();
+
+ float kx = (float)inw / w;
+ float ky = (float)inh / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ COLOR32 src = inbits[int(i*ky)*inw + int(j*kx)];
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+ long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+PU_DIV255((255-alpha)*getr(dst)),
+ getg(src)+PU_DIV255((255-alpha)*getg(dst)),
+ getb(src)+PU_DIV255((255-alpha)*getb(dst)),
+ geta(src)+PU_DIV255((255-alpha)*geta(dst))
+ );
+ }
+ }
+}
+
+void MyBitmap::Blend(MyBitmap *bmp, int x, int y, int w, int h)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+
+ GdiFlush();
+
+ if (!w) w = bmp->width;
+ if (!h) h = bmp->height;
+ float kx = (float)bmp->width / w;
+ float ky = (float)bmp->height / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ COLOR32 src = bmp->bits[int(i*ky)*bmp->width + int(j*kx)];
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+ long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+PU_DIV255((255-alpha)*getr(dst)),
+ getg(src)+PU_DIV255((255-alpha)*getg(dst)),
+ getb(src)+PU_DIV255((255-alpha)*getb(dst)),
+ geta(src)+PU_DIV255((255-alpha)*geta(dst))
+ );
+ }
+ }
+}
+
+void MyBitmap::Draw(MyBitmap *bmp, int x, int y, int w, int h)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+
+ GdiFlush();
+
+ if (!w) w = bmp->width;
+ if (!h) h = bmp->height;
+
+ if (!x && !y && (w == width) && (h == height) && (w == bmp->width) && (h == bmp->height))
+ {
+ // fast bitmap copy is possible good for animated avatars
+ CopyMemory(bits, bmp->bits, width*height*sizeof(COLOR32));
+ return;
+ }
+
+ float kx = (float)bmp->width / w;
+ float ky = (float)bmp->height / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ bits[(i+y)*width + (j+x)] = bmp->bits[int(i*ky)*bmp->width + int(j*kx)];
+ }
+ }
+}
+
+void MyBitmap::BlendColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+
+ GdiFlush();
+
+ if (!w) w = bmp->width;
+ if (!h) h = bmp->height;
+ float kx = (float)bmp->width / w;
+ float ky = (float)bmp->height / h;
+
+ // we should swap B and R channels when working with win32 COLORREF
+ float koef1r = (255 - getb(color)) / 128.0f;
+ float koef1g = (255 - getg(color)) / 128.0f;
+ float koef1b = (255 - getr(color)) / 128.0f;
+
+ int br = - 255 + 2 * getb(color);
+ int bg = - 255 + 2 * getg(color);
+ int bb = - 255 + 2 * getr(color);
+
+ float koef2r = (getb(color)) / 128.0f;
+ float koef2g = (getg(color)) / 128.0f;
+ float koef2b = (getr(color)) / 128.0f;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+// bits[(i+y)*width + (j+x)] = (cl > 128) ?
+// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])):
+// rgba(koef2r * cl, koef2g * cl, koef2b * cl, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]));
+
+ long alpha = geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+ COLOR32 cl = alpha ? getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])*255/alpha : 0;
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ COLOR32 src = (cl > 128) ?
+ rgba(
+ PU_DIV255((koef1r * cl + br)*alpha),
+ PU_DIV255((koef1g * cl + bg)*alpha),
+ PU_DIV255((koef1b * cl + bb)*alpha),
+ alpha):
+ rgba(
+ PU_DIV255(koef2r * cl * alpha),
+ PU_DIV255(koef2g * cl * alpha),
+ PU_DIV255(koef2b * cl * alpha),
+ alpha);
+#pragma warning(pop)
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+// COLOR32 src = (cl > 128) ?
+// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, alpha):
+// rgba(koef2r * cl, koef2g * cl, koef2b * cl, alpha);
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+// long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+PU_DIV255((255-alpha)*getr(dst)),
+ getg(src)+PU_DIV255((255-alpha)*getg(dst)),
+ getb(src)+PU_DIV255((255-alpha)*getb(dst)),
+ geta(src)+PU_DIV255((255-alpha)*geta(dst))
+ );
+
+ }
+ }
+}
+
+void MyBitmap::DrawColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+
+ GdiFlush();
+
+ if (!w) w = bmp->width;
+ if (!h) h = bmp->height;
+ float kx = (float)bmp->width / w;
+ float ky = (float)bmp->height / h;
+
+ // we should swap B and R channels when working with win32 COLORREF
+ float koef1r = (255 - getb(color)) / 128.0f;
+ float koef1g = (255 - getg(color)) / 128.0f;
+ float koef1b = (255 - getr(color)) / 128.0f;
+
+ int br = - 255 + 2 * getb(color);
+ int bg = - 255 + 2 * getg(color);
+ int bb = - 255 + 2 * getr(color);
+
+ float koef2r = (getb(color)) / 128.0f;
+ float koef2g = (getg(color)) / 128.0f;
+ float koef2b = (getr(color)) / 128.0f;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+
+ long alpha = geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+ COLOR32 cl = alpha ? getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])*255/alpha : 0;
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ bits[(i+y)*width + (j+x)] = (cl > 128) ?
+ rgba(
+ PU_DIV255((koef1r * cl + br)*alpha),
+ PU_DIV255((koef1g * cl + bg)*alpha),
+ PU_DIV255((koef1b * cl + bb)*alpha),
+ alpha):
+ rgba(
+ PU_DIV255(koef2r * cl * alpha),
+ PU_DIV255(koef2g * cl * alpha),
+ PU_DIV255(koef2b * cl * alpha),
+ alpha);
+#pragma warning(pop)
+// bits[(i+y)*width + (j+x)] = (cl > 128) ?
+// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])):
+// rgba(koef2r * cl, koef2g * cl, koef2b * cl, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]));
+ }
+ }
+}
+
+void MyBitmap::BlendPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+ if (!win || !hin) return;
+
+ GdiFlush();
+
+ if (!w) w = win;
+ if (!h) h = hin;
+ float kx = (float)win / w;
+ float ky = (float)hin / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ COLOR32 src = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)];
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+ long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+PU_DIV255((255-alpha)*getr(dst)),
+ getg(src)+PU_DIV255((255-alpha)*getg(dst)),
+ getb(src)+PU_DIV255((255-alpha)*getb(dst)),
+ geta(src)+PU_DIV255((255-alpha)*geta(dst))
+ );
+// bits[(i+y)*width + (j+x)] = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)];
+ }
+ }
+}
+
+void MyBitmap::BlendPartColorized(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h, COLOR32 color)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+ if (!win || !hin) return;
+
+ GdiFlush();
+
+ if (!w) w = win;
+ if (!h) h = hin;
+ float kx = (float)win / w;
+ float ky = (float)hin / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ // we should swap B and R channels when working with win32 COLORREF
+ float koef1r = (255 - getb(color)) / 128.0f;
+ float koef1g = (255 - getg(color)) / 128.0f;
+ float koef1b = (255 - getr(color)) / 128.0f;
+
+ int br = - 255 + 2 * getb(color);
+ int bg = - 255 + 2 * getg(color);
+ int bb = - 255 + 2 * getr(color);
+
+ float koef2r = (getb(color)) / 128.0f;
+ float koef2g = (getg(color)) / 128.0f;
+ float koef2b = (getr(color)) / 128.0f;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+
+ long alpha = geta(bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)]);
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+ COLOR32 cl = alpha ? getr(bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)])*255/alpha : 0;
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ COLOR32 src = (cl > 128) ?
+ rgba(
+ PU_DIV255((koef1r * cl + br)*alpha),
+ PU_DIV255((koef1g * cl + bg)*alpha),
+ PU_DIV255((koef1b * cl + bb)*alpha),
+ alpha):
+ rgba(
+ PU_DIV255(koef2r * cl * alpha),
+ PU_DIV255(koef2g * cl * alpha),
+ PU_DIV255(koef2b * cl * alpha),
+ alpha);
+#pragma warning(pop)
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+// COLOR32 src = (cl > 128) ?
+// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, alpha):
+// rgba(koef2r * cl, koef2g * cl, koef2b * cl, alpha);
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+// long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+PU_DIV255((255-alpha)*getr(dst)),
+ getg(src)+PU_DIV255((255-alpha)*getg(dst)),
+ getb(src)+PU_DIV255((255-alpha)*getb(dst)),
+ geta(src)+PU_DIV255((255-alpha)*geta(dst))
+ );
+
+/* COLOR32 src = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)];
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+ long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+(255-alpha)*getr(dst)/255,
+ getg(src)+(255-alpha)*getg(dst)/255,
+ getb(src)+(255-alpha)*getb(dst)/255,
+ geta(src)+(255-alpha)*geta(dst)/255
+ );*/
+// bits[(i+y)*width + (j+x)] = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)];
+ }
+ }
+}
+
+void MyBitmap::DrawPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+ if (!win || !hin) return;
+
+ GdiFlush();
+
+ if (!w) w = win;
+ if (!h) h = hin;
+ float kx = (float)win / w;
+ float ky = (float)hin / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ bits[(i+y)*width + (j+x)] = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)];
+ }
+ }
+}
+
+void MyBitmap::DrawNoAlpha(MyBitmap *bmp, int x, int y, int w, int h)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+
+ GdiFlush();
+
+ for (int i = 0; i < bmp->height; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < bmp->width; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ bits[(i+y)*width + (j+x)] = bmp->bits[i*bmp->width + j];
+ }
+ }
+}
+
+static __forceinline int ReadP(long *p, int w, int h, int x, int y, int k)
+{
+ if (x<0) x = 0; else if (x>=w) x = w-1;
+ if (y<0) y = 0; else if (y>=h) y = h-1;
+ return p[(x+y*w)*4+k];
+}
+
+void MyBitmap::Blur(int w, int h)
+{
+ if ((w <= 0) || (h <= 0)) return;
+
+ BYTE *buf_src = new BYTE[width*height*4];
+ long *buf_tmp = new long[width*height*4];
+ BYTE *buf_dst = (BYTE *)bits;
+ memcpy(buf_src, buf_dst, width*height*4);
+
+ BYTE *src, *dst;
+ long *tmp;
+
+ src = buf_src;
+ tmp = buf_tmp;
+ dst = buf_dst;
+
+ int y;
+
+ for (y = 0; y < height; ++y)
+ {
+ for (int x = 0; x < width; ++x)
+ {
+ for (int k = 0; k < 4; ++k)
+ {
+ int tot = src[0];
+ if (x > 0) tot += tmp[-4];
+ if (y > 0) tot += tmp[-width*4];
+ if (x > 0 && y > 0) tot -= tmp[-(width+1)*4];
+ *tmp = tot;
+
+ ++src;
+ ++tmp;
+ }
+ }
+ }
+
+ src = buf_src;
+ tmp = buf_tmp;
+ dst = buf_dst;
+
+ float mul = 1.f/((w*2+1)*(h*2+1));
+ for (y = 0;y<height;y++)
+ {
+ for (int x = 0;x<width;x++)
+ {
+ for (int k = 0; k < 4; ++k)
+ {
+ int tot = ReadP(tmp,width,height,x+w,y+h,k) +
+ ReadP(tmp,width,height,x-w,y-h,k) -
+ ReadP(tmp,width,height,x-w,y+h,k) -
+ ReadP(tmp,width,height,x+w,y-h,k);
+
+ *dst = BYTE(tot*mul);
+
+ ++dst;
+ ++src;
+ }
+ }
+ }
+
+ delete [] buf_src;
+ delete [] buf_tmp;
+}
+
+void MyBitmap::IncreaseAlpha(float q)
+{
+ BYTE *p = (BYTE *)bits;
+
+ for (int i = 0; i < height; ++i)
+ {
+ for (int j = 0; j < width; ++j)
+ {
+ if (!p[3])
+ {
+ p += 4;
+ continue;
+ }
+
+ float q1 = min(q, 255.f/p[3]);
+
+ for (int k = 0; k < 4; ++k)
+ {
+ *p = (BYTE)min(255, *p * q1);
+ ++p;
+ }
+ }
+ }
+}
+
+void MyBitmap::DrawIcon(HICON hic, int x, int y, int w, int h)
+{
+ GdiFlush();
+
+ ICONINFO info;
+ GetIconInfo(hic, &info);
+
+ BITMAP bmpColor, bmpMask;
+ GetObject(info.hbmMask, sizeof(bmpMask), &bmpMask);
+ GetObject(info.hbmColor, sizeof(bmpColor), &bmpColor);
+
+ if (!w) w = abs(bmpMask.bmWidth);
+ if (!h) h = abs(bmpMask.bmHeight);
+
+ if (bmpColor.bmBitsPixel == 32)
+ {
+ if ((w != abs(bmpMask.bmWidth)) || (h != abs(bmpMask.bmHeight)))
+ {
+ DeleteObject(info.hbmColor);
+ DeleteObject(info.hbmMask);
+ HICON hicTmp = (HICON)CopyImage(hic,IMAGE_ICON,w,h,LR_COPYFROMRESOURCE);
+ GetIconInfo(hicTmp, &info);
+ GetObject(info.hbmMask, sizeof(bmpMask), &bmpMask);
+ GetObject(info.hbmColor, sizeof(bmpColor), &bmpColor);
+ DestroyIcon(hicTmp);
+ }
+
+ BYTE *cbit = new BYTE[bmpColor.bmWidthBytes*bmpColor.bmHeight];
+ BYTE *mbit = new BYTE[bmpMask.bmWidthBytes*bmpMask.bmHeight];
+ GetBitmapBits(info.hbmColor, bmpColor.bmWidthBytes*bmpColor.bmHeight, cbit);
+ GetBitmapBits(info.hbmMask, bmpMask.bmWidthBytes*bmpMask.bmHeight, mbit);
+
+ for (int i = 0; i < bmpColor.bmHeight; i++)
+ {
+ for (int j = 0; j < bmpColor.bmWidth; j++)
+ {
+ BYTE *pixel = cbit + i*bmpColor.bmWidthBytes + j*4;
+ if (!pixel[3])
+ {
+ pixel[3] = (*(mbit + i*bmpMask.bmWidthBytes + j*bmpMask.bmBitsPixel/8) & (1<<(7-j%8))) ? 0 : 255;
+ }
+
+ if (pixel[3] != 255)
+ {
+ pixel[0] = PU_DIV255(pixel[0] * pixel[3]);
+ pixel[1] = PU_DIV255(pixel[1] * pixel[3]);
+ pixel[2] = PU_DIV255(pixel[2] * pixel[3]);
+ }
+ }
+ }
+
+ this->BlendBits((COLOR32 *)cbit, bmpColor.bmWidth, bmpColor.bmHeight, x, y, w, h);
+
+ delete [] mbit;
+ delete [] cbit;
+ } else
+ {
+ this->saveAlpha(x,y,w,h);
+ DrawIconEx(this->getDC(), x, y, hic, w, h, 0, NULL, DI_NORMAL);
+ this->restoreAlpha(x,y,w,h);
+ }
+
+ DeleteObject(info.hbmColor);
+ DeleteObject(info.hbmMask);
+}
+
+//Base on code by Artem Shpynov
+//from clist_modern plugin
+//slightly modified and integrated to MyBitmap class
+void MyBitmap::DrawText(TCHAR *str, int x, int y, int blur, int strength)
+{
+ SIZE sz; GetTextExtentPoint32(this->getDC(), str, lstrlen(str), &sz);
+ sz.cx += (blur+2)*2; sz.cy += (blur+2)*2;
+ x -= blur+2; y -= blur+2;
+
+ static BYTE pbGammaWeight[256] = {0};
+ static BOOL bGammaWeightFilled = FALSE;
+
+ if (!bGammaWeightFilled)
+ {
+ int i;
+ for(i = 0;i<256;i++)
+ {
+ double f;
+ double gamma = (double)700/1000;
+
+ f = (double)i/255;
+ f = pow(f,(1/gamma));
+
+ pbGammaWeight[i] = (BYTE)(255*f);
+ }
+ bGammaWeightFilled = 1;
+ }
+
+ MyBitmap tmp(sz.cx, sz.cy);
+ HFONT hfnTmp = (HFONT)SelectObject(tmp.getDC(), GetCurrentObject(this->getDC(), OBJ_FONT));
+
+ RECT rc; SetRect(&rc, 0, 0, sz.cx, sz.cy);
+ SetTextColor(tmp.getDC(), RGB(255,255,255));
+ SetBkColor(tmp.getDC(), RGB(0,0,0));
+ ExtTextOutA(tmp.getDC(), 0, 0, ETO_OPAQUE, &rc, "", 0, NULL);
+ ::DrawText(tmp.getDC(), str, lstrlen(str), &rc, DT_CENTER|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER);
+ SelectObject(tmp.getDC(), hfnTmp);
+
+ GdiFlush();
+
+ if (blur)
+ {
+ for (int i = 0; i < sz.cy; i++)
+ {
+ COLOR32 *row_src = tmp.bits + i * tmp.width;
+
+ for (int j = 0; j < sz.cx; j++)
+ {
+ COLOR32 cl = row_src[j];
+ if (!cl) continue;
+
+ int a1 = (getr(cl) + getg(cl) + getb(cl)) / 3;
+ row_src[j] = rgba(a1, a1, a1, a1);
+ }
+ }
+ tmp.Blur(blur, blur);
+ tmp.IncreaseAlpha((float)(strength ? strength : blur));
+ }
+
+ // use Get*Value for COLORREF and get* for COLOR32
+ COLOR32 textColor = GetTextColor(this->getDC());
+ COLOR32 r = GetRValue(textColor);
+ COLOR32 g = GetGValue(textColor);
+ COLOR32 b = GetBValue(textColor);
+
+ int minx = max(0,-x);
+ int miny = max(0,-y);
+ int maxx = min(sz.cx, width-x);
+ int maxy = min(sz.cy, height-y);
+
+ for (int i = miny; i < maxy; i++)
+ {
+ COLOR32 *row_dst = bits + (i+y) * width + x;
+ COLOR32 *row_src = tmp.bits + i * tmp.width;
+
+ for (int j = minx; j < maxx; j++)
+ {
+ COLOR32 bx,rx,gx,mx;
+ {
+ bx = pbGammaWeight[getb(row_src[j])];
+ gx = pbGammaWeight[getg(row_src[j])];
+ rx = pbGammaWeight[getr(row_src[j])];
+ }
+
+ bx = (pbGammaWeight[bx]*(255-b)+bx*(b))/255;
+ gx = (pbGammaWeight[gx]*(255-g)+gx*(g))/255;
+ rx = (pbGammaWeight[rx]*(255-r)+rx*(r))/255;
+
+ mx = (BYTE)(max(max(bx,rx),gx));
+
+ if (1)
+ {
+ bx = (bx<mx)?(BYTE)(((WORD)bx*7+(WORD)mx)>>3):bx;
+ rx = (rx<mx)?(BYTE)(((WORD)rx*7+(WORD)mx)>>3):rx;
+ gx = (gx<mx)?(BYTE)(((WORD)gx*7+(WORD)mx)>>3):gx;
+ // reduce boldeness at white fonts
+ }
+ COLOR32 cl = row_dst[j];
+ if (mx)
+ {
+ COLOR32 rrx,grx,brx;
+ COLOR32 rlx,glx,blx;
+ COLOR32 axx = geta(cl);
+ COLOR32 mmx = (bx+gx+rx)/3;
+ COLOR32 nx = mmx;;//pbGammaWeight[mx];//
+ {
+ //Normalize components to alpha level
+ bx = (nx*(255-axx)+bx*axx)/255;
+ gx = (nx*(255-axx)+gx*axx)/255;
+ rx = (nx*(255-axx)+rx*axx)/255;
+ mx = (nx*(255-axx)+mmx*axx)/255;
+ }
+ {
+ blx = getb(cl);
+ glx = getg(cl);
+ rlx = getr(cl);
+
+ brx = (b-blx)*bx/255;
+ grx = (g-glx)*gx/255;
+ rrx = (r-rlx)*rx/255;
+ row_dst[j] = rgba(rlx+rrx, glx+grx, blx+brx, mx+(255-mx)*axx/255);
+ }
+ }
+ }
+ }
+}
+
+// based on code by Yuriy Zaporozhets from:
+// http://www.codeproject.com/gdi/coolrgn.asp?df = 100&forumid = 739&exp = 0&select = 6341
+// slightly modified to integrate with MyBitmap class.
+HRGN MyBitmap::buildOpaqueRgn(int level, bool opaque)
+{
+ GdiFlush();
+
+ const int addRectsCount = 64;
+ int rectsCount = addRectsCount;
+ PRGNDATA pRgnData = (PRGNDATA)(new BYTE[sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT)]);
+ LPRECT pRects = (LPRECT)(&pRgnData->Buffer);
+
+ memset(pRgnData, 0, sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT));
+ pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER);
+ pRgnData->rdh.iType = RDH_RECTANGLES;
+
+ int first = 0;
+ bool wasfirst = false;
+ bool ismask = false;
+ for (int i = 0; i < height; i++)
+ {
+ int j; // we will need j after the loop!
+ for (j = 0; j < width; j++)
+ {
+ ismask = opaque ? (int)geta(this->getRow(i)[j]) > level : (int)geta(this->getRow(i)[j]) < level;
+ if (wasfirst)
+ {
+ if (!ismask)
+ {
+ SetRect(&pRects[pRgnData->rdh.nCount++], first, i, j, i+1);
+ if ((int)(pRgnData->rdh.nCount) >= rectsCount)
+ {
+ rectsCount += addRectsCount;
+ LPRGNDATA pRgnDataNew = (LPRGNDATA)(new BYTE[sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT)]);
+ memcpy(pRgnDataNew, pRgnData, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount * sizeof(RECT));
+ delete pRgnData;
+ pRgnData = pRgnDataNew;
+ pRects = (LPRECT)(&pRgnData->Buffer);
+ }
+ wasfirst = false;
+ }
+ } else
+ if (ismask) // set wasfirst when mask is found
+ {
+ first = j;
+ wasfirst = true;
+ }
+ }
+
+ if (wasfirst && ismask)
+ {
+ SetRect(&pRects[pRgnData->rdh.nCount++], first, i, j, i+1);
+ if ((int)(pRgnData->rdh.nCount) >= rectsCount)
+ {
+ rectsCount += addRectsCount;
+ LPRGNDATA pRgnDataNew = (LPRGNDATA)(new BYTE[sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT)]);
+ memcpy(pRgnDataNew, pRgnData, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount * sizeof(RECT));
+ delete pRgnData;
+ pRgnData = pRgnDataNew;
+ pRects = (LPRECT)(&pRgnData->Buffer);
+ }
+ wasfirst = false;
+ }
+
+ }
+
+ HRGN hRgn = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount*sizeof(RECT), (LPRGNDATA)pRgnData);
+ delete pRgnData;
+ return hRgn;
+}
+
+static int hex2dec(char hex)
+{
+ if ((hex >= '0') && (hex <= '9'))
+ return hex - '0';
+ if ((hex >= 'a') && (hex <= 'f'))
+ return hex - 'a' + 0xa;
+ if ((hex >= 'A') && (hex <= 'F'))
+ return hex - 'A' + 0xa;
+ return 0;
+}
+
+bool MyBitmap::loadFromFile_pixel(const char *fn, const char *fnAlpha)
+{
+ allocate(1,1);
+ int r, g, b, a = 255;
+ const char *p = fn + lstrlenA("pixel:");
+ r = (hex2dec(p[0]) << 4) + hex2dec(p[1]);
+ g = (hex2dec(p[2]) << 4) + hex2dec(p[3]);
+ b = (hex2dec(p[4]) << 4) + hex2dec(p[5]);
+ *bits = rgba(r,g,b,a);
+ return true;
+}
+
+bool MyBitmap::loadFromFile_gradient(const char *fn, const char *fnAlpha)
+{
+ const char *p = fn + lstrlenA("gradient:");
+
+ if (*p == 'h') allocate(256,1);
+ else allocate(1,256);
+
+ int r, g, b, a = 255;
+
+ p += 2;
+ r = (hex2dec(p[0]) << 4) + hex2dec(p[1]);
+ g = (hex2dec(p[2]) << 4) + hex2dec(p[3]);
+ b = (hex2dec(p[4]) << 4) + hex2dec(p[5]);
+ COLOR32 from = rgba(r,g,b,a);
+
+ p += 7;
+ r = (hex2dec(p[0]) << 4) + hex2dec(p[1]);
+ g = (hex2dec(p[2]) << 4) + hex2dec(p[3]);
+ b = (hex2dec(p[4]) << 4) + hex2dec(p[5]);
+ COLOR32 to = rgba(r,g,b,a);
+
+ for (int i = 0; i < 256; ++i)
+ {
+ bits[i] = rgba(
+ ((255-i) * getr(from) + i * getr(to)) / 255,
+ ((255-i) * getg(from) + i * getg(to)) / 255,
+ ((255-i) * getb(from) + i * getb(to)) / 255,
+ 255
+ );
+ }
+
+ return true;
+}
+
+bool MyBitmap::loadFromFile_png(const char *fn, const char *fnAlpha)
+{
+ if (ServiceExists(MS_PNG2DIB))
+ {
+ HANDLE hFile, hMap = 0;
+ BYTE *ppMap = 0;
+ long cbFileSize = 0;
+ BITMAPINFOHEADER *pDib;
+ BYTE *pDibBits;
+ if ((hFile = CreateFileA(fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
+ if ((hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL)
+ if ((ppMap = (BYTE*)MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 )) != NULL)
+ cbFileSize = GetFileSize(hFile, NULL);
+ if (cbFileSize)
+ {
+ PNG2DIB param;
+ param.pSource = ppMap;
+ param.cbSourceSize = cbFileSize;
+ param.pResult = &pDib;
+ if (CallService(MS_PNG2DIB, 0, (LPARAM)&param))
+ pDibBits = (BYTE*)(pDib+1);
+ else
+ cbFileSize = 0;
+ }
+
+ if (ppMap) UnmapViewOfFile(ppMap);
+ if (hMap) CloseHandle(hMap);
+ if (hFile) CloseHandle(hFile);
+
+ if (!cbFileSize) return false;
+
+ BITMAPINFO *bi = (BITMAPINFO*)pDib;
+ BYTE *pt = (BYTE*)bi;
+ pt+=bi->bmiHeader.biSize;
+
+ if (bi->bmiHeader.biBitCount != 32)
+ {
+ allocate(abs(bi->bmiHeader.biWidth), abs(bi->bmiHeader.biHeight));
+ HDC hdcTmp = CreateCompatibleDC(getDC());
+ HBITMAP hBitmap = CreateDIBitmap(getDC(), pDib, CBM_INIT, pDibBits, bi, DIB_PAL_COLORS);
+ SelectObject(hdcTmp, hBitmap);
+ BitBlt(this->getDC(), 0, 0, abs(bi->bmiHeader.biWidth), abs(bi->bmiHeader.biHeight), hdcTmp, 0, 0, SRCCOPY);
+ this->makeOpaque();
+ DeleteDC(hdcTmp);
+ DeleteObject(hBitmap);
+ } else
+ {
+ allocate(abs(bi->bmiHeader.biWidth), abs(bi->bmiHeader.biHeight));
+ BYTE *p2 = (BYTE *)pt;
+ for (int y = 0; y<bi->bmiHeader.biHeight; ++y)
+ {
+ BYTE *p1 = (BYTE *)bits + (bi->bmiHeader.biHeight-y-1)*bi->bmiHeader.biWidth*4;
+ for (int x = 0; x<bi->bmiHeader.biWidth; ++x)
+ {
+ p1[0] = p2[0];
+ p1[1] = p2[1];
+ p1[2] = p2[2];
+ p1[3] = p2[3];
+ p1 += 4;
+ p2 += 4;
+ }
+ }
+// memcpy(bits, pt, bi->bmiHeader.biSizeImage);
+ premultipleChannels();
+ }
+
+ GlobalFree(pDib);
+ return true;
+ } else
+ {
+// MessageBox(NULL, Translate("You need the png2dib plugin v. 0.1.3.x or later to process PNG images"), Translate("Error"), MB_OK);
+ return false;
+ }
+}
+
+bool MyBitmap::loadFromFile_default(const char *fn, const char *fnAlpha)
+{
+ SIZE sz;
+ HBITMAP hBmpLoaded = (HBITMAP)LoadImageA(NULL, fn, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
+ if (!hBmpLoaded)
+ return false;
+
+ BITMAP bm; GetObject(hBmpLoaded, sizeof(bm), &bm);
+ SetBitmapDimensionEx(hBmpLoaded, bm.bmWidth, bm.bmHeight, NULL);
+
+ HDC dcTmp = CreateCompatibleDC(0);
+ GetBitmapDimensionEx(hBmpLoaded, &sz);
+ HBITMAP hBmpDcSave = (HBITMAP)SelectObject(dcTmp, hBmpLoaded);
+
+ allocate(sz.cx, sz.cy);
+ BitBlt(dcBmp, 0, 0, width, height, dcTmp, 0, 0, SRCCOPY);
+
+ DeleteObject(SelectObject(dcTmp, hBmpDcSave));
+ DeleteDC(dcTmp);
+
+ MyBitmap alpha;
+ if (fnAlpha && alpha.loadFromFile(fnAlpha) &&
+ (alpha.getWidth() == width) &&
+ (alpha.getHeight() == height))
+ {
+ for (int i = 0; i < width*height; i++)
+ bits[i] = (bits[i] & 0x00ffffff) | ( (alpha.bits[i] & 0x000000ff) << 24 );
+ premultipleChannels();
+ } else
+ {
+ makeOpaque();
+ }
+ return true;
+}
+
+bool MyBitmap::loadFromFile(const char *fn, const char *fnAlpha)
+{
+ if (bits) free();
+
+ if (!strncmp(fn, "pixel:", lstrlenA("pixel:")))
+ {
+ return loadFromFile_pixel(fn, fnAlpha);
+ } else
+ if (!strncmp(fn, "gradient:", lstrlenA("gradient:")))
+ {
+ return loadFromFile_gradient(fn, fnAlpha);
+ } else
+ {
+ char ext[5];
+ memcpy(ext,fn+(strlen(fn)-4),5);
+ if (!lstrcmpiA(ext,".png"))
+ {
+ return loadFromFile_png(fn, fnAlpha);
+ } else
+ {
+ return loadFromFile_default(fn, fnAlpha);
+ }
+ }
+ // unreachable place
+ return false;
+}
+
+void MyBitmap::allocate(int w, int h)
+{
+ if (dcBmp && (width == w) && (height == h)) return;
+
+ width = w;
+ height = h;
+
+ BITMAPINFO bi;
+
+ bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
+ bi.bmiHeader.biWidth = w;
+ bi.bmiHeader.biHeight = -h;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 32;
+ bi.bmiHeader.biCompression = BI_RGB;
+
+ if (dcBmp)
+ {
+ DeleteObject(SelectObject(dcBmp, hBmpSave));
+ DeleteDC(dcBmp);
+ }
+
+ hBmp = (HBITMAP)CreateDIBSection(0, &bi, DIB_RGB_COLORS, (void **)&bits, 0, 0);
+ dcBmp = CreateCompatibleDC(0);
+ hBmpSave = (HBITMAP)SelectObject(dcBmp, hBmp);
+
+ GdiFlush();
+}
+
+void MyBitmap::free()
+{
+ GdiFlush();
+
+ DeleteObject(SelectObject(dcBmp, hBmpSave));
+ DeleteDC(dcBmp);
+
+ dcBmp = 0;
+ hBmp = 0;
+ bits = 0;
+ width = height = 0;
+}
+
+void MyBitmap::premultipleChannels()
+{
+ GdiFlush();
+
+ for (int i = 0; i < width*height; i++)
+ bits[i] = rgba(getr(bits[i])*geta(bits[i])/255, getg(bits[i])*geta(bits[i])/255, getb(bits[i])*geta(bits[i])/255, geta(bits[i]));
+}
diff --git a/plugins/FloatingContacts/src/bitmap_funcs.h b/plugins/FloatingContacts/src/bitmap_funcs.h
new file mode 100644
index 0000000000..85bbee2004
--- /dev/null
+++ b/plugins/FloatingContacts/src/bitmap_funcs.h
@@ -0,0 +1,127 @@
+/*
+Popup Plus plugin for Miranda IM
+
+Copyright © 2002 Luca Santarelli,
+ © 2004-2007 Victor Pavlychko
+
+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; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __bitmap_funcs_h__
+#define __bitmap_funcs_h__
+
+// This should make bitmap manipulations much easier...
+class MyBitmap
+{
+public:
+ typedef unsigned long COLOR32;
+ static inline COLOR32 RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 0xff)
+ {
+ return (a << 24) | (r << 16) | (g << 8) | b;
+ };
+
+private:
+ HBITMAP hBmpSave, hBmp;
+ HDC dcBmp;
+ COLOR32 *bits;
+ COLOR32 *bitsSave;
+ int width, height;
+
+ void free();
+
+ bool loadFromFile_pixel(const char *fn, const char *fnAlpha = 0);
+ bool loadFromFile_gradient(const char *fn, const char *fnAlpha = 0);
+ bool loadFromFile_png(const char *fn, const char *fnAlpha = 0);
+ bool loadFromFile_default(const char *fn, const char *fnAlpha = 0);
+ void premultipleChannels();
+
+public:
+ MyBitmap();
+ MyBitmap(int w, int h);
+ MyBitmap(const char *fn, const char *fnAlpha = 0);
+ ~MyBitmap();
+ void allocate(int w, int h);
+
+ bool loadFromFile(const char *fn, const char *fnAlpha = 0);
+
+ int getWidth() { return width; }
+ int getHeight() { return height; }
+
+ HDC getDC() { return dcBmp; }
+ HBITMAP getBitmap() { return hBmp; }
+
+ void setAlpha(BYTE level);
+ void setAlphaRect(int x1, int y1, int x2, int y2, BYTE level);
+ void setAlphaRect(RECT rc, BYTE level) { setAlphaRect(rc.left, rc.top, rc.right, rc.bottom, level); }
+
+ void makeOpaque();
+ void makeOpaqueRect(int x1, int y1, int x2, int y2);
+ void makeOpaqueRect(RECT rc) { makeOpaqueRect(rc.left, rc.top, rc.right, rc.bottom); }
+
+ void saveAlpha(int x = 0, int y = 0, int w = 0, int h = 0);
+ void restoreAlpha(int x = 0, int y = 0, int w = 0, int h = 0);
+
+ void DrawBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h);
+ void BlendBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h);
+
+ void DrawNoAlpha(MyBitmap *bmp, int x, int y, int w, int h);
+
+ void Blend(MyBitmap *bmp, int x, int y, int w, int h);
+ void Draw(MyBitmap *bmp, int x, int y, int w, int h);
+
+ void BlendColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color);
+ void DrawColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color);
+
+ void BlendPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h);
+ void BlendPartColorized(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h, COLOR32 color);
+ void DrawPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h);
+// void DrawPartNoAlpha(MyBitmap *bmp, int x, int y, int w, int h);
+// void DrawPartColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color);
+
+ void Blur(int w, int h);
+ void IncreaseAlpha(float q);
+
+ void DrawIcon(HICON hic, int x, int y, int w = 0, int h = 0);
+ void DrawText(TCHAR *str, int x, int y, int blur = 0, int strength = 0);
+
+ __forceinline COLOR32 *getBits() { return bits; }
+ __forceinline COLOR32 *getRow(int row) { return bits + row * width; }
+ __forceinline COLOR32 *operator[] (int row) { return bits + row * width; }
+
+ static __forceinline COLOR32 rgba(COLOR32 r, COLOR32 g, COLOR32 b, COLOR32 a)
+ {
+ return ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
+ }
+ static __forceinline COLOR32 getr(COLOR32 c)
+ {
+ return (c >> 16) & 0xff;
+ }
+ static __forceinline COLOR32 getg(COLOR32 c)
+ {
+ return (c >> 8) & 0xff;
+ }
+ static __forceinline COLOR32 getb(COLOR32 c)
+ {
+ return c & 0xff;
+ }
+ static __forceinline COLOR32 geta(COLOR32 c)
+ {
+ return (c >> 24) & 0xff;
+ }
+
+ HRGN buildOpaqueRgn(int level = 64, bool opaque = true);
+};
+
+#endif // __bitmap_funcs_h__
diff --git a/plugins/FloatingContacts/src/filedrop.cpp b/plugins/FloatingContacts/src/filedrop.cpp
new file mode 100644
index 0000000000..473c7a6814
--- /dev/null
+++ b/plugins/FloatingContacts/src/filedrop.cpp
@@ -0,0 +1,368 @@
+#include "stdhdr.h"
+
+static void ProcessDroppedItems ( char **ppDroppedItems, int nCount, char **ppFiles );
+static int CountDroppedFiles ( char **ppDroppedItems, int nCount );
+static BOOL OnDropFiles ( HDROP hDrop, ThumbInfo *pThumb );
+
+HRESULT STDMETHODCALLTYPE CDropTarget::QueryInterface(REFIID riid,LPVOID *ppvObj)
+{
+ if ( IsEqualIID( riid, IID_IDropTarget ))
+ {
+ *ppvObj = this;
+ this->AddRef();
+ return S_OK;
+ }
+
+ *ppvObj = NULL;
+
+ return ( E_NOINTERFACE );
+}
+
+ULONG STDMETHODCALLTYPE CDropTarget::AddRef( )
+{
+ return ++this->refCount;
+}
+
+ULONG STDMETHODCALLTYPE CDropTarget::Release( )
+{
+ int res = --this->refCount;
+ if (!res) delete this;
+ return res;
+}
+
+
+HRESULT STDMETHODCALLTYPE CDropTarget::DragOver( DWORD fKeyState, POINTL pt, DWORD *pdwEffect )
+{
+ *pdwEffect = 0;
+
+ if ( hwndCurDrag == NULL )
+ {
+ *pdwEffect = DROPEFFECT_NONE;
+ }
+ else
+ {
+ *pdwEffect |= DROPEFFECT_COPY;
+ }
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE CDropTarget::DragEnter( IDataObject *pData, DWORD fKeyState, POINTL pt, DWORD *pdwEffect)
+{
+ HWND hwnd = NULL;
+ POINT shortPt;
+ FORMATETC feFile = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ FORMATETC feText = { CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ ThumbInfo *pThumb;
+
+ if ( S_OK == pData->QueryGetData( &feFile ) ||
+ S_OK == pData->QueryGetData( &feText ))
+ {
+ shortPt.x = pt.x;
+ shortPt.y = pt.y;
+
+ hwnd = WindowFromPoint( shortPt );
+
+ if ( pThumb = thumbList.FindThumb( hwnd ))
+ {
+ hwndCurDrag = hwnd;
+ pThumb->ThumbSelect( TRUE );
+ }
+ }
+
+ return DragOver( fKeyState, pt, pdwEffect);
+}
+
+
+HRESULT STDMETHODCALLTYPE CDropTarget::DragLeave( )
+{
+ ThumbInfo *pThumb = thumbList.FindThumb( hwndCurDrag );
+
+ if ( NULL != pThumb )
+ {
+ pThumb->ThumbDeselect( TRUE );
+ }
+
+ hwndCurDrag = NULL;
+
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE CDropTarget::Drop( IDataObject *pData,DWORD fKeyState,POINTL pt,DWORD *pdwEffect)
+{
+ FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM stg;
+ HDROP hDrop = NULL;
+ ThumbInfo *pThumb = NULL;
+ char *pText = NULL;
+ BOOL bFormatText = FALSE;
+
+ *pdwEffect = DROPEFFECT_NONE;
+
+
+ if ( hwndCurDrag == NULL ) return( S_OK );
+
+ pThumb = (ThumbInfo*)GetWindowLongPtr( hwndCurDrag, GWLP_USERDATA );
+ if ( pThumb == NULL ) return( S_OK );
+
+ if ( S_OK != pData->GetData( &fe,&stg ))
+ {
+ fe.cfFormat = CF_TEXT;
+
+ if ( S_OK != pData->GetData( &fe,&stg ))
+ {
+ return( S_OK );
+ }
+ else
+ {
+ bFormatText = TRUE;
+ }
+ }
+
+
+
+ if ( !bFormatText )
+ {
+ hDrop = (HDROP)stg.hGlobal;
+
+ if ( hDrop != NULL )
+ {
+ OnDropFiles( hDrop, pThumb );
+ }
+ }
+ else
+ {
+ pText = (char*)GlobalLock( stg.hGlobal );
+
+ if ( pText != NULL )
+ {
+ SendMsgDialog( hwndCurDrag, pText );
+ GlobalUnlock( stg.hGlobal );
+ }
+ }
+
+ if ( stg.pUnkForRelease != NULL )
+ {
+ stg.pUnkForRelease->Release( );
+ }
+ else
+ {
+ GlobalFree( stg.hGlobal );
+ }
+
+ DragLeave( );
+
+ return S_OK;
+}
+
+///////////////////////////////////////////////////////
+// Send files processing
+
+BOOL OnDropFiles( HDROP hDrop, ThumbInfo *pThumb )
+{
+ BOOL bSuccess = FALSE;
+ UINT nFilesCount = 0;
+ UINT iItem = 0;
+ char **ppFiles = NULL;
+ char **ppDroppedItems = NULL;
+ UINT nDroppedItemsCount = 0;
+ char szFilename[ MAX_PATH ];
+
+
+ nDroppedItemsCount = DragQueryFile( hDrop, 0xFFFFFFFF, NULL, 0 );
+
+ ppDroppedItems = ( char** )malloc( sizeof(char*)*( nDroppedItemsCount + 1 ));
+
+ if ( ppDroppedItems == NULL )
+ {
+ return( FALSE );
+ }
+
+ ppDroppedItems[ nDroppedItemsCount ] = NULL;
+
+ for ( iItem = 0; iItem < nDroppedItemsCount; ++iItem )
+ {
+ DragQueryFileA( hDrop, iItem, szFilename, sizeof( szFilename ));
+ ppDroppedItems[ iItem ] = _strdup( szFilename );
+ }
+
+ nFilesCount = CountDroppedFiles( ppDroppedItems, nDroppedItemsCount );
+
+ ppFiles = ( char** )malloc( sizeof( char *)* ( nFilesCount+1 ));
+
+ if ( ppFiles == NULL )
+ {
+ return( FALSE );
+ }
+
+ ppFiles[ nFilesCount] = NULL;
+
+ ProcessDroppedItems( ppDroppedItems, nDroppedItemsCount, ppFiles );
+
+ bSuccess = (BOOL)CallService( MS_CLIST_CONTACTFILESDROPPED, (WPARAM)pThumb->hContact, (LPARAM)ppFiles );
+
+ // Cleanup
+ for ( iItem = 0; ppDroppedItems[ iItem ]; ++iItem )
+ {
+ free( ppDroppedItems[ iItem ] );
+ }
+
+ free( ppDroppedItems );
+
+ for ( iItem = 0; iItem < nFilesCount ; ++iItem )
+ {
+ free( ppFiles[ iItem ] );
+ }
+
+ free( ppFiles );
+
+ return( bSuccess );
+}
+
+
+static int CountFiles( char *szItem )
+{
+ int nCount = 0;
+ WIN32_FIND_DATAA fd;
+
+ HANDLE hFind = FindFirstFileA( szItem, &fd );
+
+ if ( hFind != INVALID_HANDLE_VALUE )
+ {
+ do
+ {
+ if ( fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY )
+ {
+ // Skip parent directories
+ if ( ( 0 != strcmp( fd.cFileName, "." )) &&
+ ( 0 != strcmp( fd.cFileName, ".." )) )
+ {
+ char szDirName[ MAX_PATH ];
+ strncpy( szDirName, szItem, MAX_PATH - 1 );
+
+ if ( NULL != strstr( szItem, "*.*" ))
+ {
+ sprintf( szDirName + strlen( szDirName ) - 3, "%s\0", fd.cFileName );
+ }
+
+ ++nCount;
+ strcat( szDirName, "\\*.*" );
+ nCount += CountFiles( szDirName );
+ }
+ }
+ else
+ {
+ ++nCount;
+ }
+ }
+ while( FALSE != FindNextFileA( hFind, &fd ));
+ }
+
+ return( nCount );
+}
+
+
+
+static void SaveFiles( char *szItem, char **ppFiles, int *pnCount )
+{
+
+ WIN32_FIND_DATAA fd;
+
+ HANDLE hFind = FindFirstFileA( szItem, &fd );
+
+ if ( hFind != INVALID_HANDLE_VALUE )
+ {
+ do
+ {
+ if ( fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY )
+ {
+ // Skip parent directories
+ if ( ( 0 != strcmp( fd.cFileName, "." )) &&
+ ( 0 != strcmp( fd.cFileName, ".." )) )
+ {
+ char szDirName[ MAX_PATH ];
+ strncpy( szDirName, szItem, MAX_PATH - 1 );
+
+ if ( NULL != strstr( szItem, "*.*" ))
+ {
+ sprintf( szDirName + strlen( szDirName ) - 3, "%s\0", fd.cFileName );
+ }
+
+ ppFiles[ *pnCount ] = _strdup( szDirName );
+ ++( *pnCount );
+
+ strcat( szDirName, "\\*.*" );
+ SaveFiles( szDirName, ppFiles, pnCount );
+
+ }
+ }
+ else
+ {
+ int nSize = sizeof(char) * ( strlen( szItem ) + strlen( fd.cFileName ) + sizeof( char ));
+ char *szFile = (char*) malloc( nSize ) ;
+
+ strncpy( szFile, szItem, nSize - 1 );
+
+ if ( NULL != strstr( szFile, "*.*" ))
+ {
+ szFile[ strlen( szFile ) - 3 ] = '\0';
+ strncat( szFile, fd.cFileName, MAX_PATH - 1 );
+ }
+
+ ppFiles[ *pnCount ] = szFile;
+ ++( *pnCount );
+ }
+ }
+ while( FALSE != FindNextFileA( hFind, &fd ));
+ }
+}
+
+
+static void ProcessDroppedItems( char **ppDroppedItems, int nCount, char **ppFiles )
+{
+ int i;
+ int fileCount = 0;
+
+ for ( i = 0; i < nCount; ++i )
+ {
+ SaveFiles( ppDroppedItems[ i ], ppFiles, &fileCount );
+ }
+}
+
+
+static int CountDroppedFiles( char **ppDroppedItems, int nCount )
+{
+ int fileCount = 0;
+ int i;
+
+ for ( i = 0; i < nCount; ++i )
+ {
+ fileCount += CountFiles( ppDroppedItems[ i ] );
+ }
+
+ return( fileCount );
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Init/destroy
+void InitFileDropping()
+{
+ OleInitialize( NULL );
+}
+
+void FreeFileDropping(void)
+{
+ OleUninitialize();
+}
+
+void RegisterFileDropping( HWND hwnd, CDropTarget* pdropTarget )
+{
+ RegisterDragDrop( hwnd, (IDropTarget*)pdropTarget );
+}
+
+void UnregisterFileDropping( HWND hwnd )
+{
+ RevokeDragDrop( hwnd );
+}
diff --git a/plugins/FloatingContacts/src/filedrop.h b/plugins/FloatingContacts/src/filedrop.h
new file mode 100644
index 0000000000..b5c7f803aa
--- /dev/null
+++ b/plugins/FloatingContacts/src/filedrop.h
@@ -0,0 +1,26 @@
+/* This file is a modification of clcfiledrop.h originally
+ written by Richard Hughes*/
+
+static HWND hwndCurDrag = NULL;
+
+class CDropTarget: public IDropTarget
+{
+private:
+ unsigned long refCount;
+
+public:
+ CDropTarget(): refCount(0) {}
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,LPVOID *ppvObj);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+ HRESULT STDMETHODCALLTYPE DragOver(DWORD fKeyState, POINTL pt, DWORD *pdwEffect);
+ HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pData, DWORD fKeyState, POINTL pt, DWORD *pdwEffect);
+ HRESULT STDMETHODCALLTYPE DragLeave();
+ HRESULT STDMETHODCALLTYPE Drop(IDataObject *pData,DWORD fKeyState,POINTL pt,DWORD *pdwEffect);
+};
+
+void InitFileDropping();
+void FreeFileDropping(void);
+void RegisterFileDropping( HWND hwnd, CDropTarget* pdropTarget );
+void UnregisterFileDropping( HWND hwnd );
diff --git a/plugins/FloatingContacts/src/fltcont.h b/plugins/FloatingContacts/src/fltcont.h
new file mode 100644
index 0000000000..3d725d71bc
--- /dev/null
+++ b/plugins/FloatingContacts/src/fltcont.h
@@ -0,0 +1,191 @@
+
+#ifndef __FLTCONT_H__
+#define __FLTCONT_H__
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+#define WND_CLASS _T("MirandaThumbsWnd")
+#define WM_REFRESH_CONTACT WM_USER + 0x100
+
+#ifndef WS_EX_LAYERED
+ #define WS_EX_LAYERED 0x00080000
+#endif
+
+#ifndef LWA_ALPHA
+ #define LWA_ALPHA 0x00000002
+#endif
+
+#ifndef ULW_ALPHA
+ #define ULW_ALPHA 0x00000002
+#endif
+
+#define TIMERID_SELECT_T 1
+#define TIMERID_HOVER_T 2
+#define TIMERID_TOTOP_T 3
+#define TIMERID_LEAVE_T 4
+
+
+#if WINVER < 0x0500
+ #define SM_XVIRTUALSCREEN 76
+ #define SM_YVIRTUALSCREEN 77
+ #define SM_CXVIRTUALSCREEN 78
+ #define SM_CYVIRTUALSCREEN 79
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+enum
+{
+ FLT_FONTID_CONTACTS,
+ FLT_FONTID_INVIS,
+ FLT_FONTID_OFFLINE,
+ FLT_FONTID_OFFINVIS,
+ FLT_FONTID_NOTONLIST,
+ FLT_FONTIDS,
+};
+
+#define DBFONTF_BOLD 1
+#define DBFONTF_ITALIC 2
+#define DBFONTF_UNDERLINE 4
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+#define FLT_DEFAULT_DRAWBORDER TRUE
+#define FLT_DEFAULT_LTEDGESCOLOR GetSysColor(COLOR_3DHILIGHT)
+#define FLT_DEFAULT_RBEDGESCOLOR GetSysColor(COLOR_3DDKSHADOW)
+#define FLT_DEFAULT_BKGNDCOLOR GetSysColor(COLOR_3DFACE)
+#define FLT_DEFAULT_BKGNDUSEBITMAP FALSE
+#define FLT_DEFAULT_BKGNDBITMAPOPT CLB_STRETCH
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+#define sModule "FloatingContacts"
+
+#define TOTOPTIME_P 1000
+#define TOTOPTIME_MAX (15*(60000/TOTOPTIME_P))
+#define TOTOPTIME_DEF (3*(60000/TOTOPTIME_P))
+
+#define MAXRCOOR 32767.0
+#define DB_POS_GETX(pos) (short)(((float)(short)(LOWORD(pos))*(float)GetSystemMetrics(SM_CXSCREEN))/MAXRCOOR+0.5)
+#define DB_POS_GETY(pos) (short)(((float)(short)(HIWORD(pos))*(float)GetSystemMetrics(SM_CYSCREEN))/MAXRCOOR+0.5)
+#define DB_POS_MAKE_XY(x, y) MAKELONG((short)(((float)x*MAXRCOOR)/(float)GetSystemMetrics(SM_CXSCREEN)+0.5), (short)(((float)y*MAXRCOOR)/(float)GetSystemMetrics(SM_CYSCREEN)+0.5))
+
+extern HINSTANCE hInst;
+extern BOOL bNT;
+//extern BOOL bHideOffline;
+//extern BOOL bHideAll;
+//extern BOOL bHideWhenFullscreen;
+//extern BOOL bMoveTogether;
+//extern BOOL bFixedWidth;
+//extern int nThumbWidth;
+//extern BYTE thumbAlpha;
+//extern BOOL bShowTip;
+extern BOOL bEnableTip;
+//extern WORD TimeIn;
+//extern BOOL bToTop;
+//extern WORD ToTopTime;
+//extern BOOL bHideWhenCListShow;
+
+extern BOOL bIsCListShow;
+extern HWND hwndMiranda;
+extern HIMAGELIST himl;
+extern RECT rcScreen;
+
+extern HFONT hFont[FLT_FONTIDS];
+extern COLORREF tColor[FLT_FONTIDS];
+
+extern HPEN hLTEdgesPen;
+extern HPEN hRBEdgesPen;
+extern HBRUSH hBkBrush;
+extern DWORD bkColor;
+extern HBITMAP hBmpBackground;
+extern WORD nBackgroundBmpUse;
+
+
+
+typedef struct _FCOptions
+{
+ BYTE thumbAlpha;
+ BOOL bHideOffline;
+ BOOL bHideAll;
+ BOOL bHideWhenFullscreen;
+ BOOL bMoveTogether;
+ BOOL bFixedWidth;
+ int nThumbWidth;
+ BOOL bShowTip;
+ WORD TimeIn;
+ BOOL bToTop;
+ WORD ToTopTime;
+ BOOL bHideWhenCListShow;
+ BOOL bUseSingleClick;
+ BOOL bShowIdle;
+}
+FCOptions;
+
+extern FCOptions fcOpt;
+
+extern BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
+extern BOOL (WINAPI *pUpdateLayeredWindow)
+ (HWND hwnd, HDC hdcDST, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc,
+ COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags);
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+static __forceinline BOOL ImageList_GetIconSize_my(HIMAGELIST himl, SIZE &sz)
+{
+ int cx, cy;
+ BOOL res = ImageList_GetIconSize(himl, &cx, &cy);
+ sz.cx = cx; sz.cy = cy;
+ return res;
+}
+
+void RegHotkey ( HANDLE hContact, HWND hwnd );
+BOOL IsStatusVisible ( int status );
+BOOL HideOnFullScreen ();
+void SendMsgDialog ( HWND hwnd, char *pText );
+void SaveContactsPos ( void );
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+void
+GetFontSetting
+ ( IN BOOL bFltContacts
+ , IN int nFontId
+ , IN LOGFONTA* lf
+ , IN COLORREF* colour
+ );
+
+void
+ApplyOptionsChanges();
+
+void
+OnStatusChanged();
+
+void
+SetThumbsOpacity
+ ( IN BYTE btAlpha
+ );
+
+int
+OnOptionsInitialize
+ ( IN WPARAM wParam
+ , IN LPARAM lParam
+ );
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // #ifndef __FLTCONT_H__
+
+/////////////////////////////////////////////////////////////////////////////
+// End Of File fltcont.h
diff --git a/plugins/FloatingContacts/src/main.cpp b/plugins/FloatingContacts/src/main.cpp
new file mode 100644
index 0000000000..f51e1f6d34
--- /dev/null
+++ b/plugins/FloatingContacts/src/main.cpp
@@ -0,0 +1,1268 @@
+/*
+Miranda Floating Contacts plugin, created by Iavor Vajarov ( ivajarov@code.bg )
+http://miranda-icq.sourceforge.net/
+
+Miranda fonts and colors settings by Ranger.
+Extended bonts and backgrounds settings by Oleksiy Shurubura
+
+
+This file is placed in the public domain. Anybody is free to use or
+modify it as they wish with no restriction.
+
+This plugin has been tested to work under Windows ME, 2000 and XP.
+
+No warranty for any misbehaviour.
+*/
+
+#include "stdhdr.h"
+#include "shlwapi.h"
+
+#include "version.h"
+
+#pragma comment ( lib, "comctl32.lib" )
+#pragma comment ( lib, "shlwapi.lib" )
+
+#pragma warning ( default : 4201 )
+
+//#define DB_POS_GETX(pos) LOWORD(pos)
+//#define DB_POS_GETY(pos) HIWORD(pos)
+//#define DB_POS_MAKE_XY(x, y) MAKELONG(x, y)
+
+BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND, COLORREF, BYTE, DWORD);
+BOOL (WINAPI *pUpdateLayeredWindow)
+ (HWND hwnd, HDC hdcDST, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc,
+ COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags);
+
+// Globals
+
+// TODO: move to some more approriate place, probably part of Thumbs manager
+static void LoadContacts ( void );
+static void LoadContact ( HANDLE hContact );
+
+// Internal funcs
+static void RepaintWindow ( HWND hwnd, HDC hdc );
+static void LoadMenus ();
+static void CreateThumbWnd ( TCHAR *ptszName, HANDLE hContact, int nX, int nY );
+static void RegisterWindowClass ( void );
+static void UnregisterWindowClass ( void );
+static void CleanUp ( void );
+static BOOL GetOSPlatform ( void );
+static void LoadDBSettings ( void );
+static void CreateThumbsFont ( void );
+static void CreateBackgroundBrush ( void );
+static int GetContactStatus ( HANDLE hContact );
+static void GetScreenRect ( void );
+extern void SetThumbsOpacity ( BYTE btAlpha );
+static int ClcStatusToPf2 ( int status );
+
+static LRESULT __stdcall CommWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
+static LRESULT __stdcall newMirandaWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+static int OnContactDeleted ( WPARAM wParam, LPARAM lParam );
+static int OnContactIconChanged ( WPARAM wParam, LPARAM lParam );
+static int OnContactDrag ( WPARAM wParam, LPARAM lParam );
+static int OnContactDrop ( WPARAM wParam, LPARAM lParam );
+static int OnContactDragStop ( WPARAM wParam, LPARAM lParam );
+static int OnSkinIconsChanged ( WPARAM wParam, LPARAM lParam );
+static int OnContactSettingChanged ( WPARAM wParam, LPARAM lParam );
+static int OnStatusModeChange ( WPARAM wParam, LPARAM lParam );
+static int OnModulesLoded ( WPARAM wParam, LPARAM lParam );
+static int OnPrebuildContactMenu ( WPARAM wParam, LPARAM lParam );
+
+static INT_PTR OnContactMenu_Remove ( WPARAM wParam, LPARAM lParam );
+static INT_PTR OnMainMenu_HideAll ( WPARAM wParam, LPARAM lParam );
+static INT_PTR OnHotKey_HideWhenCListShow( WPARAM wParam, LPARAM lParam );
+static VOID CALLBACK ToTopTimerProc ( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
+
+WNDPROC oldMirandaWndProc;
+
+
+HINSTANCE hInst = NULL;
+HMODULE hUserDll = NULL;
+HFONT hFont[FLT_FONTIDS] = {NULL};
+COLORREF tColor[FLT_FONTIDS] = {0};
+HIMAGELIST himl = NULL;
+HANDLE hevContactIcon = NULL;
+HANDLE hevContactDrop = NULL;
+HANDLE hevContactDragStop = NULL;
+HANDLE hevSkinIcons = NULL;
+HANDLE hevContactDrag = NULL;
+HANDLE hevContactSetting = NULL;
+HANDLE hevContactDeleted = NULL;
+HANDLE hevOptionsInit = NULL;
+HANDLE hevStatusMode = NULL;
+HANDLE hevModules = NULL;
+HANDLE hevPrebuildMenu = NULL;
+HANDLE hNewContact = NULL;
+
+HPEN hLTEdgesPen = NULL;
+HPEN hRBEdgesPen = NULL;
+HBRUSH hBkBrush = NULL;
+DWORD bkColor = 0;
+HBITMAP hBmpBackground = NULL;
+WORD nBackgroundBmpUse = CLB_STRETCH;
+
+HWND hwndMiranda = NULL;
+BOOL bVersionOK = FALSE;
+BOOL bNT = FALSE;
+BOOL bDockHorz = TRUE;
+//UINT nStatus = 0;
+HMENU hContactMenu = NULL;
+HANDLE hMenuItemRemove = NULL;
+HANDLE hMenuItemHideAll = NULL;
+HANDLE hMainMenuItemHideAll = NULL;
+RECT rcScreen;
+DWORD dwOfflineModes = 0;
+BOOL bEnableTip = FALSE;
+UINT_PTR ToTopTimerID = 0;
+BOOL bIsCListShow = TRUE;
+
+HANDLE hRemoveThumb = NULL;
+HANDLE hMainHideAllThumbs = NULL;
+HANDLE hHideWhenCListShow = NULL;
+int hLangpack;
+
+//Options
+
+FCOptions fcOpt = {0};
+
+static void InitOptions() {
+ fcOpt.thumbAlpha = 255;
+ fcOpt.bHideOffline = FALSE;
+ fcOpt.bHideAll = FALSE;
+ fcOpt.bHideWhenFullscreen = FALSE;
+ fcOpt.bMoveTogether = FALSE;
+ fcOpt.bFixedWidth = FALSE;
+ fcOpt.nThumbWidth = 0;
+ fcOpt.bShowTip = TRUE;
+ fcOpt.TimeIn = 0;
+ fcOpt.bToTop = TRUE;
+ fcOpt.ToTopTime = TOTOPTIME_DEF;
+ fcOpt.bHideWhenCListShow = FALSE;
+ fcOpt.bUseSingleClick = FALSE;
+ fcOpt.bShowIdle = TRUE;
+}
+
+// {53C715A8-EB01-4136-A73C-441868610074}
+#define MIID_FLTCONT { 0x53c715a8, 0xeb01, 0x4136, { 0xa7, 0x3c, 0x44, 0x18, 0x68, 0x61, 0x0, 0x74 } }
+
+PLUGININFOEX pluginInfoEx = {
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ 0,
+ __DESC,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ MIID_FLTCONT
+};
+
+_inline unsigned int MakeVer(int a, int b, int c, int d)
+{
+ return PLUGIN_MAKE_VERSION(a, b, c, d);
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfoEx;
+}
+
+
+///////////////////////////////////////////////////////
+// Load / unload
+BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
+{
+ hInst = hinstDLL;
+
+ switch ( fdwReason )
+ {
+ case DLL_PROCESS_ATTACH:
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return( TRUE );
+}
+
+extern "C" int __declspec(dllexport) Load( )
+{
+ SetLastError( 0 );
+ InitOptions();
+
+ mir_getLP(&pluginInfoEx);
+
+ hevModules = HookEvent( ME_SYSTEM_MODULESLOADED, OnModulesLoded );
+ bNT = GetOSPlatform();
+
+ if (hUserDll = LoadLibrary(_T("user32.dll"))) {
+ pSetLayeredWindowAttributes =
+ (BOOL (WINAPI *)(HWND, COLORREF, BYTE, DWORD))
+ GetProcAddress(hUserDll, "SetLayeredWindowAttributes");
+ pUpdateLayeredWindow =
+ (BOOL (WINAPI *)(HWND, HDC, POINT *, SIZE *, HDC, POINT *, COLORREF, BLENDFUNCTION *, DWORD))
+ GetProcAddress(hUserDll, "UpdateLayeredWindow");
+ }
+ else {
+ pSetLayeredWindowAttributes = NULL;
+ pUpdateLayeredWindow = NULL;
+ }
+
+ return 0;
+}
+
+
+
+extern "C" int __declspec(dllexport) Unload()
+{
+ CleanUp();
+ return 0;
+}
+
+
+
+static void CleanUp()
+{
+ int nFontId;
+
+ UnhookEvent( hevContactIcon );
+ UnhookEvent( hevContactDrag );
+ UnhookEvent( hevContactDrop );
+ UnhookEvent( hevContactDragStop );
+ UnhookEvent( hevSkinIcons );
+ UnhookEvent( hevContactDeleted );
+ UnhookEvent( hevContactSetting );
+ UnhookEvent( hevOptionsInit );
+ UnhookEvent( hevStatusMode );
+ UnhookEvent( hevModules );
+ UnhookEvent( hevPrebuildMenu );
+
+ if (hRemoveThumb)
+ DestroyServiceFunction(hRemoveThumb);
+ if (hMainHideAllThumbs)
+ DestroyServiceFunction(hMainHideAllThumbs);
+ if (hHideWhenCListShow)
+ DestroyServiceFunction(hHideWhenCListShow);
+
+ if (ServiceExists(MS_HOTKEY_UNREGISTER)) {
+ CallService(MS_HOTKEY_UNREGISTER, 0, (LPARAM)(sModule "/MainHideAllThumbs"));
+ CallService(MS_HOTKEY_UNREGISTER, 0, (LPARAM)(sModule "/HideWhenCListShow"));
+ }
+
+ if (NULL != hLTEdgesPen)
+ DeleteObject(hLTEdgesPen);
+ if (NULL != hRBEdgesPen)
+ DeleteObject(hRBEdgesPen);
+ if (NULL != hBmpBackground)
+ DeleteObject(hBmpBackground);
+ if (NULL != hBkBrush) {
+ SetClassLong((HWND)WND_CLASS, GCLP_HBRBACKGROUND, (LONG)NULL);
+ DeleteObject(hBkBrush);
+ hBkBrush = NULL;
+ }
+
+ for (nFontId = 0; nFontId < FLT_FONTIDS; nFontId++)
+ if (NULL != hFont[nFontId])
+ DeleteObject(hFont[nFontId]);
+
+ UnregisterWindowClass();
+
+ FreeFileDropping();
+
+ if ( hUserDll != NULL )
+ FreeLibrary( hUserDll );
+}
+
+
+
+///////////////////////////////////////////////////////
+// Hooked events
+static int OnModulesLoded( WPARAM wParam, LPARAM lParam )
+{
+ hevContactIcon = HookEvent( ME_CLIST_CONTACTICONCHANGED, OnContactIconChanged );
+ hevSkinIcons = HookEvent( ME_SKIN_ICONSCHANGED, OnSkinIconsChanged );
+ hevContactDrag = HookEvent( ME_CLUI_CONTACTDRAGGING, OnContactDrag );
+ hevContactDrop = HookEvent( ME_CLUI_CONTACTDROPPED, OnContactDrop );
+ hevContactDragStop = HookEvent( ME_CLUI_CONTACTDRAGSTOP, OnContactDragStop );
+ hevContactSetting = HookEvent( ME_DB_CONTACT_SETTINGCHANGED, OnContactSettingChanged );
+ hevContactDeleted = HookEvent( ME_DB_CONTACT_DELETED, OnContactDeleted );
+ hevOptionsInit = HookEvent( ME_OPT_INITIALISE, OnOptionsInitialize );
+ hevStatusMode = HookEvent( ME_CLIST_STATUSMODECHANGE, OnStatusModeChange );
+ hevPrebuildMenu = HookEvent( ME_CLIST_PREBUILDCONTACTMENU, OnPrebuildContactMenu );
+ hwndMiranda = (HWND)CallService( MS_CLUI_GETHWND, 0, 0 );
+
+ oldMirandaWndProc = (WNDPROC)SetWindowLongPtr( hwndMiranda, GWLP_WNDPROC, (LONG)newMirandaWndProc);
+
+
+
+ // No thumbs yet
+// pThumbsList = NULL;
+ bEnableTip = ServiceExists("mToolTip/ShowTip");
+
+ RegisterWindowClass();
+ InitFileDropping();
+ GetScreenRect();
+ LoadDBSettings();
+ CreateBackgroundBrush();
+ CreateThumbsFont();
+ LoadContacts();
+ LoadMenus();
+
+ if (fcOpt.bToTop){
+ fcOpt.ToTopTime = (fcOpt.ToTopTime<1)?1:fcOpt.ToTopTime;
+ fcOpt.ToTopTime = (fcOpt.ToTopTime>TOTOPTIME_MAX)?TOTOPTIME_MAX:fcOpt.ToTopTime;
+ ToTopTimerID = SetTimer(NULL, 0, fcOpt.ToTopTime*TOTOPTIME_P, ToTopTimerProc);
+ }
+ return( 0 );
+}
+
+
+static int OnContactDeleted( WPARAM wParam, LPARAM lParam )
+{
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+ if (!pThumb) return 0;
+
+ pThumb->DeleteContactPos();
+ thumbList.RemoveThumb(pThumb);
+
+ return 0;
+}
+
+
+static int OnContactIconChanged( WPARAM wParam, LPARAM lParam )
+{
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+
+ if ( pThumb )
+ {
+ pThumb->RefreshContactIcon( ( int )lParam );
+ //pThumb->ThumbSelect( FALSE );
+ //SetTimer( pThumb->hwnd, TIMERID_SELECT_T, 1000, NULL );
+ }
+
+ return 0;
+}
+
+
+static int OnContactDrag( WPARAM wParam, LPARAM lParam )
+{
+ ThumbInfo *pNewThumb = NULL;
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+ TCHAR *ptName = (TCHAR*)CallService( MS_CLIST_GETCONTACTDISPLAYNAME, wParam, (LPARAM)GCDNF_TCHAR );
+ int idStatus = ID_STATUS_OFFLINE;
+ POINT pt;
+ GetCursorPos(&pt);
+
+ if ( pThumb == NULL ) {
+ idStatus = GetContactStatus( hContact );
+
+ if ( !fcOpt.bHideAll && !HideOnFullScreen() && ( !fcOpt.bHideOffline || IsStatusVisible( idStatus )) && (!fcOpt.bHideWhenCListShow || !bIsCListShow)) {
+ CreateThumbWnd( ptName, hContact, pt.x, pt.y );
+ pNewThumb = thumbList.FindThumbByContact( hContact );
+ ShowWindow( pNewThumb->hwnd, SW_SHOWNA );
+ hNewContact = hContact;
+
+ OnStatusChanged();
+ }
+ }
+ else if ( hContact == hNewContact )
+ pThumb->PositionThumb( (short)( pt.x - 5 ), (short)( pt.y - 5 ));
+
+ return( hNewContact != NULL ? 1 : 0 );
+}
+
+
+
+static int OnContactDrop( WPARAM wParam, LPARAM lParam )
+{
+ RECT rcMiranda;
+ RECT rcThumb;
+// RECT rcOverlap;
+
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+
+ if ( ( hNewContact == hContact ) && ( pThumb != NULL ))
+ {
+ hNewContact = NULL;
+
+ GetWindowRect( hwndMiranda, &rcMiranda );
+ pThumb->GetThumbRect( &rcThumb );
+
+ //if ( IntersectRect( &rcOverlap, &rcThumb, &rcMiranda ))
+ //{
+ // pThumb->OnLButtonDown( (short)(rcThumb.left + 5), (short)(rcThumb.top + 5));
+ //}
+ }
+
+ SaveContactsPos();
+
+ return( 1 );
+}
+
+
+static int OnContactDragStop( WPARAM wParam, LPARAM lParam )
+{
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+
+ if ( ( pThumb != NULL ) && ( hNewContact == hContact ))
+ {
+ thumbList.RemoveThumb( pThumb );
+ hNewContact = NULL;
+ }
+
+ return( 0 );
+}
+
+
+static int OnSkinIconsChanged( WPARAM wParam, LPARAM lParam )
+{
+ // Get handle to the image list
+ himl = ( HIMAGELIST )CallService( MS_CLIST_GETICONSIMAGELIST, 0, 0 );
+
+ // Update thumbs
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ thumbList[i]->UpdateContent();
+
+ return( 0 );
+}
+
+
+
+static int OnContactSettingChanged( WPARAM wParam, LPARAM lParam )
+{
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+ int idStatus = ID_STATUS_OFFLINE;
+ BOOL bRefresh = TRUE;
+ DBCONTACTWRITESETTING* pdbcws = ( DBCONTACTWRITESETTING* )lParam;
+
+
+ if ( hContact == NULL )
+ {
+ if (( 0 == stricmp( pdbcws->szModule, "CLC" )) || ( 0 == stricmp( pdbcws->szModule, sModule )) ) {
+ LoadDBSettings();
+ ApplyOptionsChanges();
+ }
+
+ return( 0 );
+ }
+
+ if ( pThumb == NULL ) return( 0 );
+
+ // Only on these 2 events we need to refresh
+ if ( 0 == stricmp( pdbcws->szSetting, "Status" ))
+ {
+ idStatus = pdbcws->value.wVal;
+ }
+ else if ( 0 == stricmp( pdbcws->szSetting, "Nick" ))
+ {
+ idStatus = GetContactStatus( hContact );
+ }
+ else if ( 0 == stricmp( pdbcws->szSetting, "MyHandle" ))
+ {
+ idStatus = GetContactStatus( hContact );
+ }
+ else if ( fcOpt.bShowIdle && 0 == stricmp( pdbcws->szSetting, "IdleTS" ))
+ {
+ idStatus = GetContactStatus( hContact );
+ }
+ else
+ {
+ bRefresh = FALSE;
+ }
+
+ if ( bRefresh )
+ {
+ // Detach call
+ PostMessage( pThumb->hwnd, WM_REFRESH_CONTACT, 0, idStatus );
+ }
+
+ return( 0 );
+}
+
+
+static int OnStatusModeChange( WPARAM wParam, LPARAM lParam )
+{
+ int idStatus;
+
+ //nStatus = (int)wParam;
+
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ {
+ idStatus = GetContactStatus( thumbList[i]->hContact );
+ thumbList[i]->RefreshContactStatus( idStatus );
+ }
+ if ( wParam == ID_STATUS_OFFLINE )
+ {
+ // Floating status window will use this
+ }
+
+ return( 0 );
+}
+
+
+
+static int OnPrebuildContactMenu( WPARAM wParam, LPARAM lParam )
+{
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( (HANDLE) wParam );
+ CLISTMENUITEM clmi;
+
+ ZeroMemory( &clmi, sizeof( clmi ));
+ clmi.cbSize = sizeof( clmi );
+
+ clmi.flags = ( pThumb == NULL ) ? CMIM_FLAGS | CMIF_HIDDEN : CMIM_FLAGS &~CMIF_HIDDEN;
+ CallService( MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemRemove, (LPARAM)&clmi );
+
+ clmi.flags = fcOpt.bHideAll ? CMIM_FLAGS | CMIF_HIDDEN : CMIM_FLAGS &~CMIF_HIDDEN;
+ CallService( MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemHideAll, (LPARAM)&clmi );
+
+ return( 0 );
+}
+
+
+
+
+///////////////////////////////////////////////////////
+// General functions
+
+static void LoadDBSettings()
+{
+ fcOpt.thumbAlpha = (BYTE)((double)DBGetContactSettingByte( NULL, sModule, "Opacity", 100 ) * 2.55 );
+ fcOpt.bHideOffline = (BOOL)DBGetContactSettingByte( NULL, sModule, "HideOffline", 0 );
+ fcOpt.bHideAll = (BOOL)DBGetContactSettingByte( NULL, sModule, "HideAll", 0 );
+ fcOpt.bHideWhenFullscreen = (BOOL)DBGetContactSettingByte( NULL, sModule, "HideWhenFullscreen", 0 );
+ fcOpt.bMoveTogether = (BOOL)DBGetContactSettingByte( NULL, sModule, "MoveTogether", 0 );
+ fcOpt.bFixedWidth = (BOOL)DBGetContactSettingByte( NULL, sModule, "FixedWidth", 0 );
+ fcOpt.nThumbWidth = (DWORD)DBGetContactSettingDword( NULL, sModule, "Width", 0 );
+ dwOfflineModes = DBGetContactSettingDword( NULL, "CLC", "OfflineModes", CLCDEFAULT_OFFLINEMODES );
+ fcOpt.bShowTip = (BOOL)DBGetContactSettingByte( NULL, sModule, "ShowTip", 1 );
+ fcOpt.TimeIn = (WORD)DBGetContactSettingWord( NULL, sModule, "TimeIn", 0 );
+ fcOpt.bToTop = (BOOL)DBGetContactSettingByte( NULL, sModule, "ToTop", 0 );
+ fcOpt.ToTopTime = (WORD)DBGetContactSettingWord( NULL, sModule, "ToTopTime", TOTOPTIME_DEF );
+ fcOpt.bHideWhenCListShow = (BOOL)DBGetContactSettingByte( NULL, sModule, "HideWhenCListShow", 0 );
+ fcOpt.bUseSingleClick = (BOOL)DBGetContactSettingByte( NULL, sModule, "UseSingleClick", 0 );
+ fcOpt.bShowIdle = (BOOL)DBGetContactSettingByte( NULL, sModule, "ShowIdle", 0 );
+
+ if (DBGetContactSettingByte(NULL, "ModernData", "HideBehind", 0))
+ bIsCListShow = (DBGetContactSettingByte(NULL, "ModernData", "BehindEdge", 0) == 0);
+ else
+ bIsCListShow = (DBGetContactSettingByte(NULL, "CList", "State", 0) == 2);
+}
+
+void SendMsgDialog( HWND hwnd, char *pText )
+{
+ ThumbInfo *pThumb = thumbList.FindThumb( hwnd );
+
+ if ( pThumb != NULL )
+ CallService( MS_MSG_SENDMESSAGE, (WPARAM)pThumb->hContact, (LPARAM)pText );
+}
+
+
+static void ShowContactMenu( HWND hwnd, POINT pt )
+{
+ ThumbInfo *pThumb = thumbList.FindThumb( hwnd );
+ int idCommand = 0;
+
+ if ( pThumb != NULL )
+ {
+ hContactMenu = (HMENU)CallService( MS_CLIST_MENUBUILDCONTACT, (WPARAM)pThumb->hContact, (LPARAM)0 );
+
+ if ( hContactMenu == NULL ) return;
+
+ idCommand = TrackPopupMenu( hContactMenu, TPM_RIGHTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, 0 , hwnd, NULL );
+ CallService( MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM( idCommand , MPCF_CONTACTMENU), (LPARAM)pThumb->hContact );
+ }
+}
+
+static LRESULT __stdcall CommWndProc( HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ LRESULT lResult = 0;
+ ThumbInfo *pThumb = thumbList.FindThumb( hwnd );
+
+ switch( uMsg )
+ {
+ case WM_RBUTTONUP:
+ {
+ POINT pt;
+ pt.x = LOWORD( lParam );
+ pt.y = HIWORD( lParam );
+
+ if (pThumb) pThumb->ThumbDeselect( TRUE );
+
+ ClientToScreen(hwnd, &pt);
+ ShowContactMenu( hwnd, pt );
+ }
+
+ break;
+
+//#if 0
+ case WM_NCPAINT:
+ if (pThumb){
+ HDC hdc = GetWindowDC( hwnd );
+ BitBlt(hdc, 0, 0, pThumb->bmpContent.getWidth(), pThumb->bmpContent.getHeight(), pThumb->bmpContent.getDC(), 0, 0, SRCCOPY);
+ //RepaintWindow( hwnd, hdc );
+ ReleaseDC( hwnd, hdc );
+ ValidateRect( hwnd, NULL );
+ return 0;
+ }
+
+ case WM_PAINT:
+ if (pThumb){
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hwnd, &ps);
+ BitBlt(hdc, 0, 0, pThumb->bmpContent.getWidth(), pThumb->bmpContent.getHeight(), pThumb->bmpContent.getDC(), 0, 0, SRCCOPY);
+ //RepaintWindow( hwnd, hdc );
+ EndPaint(hwnd, &ps);
+ break;
+ }
+
+ case WM_PRINT:
+ case WM_PRINTCLIENT:
+ if (pThumb){
+ BitBlt((HDC)wParam, 0, 0, pThumb->bmpContent.getWidth(), pThumb->bmpContent.getHeight(), pThumb->bmpContent.getDC(), 0, 0, SRCCOPY);
+ //RepaintWindow(hwnd, (HDC)wParam);
+ break;
+ }
+//#endif
+
+ case WM_MEASUREITEM:
+ lResult = CallService( MS_CLIST_MENUMEASUREITEM, wParam, lParam );
+ break;
+
+ case WM_DRAWITEM:
+ lResult = CallService( MS_CLIST_MENUDRAWITEM, wParam, lParam );
+ break;
+
+ case WM_LBUTTONDOWN:
+ if (pThumb) pThumb->OnLButtonDown( (short)LOWORD( lParam ), (short)HIWORD( lParam ));
+ break;
+
+ case WM_MOUSEMOVE:
+ if (pThumb) pThumb->OnMouseMove( (short)LOWORD( lParam ), (short)HIWORD( lParam ), wParam);
+ break;
+
+ case WM_LBUTTONUP:
+ if (pThumb) pThumb->OnLButtonUp();
+ //if (bMouseMoved || !DBGetContactSettingByte(NULL, "CList", "Tray1Click", SETTING_TRAY1CLICK_DEFAULT))
+ break;
+ // FALL THRU
+
+ case WM_LBUTTONDBLCLK:
+ // Popup message dialog
+ //if (pThumb) pThumb->ThumbDeselect( TRUE );
+ if (!fcOpt.bUseSingleClick && pThumb)
+ pThumb->PopUpMessageDialog();
+ break;
+
+ case WM_RBUTTONDOWN:
+ if (bEnableTip && fcOpt.bShowTip && pThumb) pThumb->KillTip();
+ break;
+ case WM_REFRESH_CONTACT:
+ if (pThumb)
+ {
+ _tcsncpy( pThumb->ptszName, (TCHAR*)CallService( MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)pThumb->hContact, (LPARAM)GCDNF_TCHAR ), USERNAME_LEN - 1 );
+ pThumb->RefreshContactStatus( (int)lParam );
+ pThumb->ResizeThumb();
+ }
+ break;
+
+ case WM_TIMER:
+ if (pThumb)pThumb->OnTimer(wParam);
+ break;
+
+ case WM_HOTKEY:
+ {
+ ThumbInfo *pThumb = thumbList.FindThumb( ( HWND )wParam );
+
+ if (pThumb) pThumb->PopUpMessageDialog();
+ }
+
+ default:
+ break;
+ }
+
+ lResult = DefWindowProc( hwnd, uMsg, wParam, lParam );
+
+ return( lResult );
+}
+
+
+
+extern void SetThumbsOpacity( BYTE btAlpha )
+{
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ thumbList[i]->SetThumbOpacity( btAlpha );
+}
+
+
+
+static void GetScreenRect()
+{
+ rcScreen.left = GetSystemMetrics( SM_XVIRTUALSCREEN );
+ rcScreen.top = GetSystemMetrics( SM_YVIRTUALSCREEN );
+ rcScreen.right = GetSystemMetrics( SM_CXVIRTUALSCREEN ) + rcScreen.left;
+ rcScreen.bottom = GetSystemMetrics( SM_CYVIRTUALSCREEN ) + rcScreen.top;
+}
+
+
+
+void OnStatusChanged()
+{
+ int idStatus = ID_STATUS_OFFLINE;
+
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ {
+ idStatus = GetContactStatus( thumbList[i]->hContact );
+ thumbList[i]->RefreshContactStatus( idStatus );
+ }
+}
+
+
+
+void ApplyOptionsChanges()
+{
+ CreateThumbsFont();
+ CreateBackgroundBrush();
+
+// dwOfflineModes = DBGetContactSettingDword( NULL, "CLC", "OfflineModes", CLCDEFAULT_OFFLINEMODES );
+ if (!fcOpt.bToTop && ToTopTimerID){
+ KillTimer(NULL, ToTopTimerID);
+ ToTopTimerID = 0;
+ }
+ if (fcOpt.bToTop){
+ if (ToTopTimerID) KillTimer(NULL, ToTopTimerID);
+ fcOpt.ToTopTime = (fcOpt.ToTopTime<1)?1:fcOpt.ToTopTime;
+ fcOpt.ToTopTime = (fcOpt.ToTopTime>TOTOPTIME_MAX)?TOTOPTIME_MAX:fcOpt.ToTopTime;
+ ToTopTimerID = SetTimer(NULL, 0, fcOpt.ToTopTime*TOTOPTIME_P, ToTopTimerProc);
+ }
+
+ OnStatusChanged();
+
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ thumbList[i]->ResizeThumb();
+}
+
+
+
+///////////////////////////////////////////////////////
+// Window creation
+static void RegisterWindowClass()
+{
+ WNDCLASSEX wcx;
+ ZeroMemory( &wcx, sizeof( wcx ));
+
+ wcx.cbSize = sizeof( WNDCLASSEX );
+ wcx.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
+ wcx.lpfnWndProc = CommWndProc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = 0;
+ wcx.hInstance = hInst;
+ wcx.hIcon = NULL;
+ wcx.hCursor = NULL;
+ wcx.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = WND_CLASS;
+ wcx.hIconSm = NULL;
+
+ SetLastError( 0 );
+
+ RegisterClassEx( &wcx );
+}
+
+
+
+static void UnregisterWindowClass()
+{
+ UnregisterClass( WND_CLASS, hInst );
+}
+
+
+
+static void CreateThumbWnd( TCHAR *ptszName, HANDLE hContact, int nX, int nY )
+{
+ HWND hwnd = NULL;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+
+ // Prepare for window creation
+ if ( pThumb == NULL )
+ {
+ hwnd = CreateWindowEx( WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
+ WND_CLASS,
+ ptszName,
+ WS_POPUP,
+ nX,
+ nY,
+ 50,
+ 20,
+ NULL /*hwndMiranda*/,
+ NULL,
+ hInst,
+ NULL
+ );
+
+ if ( hwnd != NULL )
+ {
+ pThumb = thumbList.AddThumb( hwnd, ptszName, hContact );
+ SetWindowLongPtr( hwnd, GWLP_USERDATA, (long)pThumb );
+ pThumb->ResizeThumb();
+
+ pThumb->SetThumbOpacity( fcOpt.thumbAlpha );
+ ShowWindow( hwnd, ( fcOpt.bHideAll || HideOnFullScreen() || fcOpt.bHideOffline || (fcOpt.bHideWhenCListShow && bIsCListShow))? SW_HIDE : SW_SHOWNA );
+ pThumb->PositionThumb( (short)nX, (short)nY );
+
+ // force repaint
+ pThumb->UpdateContent();
+ }
+ }
+}
+
+
+
+static BOOL GetOSPlatform()
+{
+ OSVERSIONINFO VersionInfo;
+
+ // Get OS platform
+ ZeroMemory( &VersionInfo, sizeof( VersionInfo ));
+ VersionInfo.dwOSVersionInfoSize = sizeof( VersionInfo );
+
+ GetVersionEx( &VersionInfo );
+ return( VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT );
+}
+
+
+
+static void CreateThumbsFont()
+{
+ int nFontId;
+ LOGFONTA lf;
+
+ for (nFontId = 0; nFontId < FLT_FONTIDS; nFontId++)
+ {
+ if (NULL != hFont[nFontId])
+ {
+ DeleteObject(hFont[nFontId]);
+ hFont[nFontId] = NULL;
+ }
+ GetFontSetting(TRUE, nFontId, &lf, &tColor[nFontId]);
+ {
+ LONG height;
+ HDC hdc = GetDC(NULL);
+ height = lf.lfHeight;
+ lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ ReleaseDC(NULL, hdc);
+
+ hFont[nFontId] = CreateFontIndirectA(&lf);
+
+ lf.lfHeight = height;
+ }
+ }
+}
+
+
+
+static void CreateBackgroundBrush()
+{
+// LOGBRUSH lb;
+ bkColor = DBGetContactSettingDword(NULL, sModule, "BkColor", FLT_DEFAULT_BKGNDCOLOR);
+
+
+ if (NULL != hLTEdgesPen)
+ {
+ DeleteObject(hLTEdgesPen);
+ hLTEdgesPen = NULL;
+ }
+ if (NULL != hRBEdgesPen)
+ {
+ DeleteObject(hRBEdgesPen);
+ hRBEdgesPen = NULL;
+ }
+ if (NULL != hBmpBackground)
+ {
+ DeleteObject(hBmpBackground);
+ hBmpBackground = NULL;
+ }
+ if (NULL != hBkBrush)
+ {
+ SetClassLong((HWND)WND_CLASS, GCLP_HBRBACKGROUND, (LONG)NULL);
+ DeleteObject( hBkBrush );
+ hBkBrush = NULL;
+ }
+
+ if (DBGetContactSettingByte(NULL, sModule, "DrawBorder", FLT_DEFAULT_DRAWBORDER))
+ {
+ COLORREF cr;
+
+ cr = (COLORREF)DBGetContactSettingDword(NULL, sModule, "LTEdgesColor", FLT_DEFAULT_LTEDGESCOLOR);
+ hLTEdgesPen = CreatePen(PS_SOLID, 1, cr);
+ cr = (COLORREF)DBGetContactSettingDword(NULL, sModule, "RBEdgesColor", FLT_DEFAULT_RBEDGESCOLOR);
+ hRBEdgesPen = CreatePen(PS_SOLID, 1, cr);
+ }
+ if (DBGetContactSettingByte(NULL, sModule, "BkUseBitmap", FLT_DEFAULT_BKGNDUSEBITMAP))
+ {
+ DBVARIANT dbv;
+
+ if (!DBGetContactSetting(NULL, sModule, "BkBitmap", &dbv))
+ {
+ hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (LPARAM)dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ nBackgroundBmpUse = (WORD)DBGetContactSettingWord(NULL, sModule, "BkBitmapOpt", FLT_DEFAULT_BKGNDBITMAPOPT);
+
+ // Create brush
+ hBkBrush = CreateSolidBrush(bkColor);
+
+ // Attach brush to the window
+ SetClassLong((HWND)WND_CLASS, GCLP_HBRBACKGROUND, (LONG)hBkBrush);
+}
+
+
+static int GetContactStatus( HANDLE hContact )
+{
+ char *szProto = NULL;
+ int idStatus = ID_STATUS_OFFLINE;
+
+ if ( hContact == NULL )
+ {
+ assert( !"Contact is NULL" );
+ return( 0 );
+ }
+
+ szProto = ( char* )CallService( "Proto/GetContactBaseProto", (WPARAM)hContact, 0 );
+
+ if ( NULL != szProto )
+ {
+ idStatus = DBGetContactSettingWord( hContact, szProto, "Status", ID_STATUS_OFFLINE );
+ }
+
+
+ return( idStatus );
+}
+
+
+static int ClcStatusToPf2( int status )
+{
+ switch(status) {
+ case ID_STATUS_ONLINE: return PF2_ONLINE;
+ case ID_STATUS_AWAY: return PF2_SHORTAWAY;
+ case ID_STATUS_DND: return PF2_HEAVYDND;
+ case ID_STATUS_NA: return PF2_LONGAWAY;
+ case ID_STATUS_OCCUPIED: return PF2_LIGHTDND;
+ case ID_STATUS_FREECHAT: return PF2_FREECHAT;
+ case ID_STATUS_INVISIBLE: return PF2_INVISIBLE;
+ case ID_STATUS_ONTHEPHONE: return PF2_ONTHEPHONE;
+ case ID_STATUS_OUTTOLUNCH: return PF2_OUTTOLUNCH;
+ case ID_STATUS_OFFLINE: return MODEF_OFFLINE;
+ }
+ return 0;
+}
+
+BOOL IsStatusVisible( int status )
+{
+ return ( 0 == ( dwOfflineModes & ClcStatusToPf2( status )) );
+}
+
+
+
+void RegHotkey( HANDLE hContact, HWND hwnd )
+{
+ char szBuf[ MAX_PATH ] = {0};
+/* char szPath[ MAX_PATH ] = {0};
+
+ GetModuleFileName( NULL, szPath, MAX_PATH );
+ PathRemoveFileSpec( szPath );
+ strcat( szPath, "\\Thumbs.ini" );
+ GetPrivateProfileString( "Hotkeys", szName, "", szBuf, MAX_PATH - 1, szPath );*/
+ DBVARIANT dbv;
+ if (DBGetContactSettingString ( hContact, sModule, "Hotkey", &dbv)) return;
+ strncpy(szBuf, dbv.pszVal, MAX_PATH - 1);
+ DBFreeVariant( &dbv );
+
+ if ( 0 != strlen( szBuf ))
+ {
+ UINT nModifiers = 0;
+ char chKey = 0;
+ char szMod[ 2 ][ 20 ] = {0};
+ char szKey[ 20 ] = {0};
+ int i = 0;
+
+ sscanf( szBuf, "%[^'+']+%[^'+']+%[^'+']", szMod[ 0 ], szMod[ 1 ], szKey );
+
+ for ( i = 0; i < 2; ++i )
+ {
+ if ( 0 == strncmp( szMod[ i ], "ALT", 19 ))
+ {
+ nModifiers = nModifiers | MOD_ALT;
+ }
+ else if ( 0 == strncmp( szMod[ i ], "CTRL", 19 ))
+ {
+ nModifiers = nModifiers | MOD_CONTROL;
+ }
+ else if ( 0 == strncmp( szMod[ i ], "SHIFT", 19 ))
+ {
+ nModifiers = nModifiers | MOD_SHIFT;
+ }
+ }
+
+ chKey = szKey[ 0 ];
+
+ RegisterHotKey( hwnd, (int)hwnd, nModifiers, VkKeyScan( chKey ));
+ }
+}
+
+
+
+///////////////////////////////////////////////////////
+// Contact sttings
+
+void SaveContactsPos()
+{
+ RECT rc;
+
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ {
+ SetLastError( 0 );
+
+ thumbList[i]->GetThumbRect( &rc );
+
+ if ( 0 == GetLastError())
+ DBWriteContactSettingDword( thumbList[i]->hContact, sModule, "ThumbsPos", DB_POS_MAKE_XY(rc.left, rc.top));
+ }
+}
+
+
+static void LoadContacts()
+{
+ HANDLE hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0) ;
+ while( hContact != NULL ) {
+ LoadContact( hContact );
+ hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDNEXT, ( WPARAM ) hContact, 0 );
+ }
+}
+
+
+
+
+static void LoadMenus()
+{
+ // Remove thumb menu item
+ hRemoveThumb = CreateServiceFunction( sModule "/RemoveThumb", OnContactMenu_Remove );
+
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof( mi );
+ mi.position = 0xFFFFF;
+ mi.flags = CMIF_TCHAR;
+ mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_HIDE ));
+ mi.ptszName = _T("Remove thumb");
+ mi.pszService = sModule "/RemoveThumb";
+ hMenuItemRemove = Menu_AddContactMenuItem(&mi);
+
+ // Hide all thumbs main menu item
+ hMainHideAllThumbs = CreateServiceFunction( sModule "/MainHideAllThumbs", OnMainMenu_HideAll );
+ ZeroMemory( &mi, sizeof( mi ));
+
+ mi.cbSize = sizeof( mi );
+ mi.position = 0xFFFFF;
+ mi.flags = CMIF_TCHAR;
+ mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( fcOpt.bHideAll ? IDI_SHOW : IDI_HIDE ));
+ mi.ptszName = fcOpt.bHideAll ? _T("Show all thumbs") : _T("Hide all thumbs");
+ mi.pszService = sModule "/MainHideAllThumbs";
+ Menu_AddMainMenuItem(&mi);
+
+ // Register hotkeys
+ HOTKEYDESC hkd = {0};
+ hkd.cbSize = sizeof(hkd);
+ hkd.pszSection = "Floating Contacts";
+
+ hkd.pszName = sModule "/MainHideAllThumbs";
+ hkd.pszDescription = LPGEN("Show/Hide all thumbs");
+ hkd.pszService = sModule "/MainHideAllThumbs";
+ Hotkey_Register(&hkd);
+
+ hHideWhenCListShow = CreateServiceFunction( sModule "/HideWhenCListShow", OnHotKey_HideWhenCListShow );
+ hkd.pszName = sModule "/HideWhenCListShow";
+ hkd.pszDescription = LPGEN("Hide when contact list is shown");
+ hkd.pszService = sModule "/HideWhenCListShow";
+ Hotkey_Register(&hkd);
+}
+
+
+static void LoadContact( HANDLE hContact )
+{
+ DWORD dwPos = (DWORD)-1;
+ TCHAR *ptName = NULL;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+ int nX, nY;
+
+
+ if ( hContact == NULL ) return;
+
+ dwPos = DBGetContactSettingDword( hContact, sModule, "ThumbsPos", (DWORD)-1 );
+
+ if ( dwPos != -1 )
+ {
+ ptName = (TCHAR*)CallService( MS_CLIST_GETCONTACTDISPLAYNAME, ( WPARAM )hContact, (LPARAM)GCDNF_TCHAR );
+
+ if ( ptName != NULL )
+ {
+ nX = DB_POS_GETX( dwPos );
+ nY = DB_POS_GETY( dwPos );
+
+ CreateThumbWnd( ptName, hContact, nX, nY );
+ pThumb->PositionThumb( (short)nX, (short)nY );
+ }
+ }
+}
+
+
+BOOL HideOnFullScreen()
+{
+ BOOL bFullscreen = FALSE;
+ HWND hWnd = 0;
+
+ if ( fcOpt.bHideWhenFullscreen )
+ {
+ int w = GetSystemMetrics(SM_CXSCREEN);
+ int h = GetSystemMetrics(SM_CYSCREEN);
+
+ hWnd = GetForegroundWindow();
+
+ while (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
+ {
+ RECT WindowRect;
+ GetWindowRect(hWnd, &WindowRect);
+
+ if ( (w == (WindowRect.right - WindowRect.left)) &&
+ (h == (WindowRect.bottom - WindowRect.top)))
+ {
+ bFullscreen = TRUE;
+ break;
+ }
+
+ hWnd = GetNextWindow( hWnd, GW_HWNDNEXT );
+ }
+ }
+
+ return bFullscreen && fcOpt.bHideWhenFullscreen;
+}
+
+
+static INT_PTR OnContactMenu_Remove( WPARAM wParam, LPARAM lParam )
+{
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+
+ if (pThumb) {
+ pThumb->DeleteContactPos();
+ thumbList.RemoveThumb(pThumb);
+ }
+
+ DestroyMenu( hContactMenu );
+ return 0;
+}
+
+static INT_PTR OnHotKey_HideWhenCListShow( WPARAM wParam, LPARAM lParam )
+{
+ fcOpt.bHideWhenCListShow = !fcOpt.bHideWhenCListShow;
+ DBWriteContactSettingByte(NULL, sModule, "HideWhenCListShow", (BYTE)fcOpt.bHideWhenCListShow);
+ OnStatusChanged();
+ return 0;
+}
+
+
+static INT_PTR OnMainMenu_HideAll( WPARAM wParam, LPARAM lParam )
+{
+ CLISTMENUITEM clmi = {0};
+ int b;
+
+ fcOpt.bHideAll = !fcOpt.bHideAll;
+ DBWriteContactSettingByte(NULL, sModule, "HideAll", (BYTE)fcOpt.bHideAll);
+ OnStatusChanged();
+
+ clmi.cbSize = sizeof( clmi );
+ clmi.flags = CMIM_NAME | CMIM_ICON|CMIF_TCHAR;
+ clmi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( fcOpt.bHideAll ? IDI_SHOW : IDI_HIDE ));
+ clmi.ptszName = fcOpt.bHideAll ? _T("Show all thumbs") : _T("Hide all thumbs");
+ b = CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMainMenuItemHideAll, ( LPARAM )&clmi );
+ return 0;
+}
+
+static VOID CALLBACK ToTopTimerProc ( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ {
+ SetWindowPos(thumbList[i]->hwnd,
+ HWND_TOPMOST,
+ 0,
+ 0,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOMOVE | /*SWP_NOZORDER |*/ SWP_NOACTIVATE);
+ }
+}
+
+void ShowThumbsOnHideCList()
+{
+ if (!fcOpt.bHideWhenCListShow || fcOpt.bHideAll || HideOnFullScreen())
+ return;
+
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ if ( !fcOpt.bHideOffline || IsStatusVisible( GetContactStatus(thumbList[i]->hContact)))
+ ShowWindow( thumbList[i]->hwnd, SW_SHOWNA );
+}
+
+
+void HideThumbsOnShowCList()
+{
+ if (!fcOpt.bHideWhenCListShow || fcOpt.bHideAll || HideOnFullScreen())return;
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ ShowWindow( thumbList[i]->hwnd, SW_HIDE );
+}
+
+static LRESULT __stdcall newMirandaWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ if ( uMsg == WM_WINDOWPOSCHANGED) {
+ WINDOWPOS *wp = (WINDOWPOS *)lParam;
+ if (wp->flags&SWP_HIDEWINDOW) {
+ bIsCListShow = FALSE;
+ ShowThumbsOnHideCList();
+ }
+ else if (wp->flags&SWP_SHOWWINDOW){
+ bIsCListShow = TRUE;
+ HideThumbsOnShowCList();
+ }
+ else if (!(wp->flags&SWP_NOMOVE)) {
+ BYTE method = DBGetContactSettingByte(NULL, "ModernData", "HideBehind", 0);
+ if (method) {
+ WORD wBehindEdgeBorderSize = DBGetContactSettingWord(NULL, "ModernData", "HideBehindBorderSize", 0);
+ RECT rc = {wp->x, wp->y, wp->x+wp->cx, wp->y+wp->cy};
+ RECT rcScreen = {wBehindEdgeBorderSize*(2-method), 0, GetSystemMetrics(SM_CXSCREEN)-wBehindEdgeBorderSize*(method-1), GetSystemMetrics(SM_CYSCREEN)};
+ RECT rcOverlap;
+ BOOL isIntersect;
+
+ isIntersect = IntersectRect( &rcOverlap, &rc, &rcScreen );
+ if ( !isIntersect && bIsCListShow ) {
+ bIsCListShow = FALSE;
+ ShowThumbsOnHideCList();
+ }
+ else if ( isIntersect && !bIsCListShow ) {
+ bIsCListShow = TRUE;
+ HideThumbsOnShowCList();
+ }
+ }
+ }
+ }
+ return( CallWindowProc(oldMirandaWndProc, hwnd, uMsg, wParam, lParam));
+}
diff --git a/plugins/FloatingContacts/src/options.cpp b/plugins/FloatingContacts/src/options.cpp
new file mode 100644
index 0000000000..cee946a438
--- /dev/null
+++ b/plugins/FloatingContacts/src/options.cpp
@@ -0,0 +1,1171 @@
+
+#include "stdhdr.h"
+
+#include "resource.h"
+#include "fltcont.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+#define SAMEASF_FACE 1
+#define SAMEASF_SIZE 2
+#define SAMEASF_STYLE 4
+#define SAMEASF_COLOUR 8
+
+typedef struct _SFontSettings
+{
+ BYTE sameAsFlags,sameAs;
+ COLORREF colour;
+ char size;
+ BYTE style;
+ BYTE charset;
+ char szFace[LF_FACESIZE];
+} SFontSettings;
+
+static SFontSettings s_rgFontSettings[FLT_FONTIDS];
+static SFontSettings s_rgFontSettingsMiranda[FLT_FONTIDS];
+
+#define FLT_SAME_AS_NONE ((BYTE)0xFF)
+#define FLT_SAME_AS_MIRANDA ((BYTE)0xFE)
+
+static char* s_rgszFontSizes[] = {"8","10","14","16","18","20","24","28"};
+
+static const TCHAR* s_rgszFontIdDescr[FLT_FONTIDS] =
+{
+ _T("Standard contacts"),
+ _T("Online contacts to whom you have a different visibility"),
+ _T("Offline contacts"),
+ _T("Offline contacts to whom you have a different visibility"),
+ _T("Contacts which are 'not on list'"),
+};
+
+static WORD s_rgwFontSameAsDefault[FLT_FONTIDS] =
+{
+ MAKEWORD(FLT_SAME_AS_MIRANDA, 0x0F),
+ MAKEWORD(FLT_SAME_AS_MIRANDA, 0x0F),
+ MAKEWORD(FLT_SAME_AS_MIRANDA, 0x0F),
+ MAKEWORD(FLT_SAME_AS_MIRANDA, 0x0F),
+ MAKEWORD(FLT_SAME_AS_MIRANDA, 0x0F),
+};
+
+static int s_rgnMirandaFontId[FLT_FONTIDS] =
+{
+ FONTID_CONTACTS,
+ FONTID_INVIS,
+ FONTID_OFFLINE,
+ FONTID_OFFINVIS,
+ FONTID_NOTONLIST
+};
+
+#define M_REBUILDFONTGROUP (WM_USER + 10)
+#define M_REMAKESAMPLE (WM_USER + 11)
+#define M_RECALCONEFONT (WM_USER + 12)
+#define M_RECALCOTHERFONTS (WM_USER + 13)
+#define M_SAVEFONT (WM_USER + 14)
+#define M_REFRESHSAMEASBOXES (WM_USER + 15)
+#define M_FILLSCRIPTCOMBO (WM_USER + 16)
+#define M_LOADFONT (WM_USER + 17)
+#define M_GUESSSAMEASBOXES (WM_USER + 18)
+#define M_SETSAMEASBOXES (WM_USER + 19)
+
+#define M_REFRESHBKGBOXES (WM_USER + 20)
+#define M_REFRESHBORDERPICKERS (WM_USER + 21)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+static
+LRESULT
+APIENTRY
+OptWndProc
+ ( IN HWND hwndDlg
+ , IN UINT uMsg
+ , IN WPARAM wParam
+ , IN LPARAM lParam
+ );
+
+static
+LRESULT
+APIENTRY
+OptSknWndProc
+ ( IN HWND hwndDlg
+ , IN UINT uMsg
+ , IN WPARAM wParam
+ , IN LPARAM lParam
+ );
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+int
+OnOptionsInitialize
+ ( IN WPARAM wParam
+ , IN LPARAM lParam
+ )
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_FLTCONT);
+ odp.pszTitle = LPGEN("Floating Contacts");
+ odp.pszGroup = LPGEN("Plugins");
+ odp.pszTab = LPGEN("Main Features");
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = (DLGPROC)OptWndProc;
+ Options_AddPage(wParam, &odp);
+
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SKIN);
+ odp.pszTab = LPGEN("Appearance");
+ odp.pfnDlgProc = (DLGPROC)OptSknWndProc;
+ Options_AddPage(wParam, &odp);
+
+ return 0;
+}
+
+static
+int
+CALLBACK
+EnumFontsProc
+ ( IN ENUMLOGFONTEXA* lpelfe
+ , IN NEWTEXTMETRICEXA* lpntme
+ , IN int FontType
+ , IN LPARAM lParam
+ )
+{
+ if (IsWindow((HWND)lParam))
+ {
+ if (CB_ERR == SendMessageA((HWND)lParam, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)lpelfe->elfLogFont.lfFaceName))
+ SendMessageA((HWND)lParam, CB_ADDSTRING, 0, (LPARAM)lpelfe->elfLogFont.lfFaceName);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+FillFontListThread
+ ( IN HWND hwndDlg
+ )
+{
+ LOGFONTA lf = {0};
+ HDC hdc = GetDC(hwndDlg);
+
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfFaceName[0] = 0;
+ lf.lfPitchAndFamily = 0;
+ EnumFontFamiliesExA(hdc, &lf, (FONTENUMPROCA)EnumFontsProc, (LPARAM)GetDlgItem(hwndDlg,IDC_TYPEFACE), 0);
+ ReleaseDC(hwndDlg, hdc);
+ return;
+}
+
+static
+int
+CALLBACK
+EnumFontScriptsProc
+ ( IN ENUMLOGFONTEX* lpelfe
+ , IN NEWTEXTMETRICEX* lpntme
+ , IN int FontType
+ , IN LPARAM lParam
+ )
+{
+ if (CB_ERR == SendMessage((HWND)lParam, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)lpelfe->elfScript))
+ {
+ int i = SendMessage((HWND)lParam, CB_ADDSTRING, 0, (LPARAM)lpelfe->elfScript);
+ SendMessage((HWND)lParam, CB_SETITEMDATA, i, lpelfe->elfLogFont.lfCharSet);
+ }
+ return TRUE;
+}
+
+static
+void
+GetDefaultFontSetting
+ ( IN BOOL bFltContacts
+ , IN int nFontId
+ , IN LOGFONTA* lf
+ , IN COLORREF* colour
+ )
+{
+ SystemParametersInfoA(SPI_GETICONTITLELOGFONT, sizeof(LOGFONTA), lf, FALSE);
+ *colour = GetSysColor(COLOR_WINDOWTEXT);
+ if (bFltContacts)
+ {
+ switch (nFontId)
+ {
+ case FLT_FONTID_OFFINVIS:
+ case FLT_FONTID_INVIS:
+ lf->lfItalic = !lf->lfItalic;
+ break;
+
+ case FLT_FONTID_NOTONLIST:
+ *colour = GetSysColor(COLOR_3DSHADOW);
+ break;
+ }
+ }
+ else
+ {
+ switch (s_rgnMirandaFontId[nFontId])
+ {
+ case FONTID_OFFINVIS:
+ case FONTID_INVIS:
+ lf->lfItalic = !lf->lfItalic;
+ break;
+
+ case FONTID_NOTONLIST:
+ *colour = GetSysColor(COLOR_3DSHADOW);
+ break;
+ }
+ }
+}
+
+void
+GetFontSetting
+ ( IN BOOL bFltContacts
+ , IN int nFontId
+ , IN LOGFONTA* lf
+ , IN COLORREF* colour
+ )
+{
+ DBVARIANT dbv;
+ char idstr[10];
+ BYTE style;
+ const char* pModule = (bFltContacts ? sModule : "CLC");
+
+ GetDefaultFontSetting(bFltContacts, nFontId, lf, colour);
+ if (!bFltContacts)
+ nFontId = s_rgnMirandaFontId[nFontId];
+ wsprintfA(idstr, "Font%dName", nFontId);
+ if (!DBGetContactSetting(NULL, pModule, idstr, &dbv))
+ {
+ lstrcpyA(lf->lfFaceName, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+
+ wsprintfA(idstr, "Font%dCol", nFontId);
+ *colour = DBGetContactSettingDword(NULL, pModule, idstr, *colour);
+
+ wsprintfA(idstr, "Font%dSize", nFontId);
+ lf->lfHeight = (char)DBGetContactSettingByte(NULL, pModule, idstr, lf->lfHeight);
+
+ wsprintfA(idstr, "Font%dSty", nFontId);
+ style = (BYTE)DBGetContactSettingByte(NULL, pModule, idstr
+ , (lf->lfWeight == FW_NORMAL ? 0 : DBFONTF_BOLD)
+ | (lf->lfItalic ? DBFONTF_ITALIC : 0)
+ | (lf->lfUnderline ? DBFONTF_UNDERLINE : 0)
+ );
+ lf->lfWidth = lf->lfEscapement = lf->lfOrientation = 0;
+ lf->lfWeight = ((style & DBFONTF_BOLD) ? FW_BOLD : FW_NORMAL);
+ lf->lfItalic = (0 != (style & DBFONTF_ITALIC));
+ lf->lfUnderline = (0 != (style & DBFONTF_UNDERLINE));
+ lf->lfStrikeOut = 0;
+
+ wsprintfA(idstr, "Font%dSet", nFontId);
+ lf->lfCharSet = (BYTE)DBGetContactSettingByte(NULL, pModule, idstr, lf->lfCharSet);
+ lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf->lfQuality = DEFAULT_QUALITY;
+ lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+
+ if (bFltContacts)
+ {
+ WORD wSameAs;
+ BYTE bySameAs;
+ BYTE bySameAsFlags;
+
+ wsprintfA(idstr, "Font%dAs", nFontId);
+ wSameAs = (WORD)DBGetContactSettingWord(NULL, sModule, idstr, s_rgwFontSameAsDefault[nFontId]);
+ bySameAs = LOBYTE(wSameAs);
+ bySameAsFlags = HIBYTE(wSameAs);
+
+ if (FLT_SAME_AS_MIRANDA == bySameAs)
+ {
+ LOGFONTA lfMiranda;
+ COLORREF colourMiranda;
+
+ GetFontSetting(FALSE, nFontId, &lfMiranda, &colourMiranda);
+ if (bySameAsFlags & SAMEASF_FACE)
+ {
+ lstrcpyA(lf->lfFaceName, lfMiranda.lfFaceName);
+ lf->lfCharSet = lfMiranda.lfCharSet;
+ }
+ if (bySameAsFlags & SAMEASF_SIZE)
+ lf->lfHeight = lfMiranda.lfHeight;
+ if (bySameAsFlags & SAMEASF_STYLE)
+ {
+ lf->lfWeight = lfMiranda.lfWeight;
+ lf->lfItalic = lfMiranda.lfItalic;
+ lf->lfUnderline = lfMiranda.lfUnderline;
+ }
+ if (bySameAsFlags & SAMEASF_COLOUR)
+ *colour = colourMiranda;
+ }
+ }
+}
+
+static
+LRESULT
+APIENTRY
+OptWndProc
+ ( IN HWND hwndDlg
+ , IN UINT uMsg
+ , IN WPARAM wParam
+ , IN LPARAM lParam
+ )
+{
+ switch ( uMsg )
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ // Properties
+ CheckDlgButton(hwndDlg, IDC_CHK_HIDE_OFFLINE, (fcOpt.bHideOffline ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_HIDE_ALL, (fcOpt.bHideAll ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_HIDE_WHEN_FULSCREEN, (fcOpt.bHideWhenFullscreen ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_STICK, (fcOpt.bMoveTogether ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_WIDTH, (fcOpt.bFixedWidth ? BST_CHECKED : BST_UNCHECKED));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_WIDTH), fcOpt.bFixedWidth);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_WIDTH), fcOpt.bFixedWidth);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_WIDTHSPIN), fcOpt.bFixedWidth);
+
+ SendDlgItemMessage(hwndDlg, IDC_WIDTHSPIN, UDM_SETRANGE, 0, MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg, IDC_WIDTHSPIN, UDM_SETPOS, 0, fcOpt.nThumbWidth);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_TIP, (fcOpt.bShowTip ? BST_CHECKED : BST_UNCHECKED));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_TIP), bEnableTip);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TIMEIN), bEnableTip && fcOpt.bShowTip);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TIMEIN_CMT), bEnableTip && fcOpt.bShowTip);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_TIMEIN), bEnableTip && fcOpt.bShowTip);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TIMEINSPIN), bEnableTip && fcOpt.bShowTip);
+
+ SendDlgItemMessage(hwndDlg, IDC_TIMEINSPIN, UDM_SETRANGE, 0, MAKELONG(5000,0));
+ SendDlgItemMessage(hwndDlg, IDC_TIMEINSPIN, UDM_SETPOS, 0, fcOpt.TimeIn);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_TOTOP, (fcOpt.bToTop ? BST_CHECKED : BST_UNCHECKED));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TOTOP), fcOpt.bToTop);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_TOTOPTIME), fcOpt.bToTop);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TOTOPTIMESPIN), fcOpt.bToTop);
+
+ SendDlgItemMessage(hwndDlg, IDC_TOTOPTIMESPIN, UDM_SETRANGE, 0, MAKELONG(TOTOPTIME_MAX,1));
+ SendDlgItemMessage(hwndDlg, IDC_TOTOPTIMESPIN, UDM_SETPOS, 0, fcOpt.ToTopTime);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_HIDE_WHEN_CLISTSHOW, (fcOpt.bHideWhenCListShow ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_SINGLECLK, (fcOpt.bUseSingleClick ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_SHOWIDLE, (fcOpt.bShowIdle ? BST_CHECKED : BST_UNCHECKED));
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CHK_WIDTH:
+ {
+ if (BN_CLICKED == HIWORD(wParam))
+ {
+ BOOL bChecked = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_WIDTH);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_WIDTH ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_WIDTH ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_WIDTHSPIN), bChecked);
+ }
+ break;
+ }
+ case IDC_TXT_WIDTH:
+ {
+ if (EN_CHANGE != HIWORD(wParam) || (HWND)lParam != GetFocus())
+ return 0;
+ break;
+ }
+ case IDC_CHK_TIP:
+ {
+ if (BN_CLICKED == HIWORD(wParam))
+ {
+ BOOL bChecked = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_TIP);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TIMEIN ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TIMEIN_CMT ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_TIMEIN ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TIMEINSPIN), bChecked);
+ }
+ break;
+ }
+ case IDC_TXT_TIMEIN:
+ {
+ if (EN_CHANGE != HIWORD(wParam) || (HWND)lParam != GetFocus())
+ return 0;
+ break;
+ }
+ case IDC_CHK_TOTOP:
+ {
+ if (BN_CLICKED == HIWORD(wParam))
+ {
+ BOOL bChecked = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_TOTOP);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TOTOP ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_TOTOPTIME ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TOTOPTIMESPIN), bChecked);
+ }
+ break;
+ }
+ case IDC_TXT_TOTOPTIME:
+ {
+ if (EN_CHANGE != HIWORD(wParam) || (HWND)lParam != GetFocus())
+ return 0;
+ break;
+ }
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ LPNMHDR phdr = (LPNMHDR)(lParam);
+
+ if (0 == phdr->idFrom)
+ {
+ switch (phdr->code)
+ {
+ case PSN_APPLY:
+ {
+ BOOL bSuccess = FALSE;
+
+ fcOpt.bHideOffline = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_HIDE_OFFLINE);
+ DBWriteContactSettingByte(NULL, sModule, "HideOffline", (BYTE)fcOpt.bHideOffline);
+
+ fcOpt.bHideAll = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_HIDE_ALL);
+ DBWriteContactSettingByte(NULL, sModule, "HideAll", (BYTE)fcOpt.bHideAll);
+
+ fcOpt.bHideWhenFullscreen = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_HIDE_WHEN_FULSCREEN);
+ DBWriteContactSettingByte(NULL, sModule, "HideWhenFullscreen", (BYTE)fcOpt.bHideWhenFullscreen);
+
+ fcOpt.bMoveTogether = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_STICK);
+ DBWriteContactSettingByte(NULL, sModule, "MoveTogether", (BYTE)fcOpt.bMoveTogether);
+
+ fcOpt.bFixedWidth = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_WIDTH);
+ DBWriteContactSettingByte(NULL, sModule, "FixedWidth", (BYTE)fcOpt.bFixedWidth);
+ fcOpt.nThumbWidth = GetDlgItemInt(hwndDlg, IDC_TXT_WIDTH, &bSuccess, FALSE);
+ DBWriteContactSettingDword(NULL, sModule, "Width", fcOpt.nThumbWidth );
+
+ if (bEnableTip)
+ {
+ fcOpt.bShowTip = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_TIP);
+ DBWriteContactSettingByte(NULL, sModule, "ShowTip", (BYTE)fcOpt.bShowTip);
+ fcOpt.TimeIn = GetDlgItemInt(hwndDlg, IDC_TXT_TIMEIN, &bSuccess, FALSE);
+ DBWriteContactSettingWord(NULL, sModule, "TimeIn", fcOpt.TimeIn );
+ }
+
+ fcOpt.bToTop = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_TOTOP);
+ DBWriteContactSettingByte(NULL, sModule, "ToTop", (BYTE)fcOpt.bToTop);
+ fcOpt.ToTopTime = GetDlgItemInt(hwndDlg, IDC_TXT_TOTOPTIME, &bSuccess, FALSE);
+ DBWriteContactSettingWord(NULL, sModule, "ToTopTime", fcOpt.ToTopTime );
+
+ fcOpt.bHideWhenCListShow = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_HIDE_WHEN_CLISTSHOW);
+ DBWriteContactSettingByte(NULL, sModule, "HideWhenCListShow", (BYTE)fcOpt.bHideWhenCListShow);
+
+ fcOpt.bUseSingleClick = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_SINGLECLK);
+ DBWriteContactSettingByte(NULL, sModule, "UseSingleClick", (BYTE)fcOpt.bUseSingleClick);
+
+ fcOpt.bShowIdle = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_SHOWIDLE);
+ DBWriteContactSettingByte(NULL, sModule, "ShowIdle", (BYTE)fcOpt.bShowIdle);
+
+ ApplyOptionsChanges();
+ OnStatusChanged();
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ }
+ return FALSE;
+}
+
+static
+LRESULT
+APIENTRY
+OptSknWndProc
+ ( IN HWND hwndDlg
+ , IN UINT uMsg
+ , IN WPARAM wParam
+ , IN LPARAM lParam
+ )
+{
+ static HFONT hFontSample;
+
+ switch ( uMsg )
+ {
+ case WM_INITDIALOG:
+ {
+ BYTE btOpacity;
+ char szPercent[20];
+
+ TranslateDialogDefault(hwndDlg);
+
+ // Border
+ CheckDlgButton(hwndDlg, IDC_DRAWBORDER
+ , DBGetContactSettingByte(NULL, sModule, "DrawBorder", FLT_DEFAULT_DRAWBORDER)
+ ? BST_CHECKED : BST_UNCHECKED
+ );
+ SendMessage(hwndDlg, M_REFRESHBORDERPICKERS, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_LTEDGESCOLOR, CPM_SETDEFAULTCOLOUR, 0, FLT_DEFAULT_LTEDGESCOLOR);
+ SendDlgItemMessage(hwndDlg, IDC_LTEDGESCOLOR, CPM_SETCOLOUR, 0
+ , DBGetContactSettingDword(NULL, sModule, "LTEdgesColor", FLT_DEFAULT_LTEDGESCOLOR)
+ );
+ SendDlgItemMessage(hwndDlg, IDC_RBEDGESCOLOR, CPM_SETDEFAULTCOLOUR, 0, FLT_DEFAULT_RBEDGESCOLOR);
+ SendDlgItemMessage(hwndDlg, IDC_RBEDGESCOLOR, CPM_SETCOLOUR, 0
+ , DBGetContactSettingDword(NULL, sModule, "RBEdgesColor", FLT_DEFAULT_RBEDGESCOLOR)
+ );
+
+ // Background
+ CheckDlgButton(hwndDlg, IDC_CHK_WIDTH, (fcOpt.bFixedWidth ? BST_CHECKED : BST_UNCHECKED));
+
+ SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETDEFAULTCOLOUR, 0, FLT_DEFAULT_BKGNDCOLOR);
+ SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETCOLOUR, 0
+ , DBGetContactSettingDword(NULL, sModule, "BkColor", FLT_DEFAULT_BKGNDCOLOR)
+ );
+ CheckDlgButton(hwndDlg, IDC_BITMAP
+ , DBGetContactSettingByte(NULL, sModule, "BkUseBitmap", FLT_DEFAULT_BKGNDUSEBITMAP)
+ ? BST_CHECKED : BST_UNCHECKED
+ );
+ SendMessage(hwndDlg, M_REFRESHBKGBOXES, 0, 0);
+ {
+ DBVARIANT dbv;
+
+ if (!DBGetContactSetting(NULL, sModule, "BkBitmap", &dbv))
+ {
+ SetDlgItemTextA(hwndDlg, IDC_FILENAME, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ {
+ WORD bmpUse = (WORD)DBGetContactSettingWord(NULL, sModule, "BkBitmapOpt", FLT_DEFAULT_BKGNDBITMAPOPT);
+
+ CheckDlgButton(hwndDlg, IDC_STRETCHH, ((bmpUse & CLB_STRETCHH) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_STRETCHV, ((bmpUse & CLB_STRETCHV) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_TILEH, ((bmpUse & CLBF_TILEH) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_TILEV, ((bmpUse & CLBF_TILEV) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_PROPORTIONAL, ((bmpUse & CLBF_PROPORTIONAL) ? BST_CHECKED : BST_UNCHECKED));
+ }
+ {
+ HRESULT (STDAPICALLTYPE *MySHAutoComplete)(HWND,DWORD);
+
+ MySHAutoComplete = (HRESULT (STDAPICALLTYPE*)(HWND,DWORD))GetProcAddress(GetModuleHandle(_T("shlwapi")), "SHAutoComplete");
+ if (MySHAutoComplete)
+ MySHAutoComplete(GetDlgItem(hwndDlg, IDC_FILENAME), 1);
+ }
+
+ // Windows 2K/XP
+ btOpacity = (BYTE)DBGetContactSettingByte(NULL, sModule, "Opacity", 100);
+ SendDlgItemMessage(hwndDlg, IDC_SLIDER_OPACITY, TBM_SETRANGE, TRUE, MAKELONG(0, 100));
+ SendDlgItemMessage(hwndDlg, IDC_SLIDER_OPACITY, TBM_SETPOS, TRUE, btOpacity);
+
+ wsprintfA(szPercent, "%d%%", btOpacity);
+ SetDlgItemTextA(hwndDlg, IDC_OPACITY, szPercent);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SLIDER_OPACITY), (NULL != pSetLayeredWindowAttributes));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OPACITY), (NULL != pSetLayeredWindowAttributes));
+
+ // Fonts
+ hFontSample = NULL;
+ SetDlgItemText(hwndDlg, IDC_SAMPLE, TranslateT("Sample"));
+ FillFontListThread(hwndDlg);
+ {
+ int i;
+ int itemId;
+ LOGFONTA lf;
+ COLORREF colour;
+ WORD sameAs;
+ char str[32];
+
+ for (i = 0; i < FLT_FONTIDS; i++)
+ {
+ // Floating contacts fonts
+ GetFontSetting(TRUE, i, &lf, &colour);
+ wsprintfA(str, "Font%dAs", i);
+ sameAs = (WORD)DBGetContactSettingWord(NULL, sModule, str, s_rgwFontSameAsDefault[i]);
+ s_rgFontSettings[i].sameAs = LOBYTE(sameAs);
+ s_rgFontSettings[i].sameAsFlags = HIBYTE(sameAs);
+ s_rgFontSettings[i].style = (FW_NORMAL == lf.lfWeight? 0 : DBFONTF_BOLD)
+ | (lf.lfItalic ? DBFONTF_ITALIC : 0)
+ | (lf.lfUnderline ? DBFONTF_UNDERLINE : 0);
+ if (lf.lfHeight < 0)
+ {
+ HDC hdc;
+ SIZE size;
+ HFONT hFont = CreateFontIndirectA(&lf);
+
+ hdc = GetDC(hwndDlg);
+ SelectObject(hdc, hFont);
+ GetTextExtentPoint32A(hdc, "x", 1, &size);
+ ReleaseDC(hwndDlg, hdc);
+ DeleteObject(hFont);
+ s_rgFontSettings[i].size = (char)size.cy;
+ }
+ else
+ s_rgFontSettings[i].size = (char)lf.lfHeight;
+ s_rgFontSettings[i].charset = lf.lfCharSet;
+ s_rgFontSettings[i].colour = colour;
+ lstrcpyA(s_rgFontSettings[i].szFace, lf.lfFaceName);
+ itemId = SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_ADDSTRING, 0, (LPARAM)TranslateTS(s_rgszFontIdDescr[i]));
+ SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_SETITEMDATA, itemId, i);
+
+ // Miranda contact list fonts
+ GetFontSetting(FALSE, i, &lf, &colour);
+ s_rgFontSettingsMiranda[i].sameAs = 0;
+ s_rgFontSettingsMiranda[i].sameAsFlags = 0;
+ lstrcpyA(s_rgFontSettingsMiranda[i].szFace, lf.lfFaceName);
+ s_rgFontSettingsMiranda[i].charset = lf.lfCharSet;
+ s_rgFontSettingsMiranda[i].style = (FW_NORMAL == lf.lfWeight? 0 : DBFONTF_BOLD)
+ | (lf.lfItalic ? DBFONTF_ITALIC : 0)
+ | (lf.lfUnderline ? DBFONTF_UNDERLINE : 0);
+ if (lf.lfHeight < 0)
+ {
+ HDC hdc;
+ SIZE size;
+ HFONT hFont = CreateFontIndirectA(&lf);
+
+ hdc = GetDC(hwndDlg);
+ SelectObject(hdc, hFont);
+ GetTextExtentPoint32A(hdc, "x", 1, &size);
+ ReleaseDC(hwndDlg, hdc);
+ DeleteObject(hFont);
+ s_rgFontSettingsMiranda[i].size = (char)size.cy;
+ }
+ else
+ s_rgFontSettingsMiranda[i].size = (char)lf.lfHeight;
+ s_rgFontSettingsMiranda[i].colour = colour;
+ }
+ SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_SETCURSEL, 0, 0);
+ for (i = 0; i < sizeof(s_rgszFontSizes)/sizeof(s_rgszFontSizes[0]); i++)
+ SendDlgItemMessageA(hwndDlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)s_rgszFontSizes[i]);
+ }
+ SendMessage(hwndDlg, M_REBUILDFONTGROUP, 0, 0);
+ SendMessage(hwndDlg, M_SAVEFONT, 0, 0);
+ return TRUE;
+ }
+ case M_REFRESHBKGBOXES:
+ {
+ BOOL bEnable = IsDlgButtonChecked(hwndDlg, IDC_BITMAP);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILENAME), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_STRETCHH), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_STRETCHV), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TILEH), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TILEV), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PROPORTIONAL), bEnable);
+ break;
+ }
+ case M_REFRESHBORDERPICKERS:
+ {
+ BOOL bEnable = IsDlgButtonChecked(hwndDlg, IDC_DRAWBORDER);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LTEDGESCOLOR), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RBEDGESCOLOR), bEnable);
+ break;
+ }
+ // remake all the needed controls when the user changes the font selector at the top
+ case M_REBUILDFONTGROUP:
+ {
+ int i = SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETCURSEL, 0, 0);
+ int j;
+ int itemId;
+ int nSameAs = FLT_SAME_AS_NONE;
+ char szText[256];
+
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_RESETCONTENT, 0, 0);
+ itemId = SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_ADDSTRING, 0, (LPARAM)TranslateT("<none>"));
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETITEMDATA, itemId, FLT_SAME_AS_NONE);
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETCURSEL, itemId, 0);
+ itemId = SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_ADDSTRING, 0, (LPARAM)TranslateT("<Contact List Text>"));
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETITEMDATA, itemId, FLT_SAME_AS_MIRANDA);
+ if (FLT_SAME_AS_MIRANDA == s_rgFontSettings[i].sameAs)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETCURSEL, itemId, 0);
+ nSameAs = FLT_SAME_AS_MIRANDA;
+ }
+ for (j = 0; j < FLT_FONTIDS; j++)
+ {
+ int nDependsOn = j;
+
+ while (nDependsOn != i)
+ {
+ if (FLT_SAME_AS_NONE == nDependsOn || FLT_SAME_AS_MIRANDA == nDependsOn)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETLBTEXT, j, (LPARAM)szText);
+ itemId = SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_ADDSTRING, 0, (LPARAM)szText);
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETITEMDATA, itemId, j);
+ if (j == s_rgFontSettings[i].sameAs)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETCURSEL, itemId, 0);
+ nSameAs = j;
+ }
+ break;
+ }
+ else
+ nDependsOn = s_rgFontSettings[nDependsOn].sameAs;
+ }
+ }
+ if (FLT_SAME_AS_NONE == nSameAs)
+ s_rgFontSettings[i].sameAsFlags = 0;
+
+ SendMessage(hwndDlg, M_LOADFONT, i, 0);
+ SendMessage(hwndDlg, M_SETSAMEASBOXES, i, 0);
+ SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, i, 0);
+ SendMessage(hwndDlg, M_REMAKESAMPLE, 0, 0);
+ break;
+ }
+ //fill the script combo box and set the selection to the value for fontid wParam
+ case M_FILLSCRIPTCOMBO:
+ {
+ int i;
+ HDC hdc = GetDC(hwndDlg);
+ LOGFONT lf = {0};
+
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfPitchAndFamily = 0;
+ GetDlgItemText(hwndDlg, IDC_TYPEFACE, lf.lfFaceName, sizeof(lf.lfFaceName));
+ SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_RESETCONTENT, 0, 0);
+ EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)EnumFontScriptsProc, (LPARAM)GetDlgItem(hwndDlg, IDC_SCRIPT), 0);
+ ReleaseDC(hwndDlg, hdc);
+ for (i = SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETCOUNT, 0, 0) - 1; i >= 0; i--)
+ {
+ if (SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETITEMDATA, i, 0) == s_rgFontSettings[wParam].charset)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_SETCURSEL, i, 0);
+ break;
+ }
+ }
+ if (i < 0)
+ SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_SETCURSEL, 0, 0);
+ break;
+ }
+ // set the check mark in the 'same as' boxes to the right value for fontid wParam
+ case M_SETSAMEASBOXES:
+ {
+ CheckDlgButton(hwndDlg, IDC_SAMETYPE, (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_FACE ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_SAMESIZE, (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_SIZE ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_SAMESTYLE, (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_STYLE ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_SAMECOLOUR, (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_COLOUR ? BST_CHECKED : BST_UNCHECKED));
+ break;
+ }
+ // set the disabled flag on the 'same as' checkboxes to the values for fontid wParam
+ case M_REFRESHSAMEASBOXES:
+ {
+ BOOL bSameAsNone = (FLT_SAME_AS_NONE == s_rgFontSettings[wParam].sameAs);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SAMETYPE), !bSameAsNone);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SAMESIZE), !bSameAsNone);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SAMESTYLE), !bSameAsNone);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SAMECOLOUR), !bSameAsNone);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEFACE), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_FACE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SCRIPT), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_FACE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FONTSIZE), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_SIZE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BOLD), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_STYLE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ITALIC), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_STYLE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_UNDERLINE), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_STYLE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_COLOUR), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_COLOUR));
+ break;
+ }
+ // remake the sample edit box font based on the settings in the controls
+ case M_REMAKESAMPLE:
+ {
+ LOGFONTA lf;
+
+ if (hFontSample)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_SAMPLE, WM_SETFONT, SendDlgItemMessage(hwndDlg, IDC_FONTID, WM_GETFONT, 0, 0), 0);
+ DeleteObject(hFontSample);
+ }
+ lf.lfHeight = GetDlgItemInt(hwndDlg, IDC_FONTSIZE, NULL, FALSE);
+ {
+ HDC hdc = GetDC(NULL);
+ lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ ReleaseDC(NULL,hdc);
+ }
+ lf.lfWidth = 0;
+ lf.lfEscapement = 0;
+ lf.lfOrientation = 0;
+ lf.lfWeight = (IsDlgButtonChecked(hwndDlg, IDC_BOLD) ? FW_BOLD : FW_NORMAL);
+ lf.lfItalic = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_ITALIC);
+ lf.lfUnderline = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE);
+ lf.lfStrikeOut = 0;
+ lf.lfCharSet = (BYTE)SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETCURSEL, 0, 0), 0);
+ lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf.lfQuality = DEFAULT_QUALITY;
+ lf.lfPitchAndFamily = (DEFAULT_PITCH | FF_DONTCARE);
+ GetDlgItemTextA(hwndDlg, IDC_TYPEFACE, lf.lfFaceName, sizeof(lf.lfFaceName));
+ if (NULL != (hFontSample = CreateFontIndirectA(&lf)))
+ SendDlgItemMessage(hwndDlg, IDC_SAMPLE, WM_SETFONT, (WPARAM)hFontSample, TRUE);
+ break;
+ }
+ // copy the 'same as' settings for fontid wParam from their sources
+ case M_RECALCONEFONT:
+ {
+ if (FLT_SAME_AS_NONE != s_rgFontSettings[wParam].sameAs)
+ {
+ SFontSettings* pSameAs = ((FLT_SAME_AS_MIRANDA == s_rgFontSettings[wParam].sameAs)
+ ? &s_rgFontSettingsMiranda[wParam]
+ : &s_rgFontSettings[s_rgFontSettings[wParam].sameAs]
+ );
+
+ if (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_FACE)
+ {
+ lstrcpyA(s_rgFontSettings[wParam].szFace, pSameAs->szFace);
+ s_rgFontSettings[wParam].charset = pSameAs->charset;
+ }
+ if (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_SIZE)
+ s_rgFontSettings[wParam].size = pSameAs->size;
+ if (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_STYLE)
+ s_rgFontSettings[wParam].style = pSameAs->style;
+ if (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_COLOUR)
+ s_rgFontSettings[wParam].colour = pSameAs->colour;
+ }
+ break;
+ }
+ // recalculate the 'same as' settings for all fonts but wParam
+ case M_RECALCOTHERFONTS:
+ {
+ int nFont;
+ int nDepth;
+ int nRecalcedFonts = 1;
+ int nRecalcDepth;
+ int nFontId = (int)wParam;
+ int nSameAs;
+
+ for (nRecalcDepth = 0; nRecalcedFonts < FLT_FONTIDS && nRecalcDepth < FLT_FONTIDS; nRecalcDepth++)
+ {
+ for (nFont = 0; nFont < FLT_FONTIDS; nFont++)
+ {
+ if (nFontId == nFont)
+ continue;
+
+ nSameAs = s_rgFontSettings[nFont].sameAs;
+ for (nDepth = 0; nDepth < nRecalcDepth; nDepth++)
+ {
+ if (FLT_SAME_AS_NONE == nSameAs || FLT_SAME_AS_MIRANDA == nSameAs || nFontId == nSameAs)
+ break;
+
+ nSameAs = s_rgFontSettings[nSameAs].sameAs;
+ }
+ if (nDepth == nRecalcDepth)
+ {
+ if (nFontId == nSameAs)
+ {
+ SendMessage(hwndDlg, M_RECALCONEFONT, nFont, 0);
+ nRecalcedFonts++;
+ }
+ else if (FLT_SAME_AS_NONE == nSameAs || FLT_SAME_AS_MIRANDA == nSameAs)
+ nRecalcedFonts++;
+ }
+ }
+ }
+ break;
+ }
+ //save the font settings from the controls to font wParam
+ case M_SAVEFONT:
+ {
+ s_rgFontSettings[wParam].sameAsFlags = (IsDlgButtonChecked(hwndDlg, IDC_SAMETYPE) ? SAMEASF_FACE : 0)
+ | (IsDlgButtonChecked(hwndDlg, IDC_SAMESIZE) ? SAMEASF_SIZE : 0)
+ | (IsDlgButtonChecked(hwndDlg, IDC_SAMESTYLE) ? SAMEASF_STYLE : 0)
+ | (IsDlgButtonChecked(hwndDlg, IDC_SAMECOLOUR) ? SAMEASF_COLOUR : 0);
+ s_rgFontSettings[wParam].sameAs = (BYTE)SendDlgItemMessage(hwndDlg
+ , IDC_SAMEAS
+ , CB_GETITEMDATA
+ , SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_GETCURSEL, 0, 0)
+ , 0
+ );
+ GetDlgItemTextA(hwndDlg, IDC_TYPEFACE, s_rgFontSettings[wParam].szFace, sizeof(s_rgFontSettings[wParam].szFace));
+ s_rgFontSettings[wParam].charset = (BYTE)SendDlgItemMessage(hwndDlg
+ , IDC_SCRIPT
+ , CB_GETITEMDATA
+ , SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETCURSEL, 0, 0)
+ , 0
+ );
+ s_rgFontSettings[wParam].size = (char)GetDlgItemInt(hwndDlg, IDC_FONTSIZE, NULL, FALSE);
+ s_rgFontSettings[wParam].style = (IsDlgButtonChecked(hwndDlg, IDC_BOLD) ? DBFONTF_BOLD : 0)
+ | (IsDlgButtonChecked(hwndDlg, IDC_ITALIC) ? DBFONTF_ITALIC : 0)
+ | (IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE) ? DBFONTF_UNDERLINE : 0);
+ s_rgFontSettings[wParam].colour = SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_GETCOLOUR, 0, 0);
+ break;
+ }
+ // load font wParam into the controls
+ case M_LOADFONT:
+ {
+ LOGFONTA lf;
+ COLORREF colour;
+
+ SetDlgItemTextA(hwndDlg, IDC_TYPEFACE, s_rgFontSettings[wParam].szFace);
+ SendMessage(hwndDlg, M_FILLSCRIPTCOMBO, wParam, 0);
+ SetDlgItemInt(hwndDlg, IDC_FONTSIZE, s_rgFontSettings[wParam].size, FALSE);
+ CheckDlgButton(hwndDlg, IDC_BOLD, ((s_rgFontSettings[wParam].style & DBFONTF_BOLD) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_ITALIC, ((s_rgFontSettings[wParam].style & DBFONTF_ITALIC) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_UNDERLINE, ((s_rgFontSettings[wParam].style & DBFONTF_UNDERLINE) ? BST_CHECKED : BST_UNCHECKED));
+ GetDefaultFontSetting(TRUE, wParam, &lf, &colour);
+ SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_SETDEFAULTCOLOUR, 0, colour);
+ SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_SETCOLOUR, 0, s_rgFontSettings[wParam].colour);
+ break;
+ }
+ // guess suitable values for the 'same as' checkboxes for fontId wParam
+ case M_GUESSSAMEASBOXES:
+ {
+ s_rgFontSettings[wParam].sameAsFlags = 0;
+ if (FLT_SAME_AS_NONE != s_rgFontSettings[wParam].sameAs)
+ {
+ SFontSettings* pSameAs = ((FLT_SAME_AS_MIRANDA == s_rgFontSettings[wParam].sameAs)
+ ? &s_rgFontSettingsMiranda[wParam]
+ : &s_rgFontSettings[s_rgFontSettings[wParam].sameAs]
+ );
+
+ if (!lstrcmpA(s_rgFontSettings[wParam].szFace, pSameAs->szFace) && s_rgFontSettings[wParam].charset == pSameAs->charset)
+ s_rgFontSettings[wParam].sameAsFlags |= SAMEASF_FACE;
+ if (s_rgFontSettings[wParam].size == pSameAs->size)
+ s_rgFontSettings[wParam].sameAsFlags |= SAMEASF_SIZE;
+ if (s_rgFontSettings[wParam].style == pSameAs->style)
+ s_rgFontSettings[wParam].sameAsFlags |= SAMEASF_STYLE;
+ if (s_rgFontSettings[wParam].colour == pSameAs->colour)
+ s_rgFontSettings[wParam].sameAsFlags |= SAMEASF_COLOUR;
+ SendMessage(hwndDlg,M_SETSAMEASBOXES,wParam,0);
+ }
+ break;
+ }
+ case WM_CTLCOLORSTATIC:
+ {
+ if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SAMPLE))
+ {
+ SetTextColor((HDC)wParam, SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_GETCOLOUR, 0, 0));
+ SetBkColor((HDC)wParam, GetSysColor(COLOR_3DFACE));
+ return (BOOL)GetSysColorBrush(COLOR_3DFACE);
+ }
+ break;
+ }
+ case WM_HSCROLL:
+ {
+ if (wParam != TB_ENDTRACK)
+ {
+ int nPos;
+ char szPercent[20];
+
+ nPos = (BYTE)SendDlgItemMessage(hwndDlg, IDC_SLIDER_OPACITY, TBM_GETPOS, 0, 0);
+ fcOpt.thumbAlpha = (BYTE)(( nPos * 255 ) / 100 );
+ SetThumbsOpacity(fcOpt.thumbAlpha);
+
+ wsprintfA(szPercent, "%d%%", nPos);
+ SetDlgItemTextA(hwndDlg, IDC_OPACITY, szPercent);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ break;
+ }
+ case WM_COMMAND:
+ {
+ int nFontId = SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETITEMDATA
+ , SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETCURSEL, 0, 0)
+ , 0
+ );
+
+ switch (LOWORD(wParam))
+ {
+ case IDC_DRAWBORDER:
+ {
+ SendMessage(hwndDlg, M_REFRESHBORDERPICKERS, 0, 0);
+ break;
+ }
+ case IDC_BROWSE:
+ {
+ char str[MAX_PATH];
+ OPENFILENAMEA ofn = {0};
+ char filter[512];
+
+ GetDlgItemTextA(hwndDlg, IDC_FILENAME, str, sizeof(str));
+ ofn.lStructSize = sizeof(OPENFILENAMEA);
+ ofn.hwndOwner = hwndDlg;
+ ofn.hInstance = NULL;
+ CallService(MS_UTILS_GETBITMAPFILTERSTRINGS, sizeof(filter), (LPARAM)filter);
+ ofn.lpstrFilter = filter;
+ ofn.lpstrFile = str;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+ ofn.nMaxFile = sizeof(str);
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = "bmp";
+ if (!GetOpenFileNameA(&ofn))
+ return FALSE;
+ SetDlgItemTextA(hwndDlg, IDC_FILENAME, str);
+ break;
+ }
+ case IDC_FILENAME:
+ {
+ if (EN_CHANGE != HIWORD(wParam) || (HWND)lParam != GetFocus())
+ return FALSE;
+ break;
+ }
+ case IDC_BITMAP:
+ {
+ SendMessage(hwndDlg, M_REFRESHBKGBOXES, 0, 0);
+ break;
+ }
+ case IDC_FONTID:
+ {
+ if (CBN_SELCHANGE == HIWORD(wParam))
+ SendMessage(hwndDlg, M_REBUILDFONTGROUP, 0, 0);
+ return FALSE;
+ }
+ case IDC_SAMETYPE:
+ case IDC_SAMESIZE:
+ case IDC_SAMESTYLE:
+ case IDC_SAMECOLOUR:
+ {
+ SendMessage(hwndDlg, M_SAVEFONT, nFontId, 0);
+ SendMessage(hwndDlg, M_RECALCONEFONT, nFontId, 0);
+ SendMessage(hwndDlg, M_RECALCOTHERFONTS, nFontId, 0);
+ SendMessage(hwndDlg, M_LOADFONT, nFontId, 0);
+ SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, nFontId, 0);
+ SendMessage(hwndDlg, M_REMAKESAMPLE, 0, 0);
+ break;
+ }
+ case IDC_SAMEAS:
+ {
+ if (CBN_SELCHANGE != HIWORD(wParam))
+ return FALSE;
+ SendMessage(hwndDlg, M_SAVEFONT, nFontId, 0);
+ SendMessage(hwndDlg, M_GUESSSAMEASBOXES, nFontId, 0);
+ SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, nFontId, 0);
+ break;
+ }
+ case IDC_TYPEFACE:
+ case IDC_SCRIPT:
+ case IDC_FONTSIZE:
+ {
+ if (CBN_EDITCHANGE != HIWORD(wParam) && CBN_SELCHANGE != HIWORD(wParam))
+ return FALSE;
+ if (CBN_SELCHANGE == HIWORD(wParam))
+ SendDlgItemMessage(hwndDlg, LOWORD(wParam), CB_SETCURSEL, SendDlgItemMessage(hwndDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0), 0);
+ if (IDC_TYPEFACE == LOWORD(wParam))
+ SendMessage(hwndDlg, M_FILLSCRIPTCOMBO, nFontId, 0);
+ // FALL THRU
+ }
+ case IDC_BOLD:
+ case IDC_ITALIC:
+ case IDC_UNDERLINE:
+ case IDC_COLOUR:
+ {
+ SendMessage(hwndDlg, M_SAVEFONT, nFontId, 0);
+ //SendMessage(hwndDlg, M_GUESSSAMEASBOXES, nFontId, 0);
+ //SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, nFontId, 0);
+ SendMessage(hwndDlg, M_RECALCOTHERFONTS, nFontId, 0);
+ SendMessage(hwndDlg, M_REMAKESAMPLE, 0, 0);
+ break;
+ }
+ case IDC_SAMPLE:
+ return 0;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ LPNMHDR phdr = (LPNMHDR)(lParam);
+
+ if (0 == phdr->idFrom)
+ {
+ switch (phdr->code)
+ {
+ case PSN_APPLY:
+ {
+ int i;
+ char str[20];
+ //BOOL bSuccess = FALSE;
+
+ // Border
+ DBWriteContactSettingByte(NULL, sModule, "DrawBorder", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_DRAWBORDER));
+ {
+ COLORREF col;
+
+ col = SendDlgItemMessage(hwndDlg, IDC_LTEDGESCOLOR, CPM_GETCOLOUR, 0, 0);
+ DBWriteContactSettingDword(NULL, sModule, "LTEdgesColor", col);
+ col = SendDlgItemMessage(hwndDlg, IDC_RBEDGESCOLOR, CPM_GETCOLOUR, 0, 0);
+ DBWriteContactSettingDword(NULL, sModule, "RBEdgesColor", col);
+ }
+
+ // Backgroud
+ {
+ COLORREF col;
+
+ col = SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0);
+ DBWriteContactSettingDword(NULL, sModule, "BkColor", col);
+ }
+ DBWriteContactSettingByte(NULL, sModule, "BkUseBitmap", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_BITMAP));
+ {
+ char str[MAX_PATH];
+
+ GetDlgItemTextA(hwndDlg, IDC_FILENAME, str, sizeof(str));
+ DBWriteContactSettingString(NULL, sModule, "BkBitmap", str);
+ }
+ {
+ WORD flags = 0;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_STRETCHH))
+ flags |= CLB_STRETCHH;
+ if (IsDlgButtonChecked(hwndDlg, IDC_STRETCHV))
+ flags |= CLB_STRETCHV;
+ if (IsDlgButtonChecked(hwndDlg, IDC_TILEH))
+ flags |= CLBF_TILEH;
+ if (IsDlgButtonChecked(hwndDlg, IDC_TILEV))
+ flags |= CLBF_TILEV;
+ if (IsDlgButtonChecked(hwndDlg, IDC_PROPORTIONAL))
+ flags |= CLBF_PROPORTIONAL;
+ DBWriteContactSettingWord(NULL, sModule, "BkBitmapOpt", flags);
+ }
+
+ DBWriteContactSettingByte(NULL, sModule, "Opacity"
+ , (BYTE)SendDlgItemMessage(hwndDlg, IDC_SLIDER_OPACITY, TBM_GETPOS, 0, 0)
+ );
+
+ for (i = 0; i < FLT_FONTIDS; i++)
+ {
+ wsprintfA(str, "Font%dName", i);
+ DBWriteContactSettingString(NULL, sModule, str, s_rgFontSettings[i].szFace);
+ wsprintfA(str, "Font%dSet", i);
+ DBWriteContactSettingByte(NULL, sModule, str, s_rgFontSettings[i].charset);
+ wsprintfA(str, "Font%dSize", i);
+ DBWriteContactSettingByte(NULL, sModule, str, s_rgFontSettings[i].size);
+ wsprintfA(str, "Font%dSty", i);
+ DBWriteContactSettingByte(NULL, sModule, str, s_rgFontSettings[i].style);
+ wsprintfA(str, "Font%dCol", i);
+ DBWriteContactSettingDword(NULL, sModule, str, s_rgFontSettings[i].colour);
+ wsprintfA(str, "Font%dAs", i);
+ DBWriteContactSettingWord(NULL, sModule, str, MAKEWORD(s_rgFontSettings[i].sameAs, s_rgFontSettings[i].sameAsFlags));
+ }
+
+ ApplyOptionsChanges();
+ OnStatusChanged();
+ return TRUE;
+ }
+ case PSN_RESET:
+ //case PSN_KILLACTIVE:
+ {
+ fcOpt.thumbAlpha = (BYTE)((double)DBGetContactSettingByte(NULL, sModule, "Opacity", 100) * 2.55);
+ SetThumbsOpacity(fcOpt.thumbAlpha);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case WM_DESTROY:
+ {
+ if (hFontSample)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_SAMPLE, WM_SETFONT, SendDlgItemMessage(hwndDlg, IDC_FONTID, WM_GETFONT, 0, 0), 0);
+ DeleteObject(hFontSample);
+ }
+ break;
+ }
+
+ }
+ return FALSE;
+}
+
diff --git a/plugins/FloatingContacts/src/resource.h b/plugins/FloatingContacts/src/resource.h
new file mode 100644
index 0000000000..fec93538d8
--- /dev/null
+++ b/plugins/FloatingContacts/src/resource.h
@@ -0,0 +1,75 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Script.rc
+//
+#define IDD_OPT_FLTCONT 101
+#define IDI_ICON1 103
+#define IDI_HIDE 103
+#define IDI_SHOW 105
+#define IDD_OPT_FNT 106
+#define IDD_OPT_SKIN 106
+#define IDC_SLIDER_OPACITY 1001
+#define IDC_OPACITY 1002
+#define IDC_CHK_HIDE_OFFLINE 1003
+#define IDC_CHK_STICK 1004
+#define IDC_CHK_WIDTH 1005
+#define IDC_LBL_WIDTH 1006
+#define IDC_TXT_WIDTH 1007
+#define IDC_WIDTHSPIN 1008
+#define IDC_TXT_TIMEIN 1009
+#define IDC_TIMEINSPIN 1010
+#define IDC_TXT_TOTOPTIME 1011
+#define IDC_CHK_HIDE_ALL 1012
+#define IDC_CHK_DEF_BACKGROUND 1013
+#define IDC_TOTOPTIMESPIN 1013
+#define IDC_CHK_HIDE_WHEN_FULSCREEN 1014
+#define IDC_CHK_TIP 1015
+#define IDC_LBL_TIMEIN 1016
+#define IDC_CHK_TOTOP 1017
+#define IDC_LBL_TOTOP 1018
+#define IDC_CHK_HIDE_WHEN_CLISTSHOW 1019
+#define IDC_CHECK1 1020
+#define IDC_CHK_SINGLECLK 1020
+#define IDC_CHECK2 1021
+#define IDC_CHK_SHOWIDLE 1021
+#define IDC_FONTID 1100
+#define IDC_SAMEAS 1101
+#define IDC_LBL_TIMEIN_CMT 1101
+#define IDC_SAMETYPE 1102
+#define IDC_SAMESIZE 1103
+#define IDC_SAMESTYLE 1104
+#define IDC_SAMECOLOUR 1105
+#define IDC_TYPEFACE 1106
+#define IDC_SCRIPT 1107
+#define IDC_FONTSIZE 1108
+#define IDC_BOLD 1109
+#define IDC_ITALIC 1110
+#define IDC_UNDERLINE 1111
+#define IDC_COLOUR 1112
+#define IDC_SAMPLE 1113
+#define IDC_STSAMETEXT 1114
+#define IDC_STASTEXT 1115
+#define IDC_STHORZBAR 1116
+#define IDC_BKGCOLOUR 1200
+#define IDC_BITMAP 1201
+#define IDC_FILENAME 1202
+#define IDC_BROWSE 1203
+#define IDC_STRETCHH 1204
+#define IDC_STRETCHV 1205
+#define IDC_TILEH 1206
+#define IDC_TILEV 1207
+#define IDC_PROPORTIONAL 1208
+#define IDC_DRAWBORDER 1209
+#define IDC_LTEDGESCOLOR 1210
+#define IDC_RBEDGESCOLOR 1211
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 107
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1022
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/FloatingContacts/src/stdhdr.h b/plugins/FloatingContacts/src/stdhdr.h
new file mode 100644
index 0000000000..03b671515f
--- /dev/null
+++ b/plugins/FloatingContacts/src/stdhdr.h
@@ -0,0 +1,64 @@
+
+#ifndef __STDHDR_H__
+#define __STDHDR_H__
+
+// disable security warnings about "*_s" functions
+#define _CRT_SECURE_NO_DEPRECATE
+
+// disable warnings about underscore in stdc functions
+#pragma warning(disable: 4996)
+
+// Unreferenced formal parameter
+#pragma warning(disable: 4100)
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+#define STRICT
+
+#include <windows.h>
+#include <stdio.h>
+#include <assert.h>
+
+#pragma warning ( disable : 4201 ) //nonstandard extension used : nameless struct/union
+#include <commctrl.h>
+
+#define MIRANDA_VER 0x0A00
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <m_skin.h>
+#include <m_utils.h>
+#include <m_langpack.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_database.h>
+#include <m_message.h>
+//#include "../../include/msgs.h"
+#include <m_file.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_options.h>
+#include <m_clc.h>
+//#include "../../include/clc.h"
+#include <m_clistint.h>
+#include <m_hotkeys.h>
+
+#include "bitmap_funcs.h"
+
+#include "fltcont.h"
+#include "thumbs.h"
+#include "filedrop.h"
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // #ifndef __STDHDR_H__
+
+/////////////////////////////////////////////////////////////////////////////
+// End Of File stdhdr.h
diff --git a/plugins/FloatingContacts/src/thumbs.cpp b/plugins/FloatingContacts/src/thumbs.cpp
new file mode 100644
index 0000000000..0195ff0717
--- /dev/null
+++ b/plugins/FloatingContacts/src/thumbs.cpp
@@ -0,0 +1,1013 @@
+#include "stdhdr.h"
+#include "Wingdi.h"
+
+ThumbList thumbList;
+
+/////////////////////////////////////////////////////////////////////////////
+// ThumbInfo
+static POINT ptOld;
+static BOOL bMouseDown = FALSE;
+static BOOL bMouseIn = FALSE;
+static BOOL bMouseMoved = FALSE;
+static short nLeft = 0;
+static short nTop = 0;
+static int nOffs = 5;
+static ThumbInfo *pThumbMouseIn = NULL;
+
+static void SnapToScreen( RECT rcThumb, int nX, int nY, int *pX, int *pY )
+{
+ int nWidth;
+ int nHeight;
+
+ assert( NULL != pX );
+ assert( NULL != pY );
+
+ nWidth = rcThumb.right - rcThumb.left;
+ nHeight = rcThumb.bottom - rcThumb.top;
+
+ *pX = nX < ( nOffs + rcScreen.left ) ? rcScreen.left : nX;
+ *pY = nY < ( nOffs + rcScreen.top ) ? rcScreen.top : nY;
+ *pX = *pX > ( rcScreen.right - nWidth - nOffs ) ? ( rcScreen.right - nWidth ) : *pX;
+ *pY = *pY > ( rcScreen.bottom - nHeight - nOffs ) ? ( rcScreen.bottom - nHeight ) : *pY;
+}
+
+ThumbInfo::ThumbInfo()
+{
+ dropTarget = new CDropTarget;
+ dropTarget->AddRef();
+ btAlpha = 255;
+}
+
+ThumbInfo::~ThumbInfo()
+{
+ if (pThumbMouseIn == this){
+ pThumbMouseIn = NULL;
+ KillTimer(hwnd, TIMERID_LEAVE_T);
+ }
+ dropTarget->Release();
+}
+
+void ThumbInfo::GetThumbRect(RECT *rc)
+{
+ rc->left = ptPos.x;
+ rc->top = ptPos.y;
+ rc->right = ptPos.x + szSize.cx;
+ rc->bottom = ptPos.y + szSize.cy;
+}
+
+void ThumbInfo::PositionThumb(short nX, short nY)
+{
+ POINT pos = { nX, nY };
+ HDWP hdwp;
+
+ hdwp = BeginDeferWindowPos(1);
+
+ ThumbInfo *pThumb = this;
+ while (pThumb)
+ {
+ pThumb->PositionThumbWorker( (short)pos.x, (short)pos.y, &pos );
+
+ DeferWindowPos( hdwp,
+ pThumb->hwnd,
+ HWND_TOPMOST,
+ pos.x,
+ pos.y,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
+
+ pThumb->ptPos = pos;
+ pos.x += pThumb->szSize.cx;
+
+ pThumb = fcOpt.bMoveTogether ? thumbList.FindThumb( pThumb->dockOpt.hwndRight ) : NULL;
+ }
+
+ EndDeferWindowPos(hdwp);
+}
+
+void ThumbInfo::PositionThumbWorker(short nX, short nY, POINT *newPos)
+{
+ RECT rc;
+ RECT rcThumb;
+ int nNewX;
+ int nNewY;
+ int nWidth;
+ int nHeight;
+ POINT pt;
+ RECT rcLeft;
+ RECT rcTop;
+ RECT rcRight;
+ RECT rcBottom;
+ BOOL bDocked;
+ BOOL bDockedLeft;
+ BOOL bDockedRight;
+ BOOL bLeading;
+
+ // Get thumb dimnsions
+ GetThumbRect( &rcThumb );
+ nWidth = rcThumb.right - rcThumb.left;
+ nHeight = rcThumb.bottom - rcThumb.top;
+
+ // Docking and screen boundaries check
+ SnapToScreen( rcThumb, nX, nY, &nNewX, &nNewY );
+
+ bLeading = dockOpt.hwndRight != NULL;
+
+ if ( fcOpt.bMoveTogether )
+ {
+ UndockThumbs( this, thumbList.FindThumb( dockOpt.hwndLeft ));
+ }
+
+
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ {
+ ThumbInfo *pCurThumb = thumbList[i];
+
+ if ( pCurThumb != this )
+ {
+ GetThumbRect( &rcThumb );
+ OffsetRect( &rcThumb, nX - rcThumb.left, nY - rcThumb.top );
+
+ pCurThumb->GetThumbRect( &rc );
+
+ // These are rects we will dock into
+
+ rcLeft.left = rc.left - nOffs;
+ rcLeft.top = rc.top - nOffs;
+ rcLeft.right = rc.left + nOffs;
+ rcLeft.bottom = rc.bottom + nOffs;
+
+ rcTop.left = rc.left - nOffs;
+ rcTop.top = rc.top - nOffs;
+ rcTop.right = rc.right + nOffs;
+ rcTop.bottom = rc.top + nOffs;
+
+ rcRight.left = rc.right - nOffs;
+ rcRight.top = rc.top - nOffs;
+ rcRight.right = rc.right + nOffs;
+ rcRight.bottom = rc.bottom + nOffs;
+
+ rcBottom.left = rc.left - nOffs;
+ rcBottom.top = rc.bottom - nOffs;
+ rcBottom.right = rc.right + nOffs;
+ rcBottom.bottom = rc.bottom + nOffs;
+
+
+ bDockedLeft = FALSE;
+ bDockedRight = FALSE;
+
+ // Upper-left
+ pt.x = rcThumb.left;
+ pt.y = rcThumb.top;
+ bDocked = FALSE;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right;
+ bDocked = TRUE;
+ }
+
+ if ( PtInRect( &rcBottom, pt ))
+ {
+ nNewY = rc.bottom;
+
+ if ( PtInRect( &rcLeft, pt ))
+ {
+ nNewX = rc.left;
+ }
+ }
+
+ if ( PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top;
+ bDockedLeft = bDocked;
+ }
+
+ // Upper-right
+ pt.x = rcThumb.right;
+ pt.y = rcThumb.top;
+ bDocked = FALSE;
+
+ if ( !bLeading && PtInRect( &rcLeft, pt ))
+ {
+ if ( !bDockedLeft )
+ {
+ nNewX = rc.left - nWidth;
+ bDocked = TRUE;
+ }
+ else if ( rc.right == rcThumb.left )
+ {
+ bDocked = TRUE;
+ }
+ }
+
+
+ if ( PtInRect( &rcBottom, pt ))
+ {
+ nNewY = rc.bottom;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right - nWidth;
+ }
+ }
+
+ if ( !bLeading && PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top;
+ bDockedRight = bDocked;
+ }
+
+ if ( fcOpt.bMoveTogether )
+ {
+ if ( bDockedRight )
+ {
+ DockThumbs( this, pCurThumb, TRUE );
+ }
+
+ if ( bDockedLeft )
+ {
+ DockThumbs( pCurThumb, this, FALSE );
+ }
+ }
+
+ // Lower-left
+ pt.x = rcThumb.left;
+ pt.y = rcThumb.bottom;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right;
+ }
+
+ if ( PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top - nHeight;
+
+ if ( PtInRect( &rcLeft, pt ))
+ {
+ nNewX = rc.left;
+ }
+ }
+
+
+ // Lower-right
+ pt.x = rcThumb.right;
+ pt.y = rcThumb.bottom;
+
+ if ( !bLeading && PtInRect( &rcLeft, pt ))
+ {
+ nNewX = rc.left - nWidth;
+ }
+
+ if ( !bLeading && PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top - nHeight;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right - nWidth;
+ }
+ }
+ }
+ }
+
+ // Adjust coords once again
+ SnapToScreen( rcThumb, nNewX, nNewY, &nNewX, &nNewY );
+
+ newPos->x = nNewX;
+ newPos->y = nNewY;
+}
+
+void ThumbInfo::ResizeThumb()
+{
+ HDC hdc = NULL;
+ HFONT hOldFont = NULL;
+ POINT ptText;
+ SIZEL sizeIcon;
+ SIZEL sizeText;
+ RECT rcThumb;
+ int index = FLT_FONTID_NOTONLIST;
+
+ ThumbInfo *pNextThumb = NULL;
+
+ himl = ( HIMAGELIST )CallService( MS_CLIST_GETICONSIMAGELIST, 0, 0 );
+
+ if ( himl == NULL ) return;
+
+ ImageList_GetIconSize_my(himl, sizeIcon);
+
+ hdc = GetWindowDC(hwnd);
+
+ if (!DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ {
+ int nStatus;
+ int nContactStatus;
+ int nApparentMode;
+ char* szProto;
+
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ if ( NULL != szProto )
+ {
+ nStatus = CallProtoService(szProto, PS_GETSTATUS, 0, 0);
+ nContactStatus = DBGetContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ nApparentMode = DBGetContactSettingWord(hContact, szProto, "ApparentMode", 0);
+
+ if ( (nStatus == ID_STATUS_INVISIBLE && nApparentMode == ID_STATUS_ONLINE)
+ || (nStatus != ID_STATUS_INVISIBLE && nApparentMode == ID_STATUS_OFFLINE)
+ )
+ {
+ if (ID_STATUS_OFFLINE == nContactStatus)
+ {
+ index = FLT_FONTID_OFFINVIS;
+ }
+ else
+ {
+ index = FLT_FONTID_INVIS;
+ }
+ }
+ else if (ID_STATUS_OFFLINE == nContactStatus)
+ {
+ index = FLT_FONTID_OFFLINE;
+ }
+ else
+ {
+ index = FLT_FONTID_CONTACTS;
+ }
+ }
+ }
+ else
+ {
+ index = FLT_FONTID_NOTONLIST;
+ }
+
+ hOldFont = (HFONT)SelectObject( hdc, hFont[ index ] );
+
+ // Get text and icon sizes
+ GetTextExtentPoint32( hdc, ptszName, _tcslen( ptszName ), &sizeText );
+
+
+ SelectObject( hdc, hOldFont );
+
+ // Transform text size
+ ptText.x = sizeText.cx;
+ ptText.y = sizeText.cy;
+ LPtoDP( hdc, &ptText, 1 );
+
+
+ szSize.cx = fcOpt.bFixedWidth ? fcOpt.nThumbWidth : sizeIcon.cx + ptText.x + 10;
+ szSize.cy = ( ( sizeIcon.cy > ptText.y ) ? sizeIcon.cy : ptText.y ) + 4;
+
+ SetWindowPos( hwnd,
+ HWND_TOPMOST,
+ 0,
+ 0,
+ szSize.cx,
+ szSize.cy,
+ SWP_NOMOVE | /*SWP_NOZORDER |*/ SWP_NOACTIVATE );
+
+ RefreshContactIcon(0xFFFFFFFF);
+
+ ReleaseDC( hwnd, hdc );
+
+ // Move the docked widnow if needed
+ if (pNextThumb = thumbList.FindThumb(dockOpt.hwndRight))
+ {
+ GetThumbRect( &rcThumb );
+ pNextThumb->PositionThumb( (short)rcThumb.right, (short)rcThumb.top );
+ }
+}
+
+void ThumbInfo::RefreshContactIcon(int iIcon)
+{
+ if ( iIcon == 0xFFFFFFFF || ImageList_GetImageCount(himl)<=iIcon )
+ {
+ this->iIcon = CallService( MS_CLIST_GETCONTACTICON, (WPARAM)hContact, 0 );
+ }
+ else
+ {
+ this->iIcon = iIcon;
+ }
+
+ UpdateContent();
+}
+
+void ThumbInfo::RefreshContactStatus(int idStatus)
+{
+ if ( IsStatusVisible( idStatus ))
+ {
+ RegisterFileDropping( hwnd, dropTarget );
+ }
+ else
+ {
+ UnregisterFileDropping( hwnd );
+ }
+
+ ShowWindow( hwnd, fcOpt.bHideAll || HideOnFullScreen() || ( fcOpt.bHideOffline && ( !IsStatusVisible( idStatus )) ) || (fcOpt.bHideWhenCListShow && bIsCListShow) ? SW_HIDE : SW_SHOWNA );
+}
+
+void ThumbInfo::DeleteContactPos()
+{
+ DBDeleteContactSetting( hContact, sModule, "ThumbsPos" );
+}
+
+void ThumbInfo::OnLButtonDown(short nX, short nY)
+{
+ RECT rc;
+
+ if (bEnableTip && fcOpt.bShowTip) KillTip();
+
+// ptOld.x = nX;
+// ptOld.y = nY;
+
+// ClientToScreen( hwnd, &ptOld );
+
+ GetCursorPos(&ptOld);
+ GetThumbRect(&rc);
+
+ nLeft = (short)rc.left;
+ nTop = (short)rc.top;
+
+ //bMouseIn = FALSE;
+ bMouseDown = TRUE;
+ bMouseMoved = FALSE;
+
+// SetCapture(hwnd);
+}
+
+void ThumbInfo::OnLButtonUp()
+{
+ RECT rcMiranda;
+ RECT rcThumb;
+ RECT rcOverlap;
+
+ if (!bMouseMoved && fcOpt.bUseSingleClick && bMouseIn){
+ PopUpMessageDialog();
+ }
+
+ //ThumbDeselect( TRUE );
+
+ if ( bMouseDown )
+ {
+ bMouseDown = FALSE;
+ SetCursor( LoadCursor( NULL, IDC_ARROW ));
+
+ // Check whether we shoud remove the window
+ GetWindowRect( hwndMiranda, &rcMiranda );
+ GetThumbRect( &rcThumb );
+
+ if ( IntersectRect( &rcOverlap, &rcMiranda, &rcThumb ))
+ {
+ if ( IsWindowVisible( hwndMiranda ))
+ {
+ DeleteContactPos( );
+ thumbList.RemoveThumb( this );
+ }
+ }
+ }
+
+ SaveContactsPos();
+}
+
+void ThumbInfo::OnMouseMove(short nX, short nY, WPARAM wParam)
+{
+// if (bMouseDown && !wParam&MK_LBUTTON) OnLButtonUp();
+
+ int dX;
+ int dY;
+ POINT ptNew;
+
+ // Position thumb
+
+ if ( bMouseDown )
+ {
+
+ ptNew.x = nX;
+ ptNew.y = nY;
+
+ ClientToScreen( hwnd, &ptNew );
+
+ dX = ptNew.x - ptOld.x;
+ dY = ptNew.y - ptOld.y;
+
+ if (dX || dY){
+ bMouseMoved = TRUE;
+
+ nLeft += (short)dX;
+ nTop += (short)dY;
+
+ PositionThumb( nLeft, nTop );
+ }
+
+ ptOld = ptNew;
+ }
+ else
+ {
+ SetCursor( LoadCursor( NULL, IDC_ARROW ));
+ }
+
+ // Update selection status
+ if ( !pThumbMouseIn )//
+ {
+ SetTimer( hwnd, TIMERID_LEAVE_T, 10, NULL );
+ pThumbMouseIn = this;
+
+ ThumbSelect( TRUE );
+ }
+ if (bEnableTip && fcOpt.bShowTip && !bMouseDown){
+ WORD tmpTimeIn;
+ POINT pt;
+ RECT rc;
+
+ GetCursorPos(&pt);
+ GetThumbRect(&rc);
+ if (!PtInRect(&rc,pt)) {
+ KillTip();
+ return;
+ }
+ if (fTipTimerActive && abs(pt.x-ptTipSt.x)<5 && abs(pt.y-ptTipSt.x)<5){
+ return;
+ }
+ ptTipSt = pt;
+
+ if (fTipTimerActive) {
+ KillTimer(hwnd, TIMERID_HOVER_T);
+ }
+ if (fTipActive) {
+ return;
+ }
+
+ tmpTimeIn = (fcOpt.TimeIn>0)?fcOpt.TimeIn:CallService(MS_CLC_GETINFOTIPHOVERTIME, 0, 0);
+ SetTimer(hwnd, TIMERID_HOVER_T, tmpTimeIn, 0);
+ fTipTimerActive = TRUE;
+ }
+}
+
+void ThumbInfo::ThumbSelect(BOOL bMouse)
+{
+ if ( bMouse )
+ {
+ bMouseIn = TRUE;
+ SetCapture( hwnd );
+ }
+
+ SetThumbOpacity( 255 );
+}
+
+void ThumbInfo::ThumbDeselect(BOOL bMouse)
+{
+ if ( bMouse )
+ {
+ bMouseIn = FALSE;
+ ReleaseCapture();
+ }
+
+ SetThumbOpacity( fcOpt.thumbAlpha );
+}
+
+void ThumbInfo::SetThumbOpacity(BYTE bAlpha)
+{
+ if ( pUpdateLayeredWindow && (bAlpha != btAlpha))
+ {
+ btAlpha = bAlpha;
+ UpdateContent();
+ }
+}
+
+void ThumbInfo::KillTip()
+{
+ if (fTipTimerActive)
+ {
+ KillTimer(hwnd, TIMERID_HOVER_T);
+ fTipTimerActive = FALSE;
+ }
+
+ if (fTipActive)
+ {
+ CallService("mToolTip/HideTip", 0, 0);
+ fTipActive = FALSE;
+ }
+}
+
+void ThumbInfo::UpdateContent()
+{
+ bmpContent.allocate(szSize.cx, szSize.cy);
+
+ HFONT hOldFont;
+ SIZE size;
+ RECT rc;
+ RECT rcText;
+ DWORD oldColor;
+ int oldBkMode, index = 0;// nStatus;
+ UINT fStyle = ILD_NORMAL;
+
+ HDC hdcDraw = bmpContent.getDC();
+ SetRect(&rc, 0, 0, szSize.cx, szSize.cy);
+
+ if ( NULL != hBmpBackground )
+ {
+ RECT rcBkgnd;
+ BITMAP bmp;
+ HDC hdcBmp;
+ HBITMAP hbmTmp;
+ int x,y;
+ int maxx,maxy;
+ int destw,desth;
+ int width;
+ int height;
+
+ SetRect(&rcBkgnd, 0, 0, szSize.cx, szSize.cy);
+ if (NULL != hLTEdgesPen)
+ InflateRect(&rcBkgnd, -1, -1);
+ width = rcBkgnd.right - rcBkgnd.left;
+ height = rcBkgnd.bottom - rcBkgnd.top;
+
+ GetObject(hBmpBackground, sizeof(bmp), &bmp);
+ hdcBmp = CreateCompatibleDC( hdcDraw );
+ hbmTmp = (HBITMAP)SelectObject( hdcBmp, hBmpBackground );
+
+ maxx = (0 != (nBackgroundBmpUse & CLBF_TILEH) ? rcBkgnd.right : rcBkgnd.left + 1);
+ maxy = (0 != (nBackgroundBmpUse & CLBF_TILEV) ? rcBkgnd.bottom : rcBkgnd.top + 1);
+ switch (nBackgroundBmpUse & CLBM_TYPE)
+ {
+ case CLB_STRETCH:
+ if (0 != (nBackgroundBmpUse & CLBF_PROPORTIONAL))
+ {
+ if (width * bmp.bmHeight < height * bmp.bmWidth)
+ {
+ desth = height;
+ destw = desth * bmp.bmWidth / bmp.bmHeight;
+ }
+ else
+ {
+ destw = width;
+ desth = destw * bmp.bmHeight / bmp.bmWidth;
+ }
+ }
+ else
+ {
+ destw = width;
+ desth = height;
+ }
+ break;
+
+ case CLB_STRETCHH:
+ destw = width;
+ if (0 != (nBackgroundBmpUse & CLBF_PROPORTIONAL))
+ desth = destw * bmp.bmHeight / bmp.bmWidth;
+ else
+ desth = bmp.bmHeight;
+ break;
+
+ case CLB_STRETCHV:
+ desth = height;
+ if (0 != (nBackgroundBmpUse & CLBF_PROPORTIONAL))
+ destw = desth * bmp.bmWidth / bmp.bmHeight;
+ else
+ destw = bmp.bmWidth;
+ break;
+
+ default: //clb_topleft
+ destw = bmp.bmWidth;
+ desth = bmp.bmHeight;
+ break;
+ }
+ SetStretchBltMode(hdcBmp, STRETCH_HALFTONE);
+
+ for (x = rcBkgnd.left; x < maxx; x += destw)
+ {
+ for (y = rcBkgnd.top; y < maxy; y += desth)
+ {
+ StretchBlt( hdcDraw, x, y, destw, desth, hdcBmp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY );
+ }
+ }
+
+ SelectObject( hdcBmp, hbmTmp );
+ DeleteDC( hdcBmp );
+ }
+ else
+ {
+ FillRect( hdcDraw, &rc, hBkBrush );
+ }
+
+ if (NULL != hLTEdgesPen)
+ {
+ HPEN hOldPen = (HPEN)SelectObject( hdcDraw, hLTEdgesPen );
+
+ MoveToEx(hdcDraw, 0, 0, NULL);
+ LineTo(hdcDraw, szSize.cx, 0);
+ MoveToEx(hdcDraw, 0, 0, NULL);
+ LineTo(hdcDraw, 0, szSize.cy);
+
+ SelectObject(hdcDraw, hRBEdgesPen);
+
+ MoveToEx(hdcDraw, 0, szSize.cy - 1, NULL);
+ LineTo(hdcDraw, szSize.cx - 1, szSize.cy - 1);
+ MoveToEx(hdcDraw, szSize.cx - 1, szSize.cy - 1, NULL);
+ LineTo(hdcDraw, szSize.cx - 1, 0);
+
+ SelectObject(hdcDraw, hOldPen);
+ //InflateRect(&rc, -1, -1);
+ }
+
+ bmpContent.setAlpha(btAlpha);
+
+ ImageList_GetIconSize_my( himl, size );
+
+ oldBkMode = SetBkMode( hdcDraw, TRANSPARENT );
+
+ if (!DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ {
+ int nStatus;
+ int nContactStatus;
+ int nApparentMode;
+ char* szProto;
+
+
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ if ( NULL != szProto )
+ {
+ nStatus = CallProtoService(szProto, PS_GETSTATUS, 0, 0);
+ nContactStatus = DBGetContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ nApparentMode = DBGetContactSettingWord(hContact, szProto, "ApparentMode", 0);
+
+ if ( (nStatus == ID_STATUS_INVISIBLE && nApparentMode == ID_STATUS_ONLINE) ||
+ (nStatus != ID_STATUS_INVISIBLE && nApparentMode == ID_STATUS_OFFLINE))
+ {
+ if (ID_STATUS_OFFLINE == nContactStatus)
+ {
+ index = FLT_FONTID_OFFINVIS;
+ }
+ else
+ {
+ index = FLT_FONTID_INVIS;
+ if (fcOpt.bShowIdle && DBGetContactSettingDword(hContact, szProto, "IdleTS", 0)) {
+ fStyle|=ILD_BLEND50;
+ }
+ }
+ }
+ else if (ID_STATUS_OFFLINE == nContactStatus)
+ {
+ index = FLT_FONTID_OFFLINE;
+ }
+ else
+ {
+ index = FLT_FONTID_CONTACTS;
+ if (fcOpt.bShowIdle && DBGetContactSettingDword(hContact, szProto, "IdleTS", 0)) {
+ fStyle|=ILD_BLEND50;
+ }
+ }
+
+ }
+ }
+ else
+ {
+ index = FLT_FONTID_NOTONLIST;
+ fStyle|=ILD_BLEND50;
+ }
+
+ oldColor = SetTextColor( hdcDraw, tColor[ index ] );
+
+/* ImageList_DrawEx( himl,
+ iIcon,
+ hdcDraw,
+ 2,
+ ( szSize.cy - size.cx ) / 2,
+ 0,
+ 0,
+ CLR_NONE,
+ CLR_NONE,
+ fStyle);
+*/
+ {
+ HICON icon = ImageList_GetIcon(himl, iIcon, ILD_NORMAL);
+ MyBitmap bmptmp(size.cx, size.cy);
+ bmptmp.DrawIcon(icon,0,0);//bmpContent
+ BLENDFUNCTION blend;
+ blend.BlendOp = AC_SRC_OVER;
+ blend.BlendFlags = 0;
+ blend.SourceConstantAlpha = (fStyle&ILD_BLEND50)?128:255;
+ blend.AlphaFormat = AC_SRC_ALPHA;
+ AlphaBlend(hdcDraw, 2,( szSize.cy - size.cx ) / 2, bmptmp.getWidth(), bmptmp.getHeight(), bmptmp.getDC(), 0, 0, bmptmp.getWidth(), bmptmp.getHeight(), blend);
+ DestroyIcon(icon);
+ }
+ SetRect(&rcText, 0, 0, szSize.cx, szSize.cy);
+ rcText.left += size.cx + 4;
+
+ hOldFont = (HFONT)SelectObject( hdcDraw, hFont[ index ] );
+
+ SIZE szText;
+ GetTextExtentPoint32(hdcDraw, ptszName, _tcslen(ptszName), &szText);
+ SetTextColor(hdcDraw, bkColor);
+
+ // simple border
+ bmpContent.DrawText(ptszName, rcText.left-1, (rcText.top + rcText.bottom - szText.cy)/2);
+ bmpContent.DrawText(ptszName, rcText.left+1, (rcText.top + rcText.bottom - szText.cy)/2);
+ bmpContent.DrawText(ptszName, rcText.left, (rcText.top + rcText.bottom - szText.cy)/2-1);
+ bmpContent.DrawText(ptszName, rcText.left, (rcText.top + rcText.bottom - szText.cy)/2+1);
+
+ // blurred border
+ // bmpContent.DrawText(ptszName, rcText.left, (rcText.top + rcText.bottom - szText.cy)/2, 3);
+
+ // text itself
+ SetTextColor(hdcDraw, tColor[index]);
+ bmpContent.DrawText(ptszName, rcText.left, (rcText.top + rcText.bottom - szText.cy)/2);
+
+ SelectObject( hdcDraw, hOldFont );
+
+ SetTextColor( hdcDraw, oldColor );
+ SetBkMode( hdcDraw, oldBkMode );
+
+ if (pUpdateLayeredWindow)
+ {
+ SetWindowLongPtr( hwnd, GWL_EXSTYLE, GetWindowLongPtr(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED );
+
+ RECT rc; GetWindowRect(hwnd, &rc);
+ POINT ptDst = {rc.left, rc.top};
+ POINT ptSrc = {0, 0};
+
+ BLENDFUNCTION blend;
+ blend.BlendOp = AC_SRC_OVER;
+ blend.BlendFlags = 0;
+ blend.SourceConstantAlpha = 255;
+ blend.AlphaFormat = AC_SRC_ALPHA;
+
+ pUpdateLayeredWindow(hwnd, NULL, &ptDst, &szSize, bmpContent.getDC(), &ptSrc, 0xffffffff, &blend, ULW_ALPHA);
+ } else
+ {
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
+ UpdateWindow(hwnd);
+ }
+}
+
+void ThumbInfo::PopUpMessageDialog( )
+{
+ CallService( MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)hContact, (LPARAM)0 );
+}
+
+void ThumbInfo::OnTimer(BYTE idTimer)
+{
+ if (idTimer == TIMERID_SELECT_T){
+ KillTimer( hwnd, TIMERID_SELECT_T );
+ ThumbDeselect( FALSE );
+ }
+ if (idTimer == TIMERID_LEAVE_T && !bMouseDown){
+ POINT pt;
+ RECT rc;
+
+ GetCursorPos(&pt);
+ GetThumbRect(&rc);
+ if (!PtInRect(&rc, pt)) {
+ KillTimer( hwnd, TIMERID_LEAVE_T );
+ pThumbMouseIn = NULL;
+ ThumbDeselect( TRUE );
+ }
+ }
+ if (bEnableTip && fcOpt.bShowTip && idTimer == TIMERID_HOVER_T){
+ POINT pt;
+ CLCINFOTIP ti = {0};
+ ti.cbSize = sizeof(ti);
+
+ KillTimer(hwnd, TIMERID_HOVER_T);
+ fTipTimerActive = FALSE;
+ GetCursorPos(&pt);
+ if (abs(pt.x-ptTipSt.x)<5 && abs(pt.y-ptTipSt.y)<5){
+ ti.ptCursor = pt;
+
+ fTipActive = TRUE;
+ ti.isGroup = 0;
+ ti.hItem = hContact;
+ ti.isTreeFocused = 0;
+ CallService("mToolTip/ShowTip", 0, (LPARAM)&ti);
+ }
+ }
+}
+
+void DockThumbs( ThumbInfo *pThumbLeft, ThumbInfo *pThumbRight, BOOL bMoveLeft )
+{
+ if ( ( pThumbRight->dockOpt.hwndLeft == NULL ) && ( pThumbLeft->dockOpt.hwndRight == NULL ))
+ {
+ pThumbRight->dockOpt.hwndLeft = pThumbLeft->hwnd;
+ pThumbLeft->dockOpt.hwndRight = pThumbRight->hwnd;
+ }
+}
+
+
+void UndockThumbs( ThumbInfo *pThumb1, ThumbInfo *pThumb2 )
+{
+ if ( ( pThumb1 == NULL ) || ( pThumb2 == NULL ))
+ {
+ return;
+ }
+
+ if ( pThumb1->dockOpt.hwndRight == pThumb2->hwnd )
+ {
+ pThumb1->dockOpt.hwndRight = NULL;
+ }
+
+ if ( pThumb1->dockOpt.hwndLeft == pThumb2->hwnd )
+ {
+ pThumb1->dockOpt.hwndLeft = NULL;
+ }
+
+ if ( pThumb2->dockOpt.hwndRight == pThumb1->hwnd )
+ {
+ pThumb2->dockOpt.hwndRight = NULL;
+ }
+
+ if ( pThumb2->dockOpt.hwndLeft == pThumb1->hwnd )
+ {
+ pThumb2->dockOpt.hwndLeft = NULL;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// ThumbList
+ThumbList::ThumbList(): LIST<ThumbInfo>(1, cmp)
+{
+}
+
+ThumbList::~ThumbList()
+{
+ for (int i = 0; i < getCount(); ++i)
+ delete (*this)[i];
+ destroy();
+}
+
+ThumbInfo *ThumbList::AddThumb(HWND hwnd, TCHAR *ptszName, HANDLE hContact)
+{
+ ThumbInfo *pThumb = NULL;
+
+ if ( ptszName == NULL ) return( NULL );
+ if ( hContact == NULL ) return( NULL );
+ if ( hwnd == NULL ) return( NULL );
+
+ pThumb = new ThumbInfo;
+
+ if ( pThumb != NULL )
+ {
+ _tcsncpy( pThumb->ptszName, ptszName, USERNAME_LEN - 1 );
+ pThumb->hContact = hContact;
+ pThumb->hwnd = hwnd;
+
+ pThumb->dockOpt.hwndLeft = NULL;
+ pThumb->dockOpt.hwndRight = NULL;
+
+ pThumb->fTipActive = FALSE;
+
+// RegHotkey(szName, hwnd);
+ RegHotkey(hContact, hwnd);
+ }
+
+ insert(pThumb);
+
+ return( pThumb );
+}
+
+void ThumbList::RemoveThumb(ThumbInfo *pThumb)
+{
+ if (!pThumb) return;
+
+ if (fcOpt.bMoveTogether)
+ {
+ UndockThumbs(pThumb, FindThumb(pThumb->dockOpt.hwndLeft));
+ UndockThumbs(pThumb, FindThumb(pThumb->dockOpt.hwndRight));
+ }
+
+ remove(pThumb);
+
+ UnregisterFileDropping( pThumb->hwnd );
+ DestroyWindow( pThumb->hwnd );
+ delete pThumb;
+}
+
+ThumbInfo *ThumbList::FindThumb(HWND hwnd)
+{
+ if (!hwnd) return NULL;
+
+ for (int i = 0; i < getCount(); ++i)
+ if ((*this)[i]->hwnd == hwnd)
+ return (*this)[i];
+
+ return NULL;
+}
+
+ThumbInfo *ThumbList::FindThumbByContact(HANDLE hContact)
+{
+ if (!hContact) return NULL;
+
+ for (int i = 0; i < getCount(); ++i)
+ if ((*this)[i]->hContact == hContact)
+ return (*this)[i];
+
+ return NULL;
+}
+
+int ThumbList::cmp(const ThumbInfo *p1, const ThumbInfo *p2)
+{
+ if ((DWORD)p1->hContact < (DWORD)p2->hContact) return -1;
+ if ((DWORD)p1->hContact > (DWORD)p2->hContact) return +1;
+ return 0;
+}
diff --git a/plugins/FloatingContacts/src/thumbs.h b/plugins/FloatingContacts/src/thumbs.h
new file mode 100644
index 0000000000..ee6db80097
--- /dev/null
+++ b/plugins/FloatingContacts/src/thumbs.h
@@ -0,0 +1,74 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+#define USERNAME_LEN 50
+class CDropTarget;
+
+typedef struct _DockOpt
+{
+ HWND hwndLeft;
+ HWND hwndRight;
+}
+DockOpt;
+
+struct ThumbInfo
+{
+public: // TODO: make private
+ HWND hwnd;
+ TCHAR ptszName[ USERNAME_LEN ];
+ HANDLE hContact;
+ int iIcon;
+ CDropTarget * dropTarget;
+ DockOpt dockOpt;
+ BOOL fTipActive;
+ BOOL fTipTimerActive;
+ POINT ptTipSt;
+
+ BYTE btAlpha;
+ MyBitmap bmpContent;
+
+ POINT ptPos;
+ SIZE szSize;
+
+public:
+ ThumbInfo();
+ ~ThumbInfo();
+
+ void GetThumbRect (RECT *rc);
+ void PositionThumb (short nX, short nY);
+ void PositionThumbWorker (short nX, short nY, POINT *rcNewPos);
+ void ResizeThumb ();
+ void RefreshContactIcon (int iIcon);
+ void RefreshContactStatus (int idStatus);
+ void DeleteContactPos ();
+ void OnLButtonDown (short nX, short nY);
+ void OnLButtonUp ();
+ void OnMouseMove (short nX, short nY, WPARAM wParam);
+ void ThumbSelect (BOOL bMouse);
+ void ThumbDeselect (BOOL bMouse);
+ void SetThumbOpacity (BYTE btAlpha);
+ void KillTip ();
+ void UpdateContent ();
+ void PopUpMessageDialog ();
+ void OnTimer (BYTE idTimer);
+};
+
+void UndockThumbs ( ThumbInfo *pThumb1, ThumbInfo *pThumb2 );
+void DockThumbs ( ThumbInfo *pThumbLeft, ThumbInfo *pThumbRight, BOOL bMoveLeft );
+
+class ThumbList: public LIST<ThumbInfo>
+{
+public:
+ ThumbList();
+ ~ThumbList();
+
+ ThumbInfo* AddThumb (HWND hwnd, TCHAR *ptszName, HANDLE hContact);
+ void RemoveThumb (ThumbInfo *pThumb);
+
+ ThumbInfo* FindThumb (HWND hwnd);
+ ThumbInfo* FindThumbByContact (HANDLE hContact);
+
+private:
+ static int cmp(const ThumbInfo *p1, const ThumbInfo *p2);
+};
+
+extern ThumbList thumbList;
diff --git a/plugins/FloatingContacts/src/version.h b/plugins/FloatingContacts/src/version.h
new file mode 100644
index 0000000000..3b8d0e8e20
--- /dev/null
+++ b/plugins/FloatingContacts/src/version.h
@@ -0,0 +1,23 @@
+#define BUILD_NUM 2
+#define BUILD_NUM_STR "2"
+#define REVISION "$Revision: 1136 $"
+
+#define COREVERSION_NUM 1, 0, 2,
+#define COREVERSION_NUM_STR "1, 0, 2"
+
+#define MINIMAL_COREVERSION 0, 6, 0, 0
+#define MINIMAL_COREVERSION_STR "0, 6, 0, 0"
+
+#define FILE_VERSION COREVERSION_NUM BUILD_NUM
+#define FILE_VERSION_STR COREVERSION_NUM_STR " build " BUILD_NUM_STR " " REVISION
+
+#define PRODUCT_VERSION FILE_VERSION
+#define PRODUCT_VERSION_STR FILE_VERSION_STR
+
+#define __PLUGIN_NAME "Floating Contacts"
+#define __FILENAME "FltContacts.dll"
+#define __DESC "Floating Contacts plugin for Miranda"
+#define __AUTHOR "Iavor Vajarov, Kosh&chka, Victor Pavlychko"
+#define __AUTHOREMAIL "ell-6@ya.ru"
+#define __AUTHORWEB "http://www.miranda-im.org/"
+#define __COPYRIGHT "© 2002-2004 I. Vajarov (ivajarov@code.bg), © 2008 Kosh&chka, V. Pavlychko"