summaryrefslogtreecommitdiff
path: root/src/win32/cdwclp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/win32/cdwclp.c')
-rw-r--r--src/win32/cdwclp.c551
1 files changed, 551 insertions, 0 deletions
diff --git a/src/win32/cdwclp.c b/src/win32/cdwclp.c
new file mode 100644
index 0000000..e39cb7f
--- /dev/null
+++ b/src/win32/cdwclp.c
@@ -0,0 +1,551 @@
+/** \file
+ * \brief Windows Clipboard Driver
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cdwin.h"
+#include "cdclipbd.h"
+#include "cdmf.h"
+#include "cdemf.h"
+#include "cdwmf.h"
+#include "cdmf_private.h"
+
+
+static cdSizeCB cdsizecb = NULL;
+
+static int cdregistercallback(int cb, cdCallback func)
+{
+ switch (cb)
+ {
+ case CD_SIZECB:
+ cdsizecb = (cdSizeCB)func;
+ return CD_OK;
+ }
+
+ return CD_ERROR;
+}
+
+/*
+%F cdPlay para Clipboard.
+Interpreta os dados do clipboard, seja metafile ou bitmap.
+*/
+static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data)
+{
+ char tmpPath[512];
+ char filename[1024];
+ HANDLE hFile;
+ DWORD dwSize, nBytesWrite;
+ int err;
+ char* buffer;
+
+ if (IsClipboardFormatAvailable(CF_TEXT))
+ {
+ HANDLE Handle;
+
+ GetTempPath(512, tmpPath);
+ GetTempFileName(tmpPath, "~cd", 0, filename);
+
+ OpenClipboard(NULL);
+ Handle = GetClipboardData(CF_TEXT);
+ if (Handle == NULL)
+ {
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ buffer = (char*)GlobalLock(Handle);
+ dwSize = (DWORD)strlen(buffer);
+
+ hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ WriteFile(hFile, buffer, dwSize, &nBytesWrite, NULL);
+ CloseHandle(hFile);
+
+ GlobalUnlock(Handle);
+
+ CloseClipboard();
+
+ err = cdCanvasPlay(canvas, CD_METAFILE, xmin, xmax, ymin, ymax, filename);
+
+ DeleteFile(filename);
+
+ if (err == CD_OK)
+ return err;
+ }
+
+ if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
+ {
+ HENHMETAFILE Handle;
+
+ GetTempPath(512, tmpPath);
+ GetTempFileName(tmpPath, "~cd", 0, filename);
+
+ OpenClipboard(NULL);
+ Handle = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE);
+ if (Handle == NULL)
+ {
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ dwSize = GetEnhMetaFileBits(Handle, 0, NULL);
+
+ buffer = (char*)malloc(dwSize);
+
+ GetEnhMetaFileBits(Handle, dwSize, buffer);
+
+ hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ WriteFile(hFile, buffer, dwSize, &nBytesWrite, NULL);
+ CloseHandle(hFile);
+
+ free(buffer);
+
+ CloseClipboard();
+
+ err = cdCanvasPlay(canvas, CD_EMF, xmin, xmax, ymin, ymax, filename);
+
+ DeleteFile(filename);
+
+ return err;
+ }
+
+ if (IsClipboardFormatAvailable(CF_METAFILEPICT))
+ {
+ HANDLE Handle;
+ METAFILEPICT* lpMFP;
+
+ GetTempPath(512, tmpPath);
+ GetTempFileName(tmpPath, "~cd", 0, filename);
+
+ OpenClipboard(NULL);
+ Handle = GetClipboardData(CF_METAFILEPICT);
+ if (Handle == NULL)
+ {
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ lpMFP = (METAFILEPICT*) GlobalLock(Handle);
+
+ dwSize = GetMetaFileBitsEx(lpMFP->hMF, 0, NULL);
+ buffer = (char*)malloc(dwSize);
+
+ GetMetaFileBitsEx(lpMFP->hMF, dwSize, buffer);
+
+ hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ wmfWritePlacebleFile(hFile, buffer, dwSize, lpMFP->mm, lpMFP->xExt, lpMFP->yExt);
+ CloseHandle(hFile);
+
+ GlobalUnlock(Handle);
+ free(buffer);
+
+ CloseClipboard();
+
+ err = cdCanvasPlay(canvas, CD_WMF, xmin, xmax, ymin, ymax, filename);
+
+ DeleteFile(filename);
+
+ return err;
+ }
+
+ if (IsClipboardFormatAvailable(CF_DIB))
+ {
+ HANDLE Handle;
+ int size;
+ cdwDIB dib;
+
+ OpenClipboard(NULL);
+ Handle = GetClipboardData(CF_DIB);
+ if (Handle == NULL)
+ {
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ cdwDIBReference(&dib, (BYTE*) GlobalLock(Handle), NULL);
+
+ if (dib.type == -1)
+ {
+ GlobalUnlock(Handle);
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ if (cdsizecb)
+ {
+ int err;
+ err = cdsizecb(canvas, dib.w, dib.h, dib.w, dib.h);
+ if (err)
+ {
+ GlobalUnlock(Handle);
+ CloseClipboard();
+ return CD_ERROR;
+ }
+ }
+
+ size = dib.w*dib.h;
+
+ if (xmax == 0) xmax = dib.w + xmin - 1;
+ if (ymax == 0) ymax = dib.h + ymin - 1;
+
+ if (dib.type == 0)
+ {
+ char *r, *g, *b;
+
+ r = (char*)malloc(size);
+ g = (char*)malloc(size);
+ b = (char*)malloc(size);
+
+ cdwDIBDecodeRGB(&dib, r, g, b);
+
+ cdCanvasPutImageRectRGB(canvas, dib.w, dib.h, r, g, b, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1, 0, 0, 0, 0);
+
+ free(r);
+ free(g);
+ free(b);
+ }
+ else
+ {
+ char *index;
+ long *colors;
+
+ index = (char*)malloc(size);
+ colors = (long*)malloc(256*sizeof(long));
+
+ cdwDIBDecodeMap(&dib, index, colors);
+
+ cdCanvasPutImageRectMap(canvas, dib.w, dib.h, index, colors, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1, 0, 0, 0, 0);
+
+ free(index);
+ free(colors);
+ }
+
+ GlobalUnlock(Handle);
+
+ CloseClipboard();
+
+ return CD_ERROR;
+ }
+
+ if (IsClipboardFormatAvailable(CF_BITMAP))
+ {
+ HBITMAP Handle;
+ int size, type;
+ cdwDIB dib;
+ HDC ScreenDC;
+ SIZE sz;
+
+ OpenClipboard(NULL);
+ Handle = GetClipboardData(CF_BITMAP);
+ if (Handle == NULL)
+ {
+ CloseClipboard();
+ return CD_ERROR;
+ }
+
+ GetBitmapDimensionEx(Handle, &sz);
+
+ ScreenDC = GetDC(NULL);
+ if (GetDeviceCaps(ScreenDC, BITSPIXEL) > 8)
+ type = 0;
+ else
+ type = 1;
+
+ dib.w = sz.cx;
+ dib.h = sz.cy;
+ dib.type = type;
+
+ if (cdsizecb)
+ {
+ int err;
+ err = cdsizecb(canvas, dib.w, dib.h, dib.w, dib.h);
+ if (err)
+ {
+ ReleaseDC(NULL, ScreenDC);
+ CloseClipboard();
+ return CD_ERROR;
+ }
+ }
+
+ cdwCreateDIB(&dib);
+
+ GetDIBits(ScreenDC, Handle, 0, sz.cy, dib.bits, dib.bmi, DIB_RGB_COLORS);
+ ReleaseDC(NULL, ScreenDC);
+
+ size = dib.w*dib.h;
+
+ if (dib.type == 0)
+ {
+ char *r, *g, *b;
+
+ r = (char*)malloc(size);
+ g = (char*)malloc(size);
+ b = (char*)malloc(size);
+
+ cdwDIBDecodeRGB(&dib, r, g, b);
+
+ cdCanvasPutImageRectRGB(canvas, dib.w, dib.h, r, g, b, 0, 0, dib.w, dib.h, 0, 0, 0, 0);
+
+ free(r);
+ free(g);
+ free(b);
+ }
+ else
+ {
+ char *index;
+ long *colors;
+
+ index = (char*)malloc(size);
+ colors = (long*)malloc(256*sizeof(long));
+
+ cdwDIBDecodeMap(&dib, index, colors);
+
+ cdCanvasPutImageRectMap(canvas, dib.w, dib.h, index, colors, 0, 0, dib.w, dib.h, 0, 0, 0, 0);
+
+ free(index);
+ free(colors);
+ }
+
+ cdwKillDIB(&dib);
+
+ CloseClipboard();
+
+ return CD_ERROR;
+ }
+
+ return CD_ERROR;
+}
+
+static void cdkillcanvasCLIPBDMF (cdCtxCanvas *ctxcanvas)
+{
+ HANDLE Handle, hFile;
+ char* buffer;
+ DWORD dwSize, nBytesRead;
+ char filename[10240];
+ cdCanvasMF* mfcanvas = (cdCanvasMF*)ctxcanvas;
+
+ /* guardar antes de remover o canvas */
+ strcpy(filename, mfcanvas->filename);
+
+ OpenClipboard(NULL);
+ EmptyClipboard();
+
+ cdkillcanvasMF(mfcanvas); /* this will close the file */
+
+ hFile = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ dwSize = GetFileSize (hFile, NULL) ;
+
+ Handle = GlobalAlloc(GMEM_MOVEABLE, dwSize+1);
+ buffer = (char*)GlobalLock(Handle);
+ ReadFile(hFile, buffer, dwSize, &nBytesRead, NULL);
+ buffer[dwSize] = 0;
+ GlobalUnlock(Handle);
+
+ CloseHandle(hFile);
+
+ SetClipboardData(CF_TEXT, Handle);
+
+ CloseClipboard();
+}
+
+static void cdkillcanvas (cdCtxCanvas *ctxcanvas)
+{
+ cdwKillCanvas(ctxcanvas);
+
+ OpenClipboard(NULL);
+ EmptyClipboard();
+
+ if (ctxcanvas->wtype == CDW_WMF)
+ {
+ HMETAFILE hmf = CloseMetaFile(ctxcanvas->hDC);
+
+ HANDLE hMemG;
+ METAFILEPICT* lpMFP;
+
+ hMemG = GlobalAlloc(GHND|GMEM_DDESHARE, (DWORD)sizeof(METAFILEPICT));
+ lpMFP = (METAFILEPICT*) GlobalLock(hMemG);
+
+ lpMFP->mm = MM_ANISOTROPIC;
+ lpMFP->xExt = (long)(100 * ctxcanvas->canvas->w_mm);
+ lpMFP->yExt = (long)(100 * ctxcanvas->canvas->h_mm);
+
+ lpMFP->hMF = hmf;
+
+ GlobalUnlock(hMemG);
+ SetClipboardData(CF_METAFILEPICT, hMemG);
+ }
+ else if (ctxcanvas->wtype == CDW_EMF)
+ {
+ HENHMETAFILE hmf = CloseEnhMetaFile(ctxcanvas->hDC);
+ SetClipboardData(CF_ENHMETAFILE, hmf);
+ }
+ else
+ {
+ HANDLE hDib;
+
+ GdiFlush();
+
+ hDib = cdwCreateCopyHDIB(&ctxcanvas->bmiClip, ctxcanvas->bitsClip);
+
+ SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBitmapClip);
+ DeleteObject(ctxcanvas->hBitmapClip);
+ DeleteDC(ctxcanvas->hDC);
+
+ SetClipboardData(CF_DIB, hDib);
+ }
+
+ CloseClipboard();
+
+ memset(ctxcanvas, 0, sizeof(cdCtxCanvas));
+ free(ctxcanvas);
+}
+
+static void cdcreatecanvas(cdCanvas* canvas, void *data)
+{
+ char* strsize = (char*)data;
+ int w = 0, h = 0, wtype = CDW_EMF; /* default clipboard type */
+ double xres=0, yres=0;
+ HDC hDC;
+ BITMAPINFO bmi;
+ BYTE* bits;
+ HBITMAP hBitmapClip, hOldBitmapClip;
+
+ /* Inicializa parametros */
+ if (strsize == NULL)
+ return;
+
+ if (strstr(strsize, "-b") != NULL)
+ wtype = CDW_BMP;
+ else if (strstr(strsize, "-m") != NULL)
+ wtype = -1; /* CD METAFILE */
+
+ if (wtype != -1)
+ {
+ sscanf(strsize,"%dx%d",&w, &h);
+ if (w == 0 || h == 0)
+ return;
+ }
+
+ if (wtype == CDW_EMF)
+ {
+ HDC ScreenDC = GetDC(NULL);
+ RECT rect;
+ /* LOGPIXELS can not be used for EMF */
+ xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE);
+ yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE);
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = (int)(100. * w / xres);
+ rect.bottom = (int)(100. * h / yres);
+ hDC = CreateEnhMetaFile(ScreenDC,NULL,&rect,NULL);
+ ReleaseDC(NULL, ScreenDC);
+ }
+ else if (wtype == CDW_BMP)
+ {
+ HDC ScreenDC = GetDC(NULL);
+ hDC = CreateCompatibleDC(ScreenDC);
+ xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE);
+ yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE);
+
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = w;
+ bmi.bmiHeader.biHeight = h;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 24;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biSizeImage = 0;
+ bmi.bmiHeader.biXPelsPerMeter = (long)(GetDeviceCaps(ScreenDC, LOGPIXELSX) / 0.0254);
+ bmi.bmiHeader.biYPelsPerMeter = (long)(GetDeviceCaps(ScreenDC, LOGPIXELSY) / 0.0254);
+ bmi.bmiHeader.biClrUsed = 0;
+ bmi.bmiHeader.biClrImportant = 0;
+
+ hBitmapClip = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
+
+ ReleaseDC(NULL, ScreenDC);
+
+ if (!hBitmapClip)
+ return;
+
+ hOldBitmapClip = SelectObject(hDC, hBitmapClip);
+ }
+
+ if (wtype == -1)
+ {
+ char filename[1024];
+ char tmpPath[512];
+ char str[1024];
+
+ GetTempPath(512, tmpPath);
+ GetTempFileName(tmpPath, "~cd", 0, filename);
+
+ sprintf(str, "%s %s", filename, strsize);
+ cdcreatecanvasMF(canvas, str);
+ }
+ else
+ {
+ cdCtxCanvas* ctxcanvas;
+
+ /* Inicializa driver WIN32 */
+ ctxcanvas = cdwCreateCanvas(canvas, NULL, hDC, wtype);
+
+ canvas->w = w;
+ canvas->h = h;
+ canvas->xres = xres;
+ canvas->yres = yres;
+ canvas->w_mm = ((double)w) / xres;
+ canvas->h_mm = ((double)h) / yres;
+ canvas->bpp = 24;
+ ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1;
+ ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1;
+
+ if (wtype == CDW_BMP)
+ {
+ ctxcanvas->hBitmapClip = hBitmapClip;
+ ctxcanvas->hOldBitmapClip = hOldBitmapClip;
+ ctxcanvas->bmiClip = bmi;
+ ctxcanvas->bitsClip = bits;
+ }
+ }
+}
+
+static void cdinittable(cdCanvas* canvas)
+{
+ if (canvas->invert_yaxis == 0) /* a simple way to distinguish MF from WIN */
+ {
+ cdinittableMF(canvas);
+ canvas->cxKillCanvas = cdkillcanvasCLIPBDMF;
+ }
+ else
+ {
+ cdwInitTable(canvas);
+ canvas->cxKillCanvas = cdkillcanvas;
+ }
+}
+
+static cdContext cdClipboardContext =
+{
+ CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_YAXIS |
+ CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV |
+ CD_CAP_FPRIMTIVES ),
+ 0,
+ cdcreatecanvas,
+ cdinittable,
+ cdplay,
+ cdregistercallback
+};
+
+cdContext* cdContextClipboard(void)
+{
+ if (cdUseContextPlus(CD_QUERY))
+ {
+ cdContext* ctx = cdGetContextPlus(CD_CTX_CLIPBOARD);
+ if (ctx != NULL)
+ return ctx;
+ }
+
+ return &cdClipboardContext;
+}