summaryrefslogtreecommitdiff
path: root/plugins/Clist_modern/modern_image_array.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Clist_modern/modern_image_array.cpp')
-rw-r--r--plugins/Clist_modern/modern_image_array.cpp705
1 files changed, 705 insertions, 0 deletions
diff --git a/plugins/Clist_modern/modern_image_array.cpp b/plugins/Clist_modern/modern_image_array.cpp
new file mode 100644
index 0000000000..f8381ad9e6
--- /dev/null
+++ b/plugins/Clist_modern/modern_image_array.cpp
@@ -0,0 +1,705 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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.
+
+Created by Pescuma
+
+*/
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_image_array.h"
+#include "hdr/modern_commonprototypes.h"
+
+// To use this code in other places, replace the body of this func by the body of ske_CreateDIB32
+static HBITMAP ImageArray_CreateBitmapPoint(int cx, int cy, void ** pt)
+{
+ return ske_CreateDIB32Point(cx, cy, pt);
+}
+
+
+// Initialize data
+static BOOL ImageArray_Alloc(LP_IMAGE_ARRAY_DATA iad, int size)
+{
+ int size_grow = size;
+
+ if (size_grow > iad->nodes_allocated_size)
+ {
+ size_grow += iad->grow_step - (size_grow % iad->grow_step);
+
+ if (iad->nodes != NULL)
+ {
+ IMAGE_ARRAY_DATA_NODE *tmp = (IMAGE_ARRAY_DATA_NODE *) realloc((void *)iad->nodes,
+ sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+
+ if (tmp == NULL)
+ {
+ TRACE("Out of memory: realloc returned NULL (ImageArray_Alloc)");
+ ImageArray_Free(iad, FALSE);
+ return FALSE;
+ }
+
+ iad->nodes = tmp;
+ memset( &iad->nodes[iad->nodes_allocated_size], 0, (size_grow - iad->nodes_allocated_size) * sizeof(IMAGE_ARRAY_DATA_NODE) );
+ }
+ else
+ {
+ iad->nodes = (IMAGE_ARRAY_DATA_NODE *) malloc(sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+
+ if (iad->nodes == NULL)
+ {
+ TRACE("Out of memory: alloc returned NULL (ImageArray_Alloc)");
+
+ ImageArray_Free(iad, FALSE);
+
+ return FALSE;
+ }
+
+ ZeroMemory(iad->nodes, sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+ }
+
+ iad->nodes_allocated_size = size_grow;
+ }
+ else if (size < iad->nodes_allocated_size)
+ {
+ // Give some more space to try to avoid a free
+ if ( (iad->nodes_allocated_size - size) / iad->grow_step >= 2 )
+ {
+ IMAGE_ARRAY_DATA_NODE *tmp;
+
+ size_grow += iad->grow_step - (size_grow % iad->grow_step);
+
+ tmp = (IMAGE_ARRAY_DATA_NODE *) realloc((void *)iad->nodes, sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+
+ if (tmp == NULL)
+ {
+ TRACE("Out of memory: realloc returned NULL when reducing size! (ImageArray_Alloc)");
+
+ ImageArray_Free(iad, FALSE);
+
+ return FALSE;
+ }
+
+ iad->nodes = tmp;
+ }
+ }
+
+ iad->nodes_size = size;
+
+ return TRUE;
+}
+
+
+// Initialize data
+void ImageArray_Initialize(LP_IMAGE_ARRAY_DATA iad, BOOL width_based, int grow_step)
+{
+ iad->width_based = width_based;
+ iad->grow_step = grow_step;
+ if (iad->grow_step <= 0)
+ {
+ iad->grow_step = 1;
+ }
+ iad->hdc = CreateCompatibleDC(NULL);
+ iad->img = NULL;
+
+ iad->width = 0;
+ iad->height = 0;
+
+ InitializeCriticalSection(&iad->cs);
+
+ iad->nodes = NULL;
+ iad->nodes_allocated_size = 0;
+ iad->nodes_size = 0;
+}
+
+
+// Free data
+// If keep_bitmap is TRUE, doesn't delete de bitmap and return its handle. Else, return NULL
+HBITMAP ImageArray_Free(LP_IMAGE_ARRAY_DATA iad, BOOL keep_bitmap)
+{
+ mod_DeleteDC(iad->hdc);
+
+ if (iad->img != NULL && !keep_bitmap)
+ {
+ DeleteObject(iad->img);
+ iad->img = NULL;
+ iad->width = 0;
+ iad->height = 0;
+ }
+
+ if (iad->nodes != NULL)
+ {
+ free(iad->nodes);
+ iad->nodes = NULL;
+ iad->nodes_allocated_size = 0;
+ iad->nodes_size = 0;
+ }
+
+ DeleteCriticalSection(&iad->cs);
+
+ return iad->img;
+}
+
+// Free data but keep config
+void ImageArray_Clear(LP_IMAGE_ARRAY_DATA iad)
+{
+ HDC tmpdc = CreateCompatibleDC(iad->hdc);
+ if (iad->hdc) mod_DeleteDC(iad->hdc);
+ iad->hdc = tmpdc;
+
+ if (iad->img != NULL)
+ {
+ DeleteObject(iad->img);
+ iad->img = NULL;
+ iad->width = 0;
+ iad->height = 0;
+ }
+
+ if (iad->nodes != NULL)
+ {
+ free(iad->nodes);
+ iad->nodes = NULL;
+ iad->nodes_allocated_size = 0;
+ iad->nodes_size = 0;
+ }
+}
+
+
+// Add image to the list (return the index of the image or -1 on error)
+// If pos == -1, add to the end of the list
+int ImageArray_AddImage(LP_IMAGE_ARRAY_DATA iad, HBITMAP hBmp, int pos)
+{
+ BITMAP bm;
+ int new_width, new_height;
+ HBITMAP hNewBmp, old_bmp;
+ HDC hdc_old;
+ BOOL last_one;
+
+ int i;
+
+ if (hBmp == NULL)
+ return -1;
+
+ EnterCriticalSection(&iad->cs);
+
+ if (pos < 0)
+ pos = iad->nodes_size;
+
+ // Add to end?
+ if (pos >= iad->nodes_size)
+ {
+ pos = iad->nodes_size;
+ last_one = TRUE;
+ }
+ else
+ {
+ last_one = FALSE;
+ }
+
+ // Get bounds
+ if (!GetObject(hBmp,sizeof(BITMAP),&bm))
+ {
+ LeaveCriticalSection(&iad->cs);
+ return -1;
+ }
+
+ if (iad->width_based)
+ {
+ new_width = max(bm.bmWidth, iad->width);
+ new_height = iad->height + bm.bmHeight;
+ }
+ else
+ {
+ new_width = bm.bmWidth + iad->width;
+ new_height = max(iad->height, bm.bmHeight);
+ }
+
+ // Alloc image
+ hNewBmp = ImageArray_CreateBitmapPoint(new_width, new_height,&(iad->lpBits));
+ if (hNewBmp == NULL)
+ {
+ LeaveCriticalSection(&iad->cs);
+ return -1;
+ }
+
+ // Alloc array
+ if (!ImageArray_Alloc(iad, iad->nodes_size + 1))
+ {
+ DeleteObject(hNewBmp);
+ LeaveCriticalSection(&iad->cs);
+ return -1;
+ }
+
+ // Move image...
+
+ // Set some draw states
+ SelectObject(iad->hdc, hNewBmp);
+ hdc_old = CreateCompatibleDC(iad->hdc);
+ old_bmp = (HBITMAP)GetCurrentObject(hdc_old, OBJ_BITMAP);
+
+ SetBkMode(iad->hdc,TRANSPARENT);
+ {
+ POINT org;
+ GetBrushOrgEx(iad->hdc, &org);
+ SetStretchBltMode(iad->hdc, HALFTONE);
+ SetBrushOrgEx(iad->hdc, org.x, org.y, NULL);
+ }
+
+ {
+ int x = 0, y = 0, w = 0, h = 0;
+
+ // 1- old data
+ if (pos > 0)
+ {
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ w = iad->width;
+ h = 0;
+ for(i = 0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = iad->height;
+ w = 0;
+ for(i = 0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ BitBlt(iad->hdc, 0, 0, w, h, hdc_old, 0, 0, SRCCOPY);
+ }
+
+ // 2- new image
+ if (iad->width_based)
+ {
+ x = 0;
+ y = h;
+ }
+ else
+ {
+ x = w;
+ y = 0;
+ }
+ SelectObject(hdc_old, hBmp);
+ BitBlt(iad->hdc, x, y, bm.bmWidth, bm.bmHeight, hdc_old, 0, 0, SRCCOPY);
+
+ // 3- old data
+ if (!last_one)
+ {
+ int ox, oy;
+
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ ox = 0;
+ oy = y;
+
+ x = 0;
+ y += bm.bmHeight;
+
+ w = iad->width;
+ h = iad->height - h;
+ }
+ else
+ {
+ ox = x;
+ oy = 0;
+
+ x += bm.bmWidth;
+ y = 0;
+
+ w = iad->width - w;
+ h = iad->height;
+ }
+ BitBlt(iad->hdc, x, y, w, h, hdc_old, ox, oy, SRCCOPY);
+ }
+ }
+
+ // restore things
+ SelectObject(hdc_old,old_bmp);
+ mod_DeleteDC(hdc_old);
+ if (iad->img != NULL) DeleteObject(iad->img);
+ iad->img = hNewBmp;
+
+ // Move array
+ if (!last_one && iad->nodes_size > 1)
+ {
+ memmove(&iad->nodes[pos+1], &iad->nodes[pos], (iad->nodes_size - pos) * sizeof(IMAGE_ARRAY_DATA_NODE));
+ }
+ iad->nodes[pos].width = bm.bmWidth;
+ iad->nodes[pos].height = bm.bmHeight;
+
+ iad->width = new_width;
+ iad->height = new_height;
+
+ // Finished it!
+ LeaveCriticalSection(&iad->cs);
+
+ return pos;
+}
+
+
+
+// Change an image in the list (return TRUE on success)
+BOOL ImageArray_ChangeImage(LP_IMAGE_ARRAY_DATA iad, HBITMAP hBmp, int pos)
+{
+ BITMAP bm;
+ int new_width, new_height;
+ HBITMAP hNewBmp;
+ HDC hdc_old;
+ int i;
+
+ if (hBmp == NULL)
+ return FALSE;
+
+ if (pos < 0)
+ return FALSE;
+
+ if (pos >= iad->nodes_size)
+ return FALSE;
+
+ EnterCriticalSection(&iad->cs);
+
+ // Get bounds
+ if (!GetObject(hBmp,sizeof(BITMAP),&bm))
+ {
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+ }
+
+ if (iad->width_based)
+ {
+ new_width = max(bm.bmWidth, iad->width);
+ new_height = iad->height + bm.bmHeight - iad->nodes[pos].height;
+ }
+ else
+ {
+ new_width = bm.bmWidth + iad->width - iad->nodes[pos].width;
+ new_height = max(iad->height, bm.bmHeight);
+ }
+
+ // Alloc image
+ hNewBmp = ImageArray_CreateBitmapPoint(new_width, new_height,&(iad->lpBits));
+ if (hNewBmp == NULL)
+ {
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+ }
+
+ // Move image...
+
+ // Set some draw states
+ SelectObject(iad->hdc, hNewBmp);
+ hdc_old = CreateCompatibleDC(iad->hdc);
+
+ SetBkMode(iad->hdc, TRANSPARENT);
+ {
+ POINT org;
+ GetBrushOrgEx(iad->hdc, &org);
+ SetStretchBltMode(iad->hdc, HALFTONE);
+ SetBrushOrgEx(iad->hdc, org.x, org.y, NULL);
+ }
+
+ {
+ int x = 0, y = 0, w = 0, h = 0;
+
+ // 1- old data
+ if (pos > 0)
+ {
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ w = iad->width;
+ h = 0;
+ for(i = 0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = iad->height;
+ w = 0;
+ for(i = 0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ BitBlt(iad->hdc, 0, 0, w, h, hdc_old, 0, 0, SRCCOPY);
+ }
+
+ // 2- new image
+ if (iad->width_based)
+ {
+ x = 0;
+ y = h;
+ }
+ else
+ {
+ x = w;
+ y = 0;
+ }
+ SelectObject(hdc_old, hBmp);
+ BitBlt(iad->hdc, x, y, bm.bmWidth, bm.bmHeight, hdc_old, 0, 0, SRCCOPY);
+
+ // 3- old data
+ if (pos < iad->nodes_size - 1)
+ {
+ int ox, oy;
+
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ ox = 0;
+ oy = y + iad->nodes[pos].height;
+
+ x = 0;
+ y += bm.bmHeight;
+
+ w = iad->width;
+ h = iad->height - h - iad->nodes[pos].height;
+ }
+ else
+ {
+ ox = x + iad->nodes[pos].width;
+ oy = 0;
+
+ x += bm.bmWidth;
+ y = 0;
+
+ w = iad->width - w - iad->nodes[pos].width;
+ h = iad->height;
+ }
+ BitBlt(iad->hdc, x, y, w, h, hdc_old, ox, oy, SRCCOPY);
+ }
+ }
+
+ // restore things
+ mod_DeleteDC(hdc_old);
+ if (iad->img != NULL) DeleteObject(iad->img);
+ iad->img = hNewBmp;
+
+ // Move array
+ iad->nodes[pos].width = bm.bmWidth;
+ iad->nodes[pos].height = bm.bmHeight;
+
+ iad->width = new_width;
+ iad->height = new_height;
+
+ // Finished it!
+ LeaveCriticalSection(&iad->cs);
+
+ return pos;
+}
+
+
+// Remove an image
+BOOL ImageArray_RemoveImage(LP_IMAGE_ARRAY_DATA iad, int pos)
+{
+ int new_width, new_height;
+ HBITMAP hNewBmp;
+ HDC hdc_old;
+ int i;
+
+ if (pos < 0)
+ return FALSE;
+
+ if (pos >= iad->nodes_size)
+ return FALSE;
+
+ EnterCriticalSection(&iad->cs);
+
+ // Get bounds
+ if (iad->width_based)
+ {
+ new_width = iad->width;
+ new_height = iad->height - iad->nodes[pos].height;
+ }
+ else
+ {
+ new_width = iad->width - iad->nodes[pos].width;
+ new_height = iad->height;
+ }
+
+ // Alloc image
+ hNewBmp = ImageArray_CreateBitmapPoint(new_width, new_height,&(iad->lpBits));
+ if (hNewBmp == NULL)
+ {
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+ }
+
+ // Move image...
+
+ // Set some draw states
+ SelectObject(iad->hdc, hNewBmp);
+ hdc_old = CreateCompatibleDC(iad->hdc);
+
+ SetBkMode(iad->hdc, TRANSPARENT);
+ {
+ POINT org;
+ GetBrushOrgEx(iad->hdc, &org);
+ SetStretchBltMode(iad->hdc, HALFTONE);
+ SetBrushOrgEx(iad->hdc, org.x, org.y, NULL);
+ }
+
+ {
+ int x = 0, y = 0, w = 0, h = 0;
+
+ if (pos > 0)
+ {
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ w = iad->width;
+ h = 0;
+ for(i = 0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = iad->height;
+ w = 0;
+ for(i = 0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ BitBlt(iad->hdc, 0, 0, w, h, hdc_old, 0, 0, SRCCOPY);
+ }
+
+ if (pos < iad->nodes_size - 1)
+ {
+ int ox, oy;
+
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ ox = 0;
+ oy = h + iad->nodes[pos].height;
+
+ x = 0;
+ y = h;
+
+ w = iad->width;
+ h = iad->height - h - iad->nodes[pos].height;
+ }
+ else
+ {
+ ox = w + iad->nodes[pos].width;
+ oy = 0;
+
+ x = w;
+ y = 0;
+
+ w = iad->width - w - iad->nodes[pos].width;
+ h = iad->height;
+ }
+ BitBlt(iad->hdc, x, y, w, h, hdc_old, ox, oy, SRCCOPY);
+ }
+ }
+
+ // restore things
+ mod_DeleteDC(hdc_old);
+ if (iad->img != NULL) DeleteObject(iad->img);
+ iad->img = hNewBmp;
+
+ // Move array
+ if (pos < iad->nodes_size - 1)
+ {
+ memmove(&iad->nodes[pos], &iad->nodes[pos + 1], (iad->nodes_size - pos - 1) * sizeof(IMAGE_ARRAY_DATA_NODE));
+ }
+
+ iad->nodes_size--;
+
+ iad->width = new_width;
+ iad->height = new_height;
+
+ // Free array
+ ImageArray_Alloc(iad, iad->nodes_size);
+
+ // Finished it!
+ LeaveCriticalSection(&iad->cs);
+
+ return pos;
+}
+
+
+
+BOOL ImageArray_DrawImage(LP_IMAGE_ARRAY_DATA iad, int pos, HDC hdcDest, int nXDest, int nYDest, BYTE Alpha)
+{
+ if (hdcDest == NULL || pos < 0 || pos >= iad->nodes_size)
+ return FALSE;
+
+ EnterCriticalSection(&iad->cs);
+ {
+ int w, h, i;
+
+ if (iad->width_based)
+ {
+ w = 0;
+ h = 0;
+ for(i = 0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = 0;
+ w = 0;
+ for(i = 0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ {
+ BLENDFUNCTION bf={AC_SRC_OVER, 0, Alpha, AC_SRC_ALPHA };
+ /*ske_*/AlphaBlend(hdcDest, nXDest, nYDest, iad->nodes[pos].width, iad->nodes[pos].height, iad->hdc, w, h, iad->nodes[pos].width, iad->nodes[pos].height,bf);
+ }
+ }
+
+
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+}
+
+BOOL ImageArray_GetImageSize(LP_IMAGE_ARRAY_DATA iad, int pos, SIZE * lpSize)
+{
+ EnterCriticalSection(&iad->cs);
+ if (lpSize)
+ {
+ lpSize->cx=iad->nodes[pos].width;
+ lpSize->cy=iad->nodes[pos].height;
+ }
+ LeaveCriticalSection(&iad->cs);
+ return TRUE;
+} \ No newline at end of file