2004/01/18 01:27:16
[org.ibex.core.git] / src / org / xwt / plat / Win32.cc
index 3bb342e..c278998 100644 (file)
@@ -1,9 +1,11 @@
 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
+#include "GCJ.cc"
 
-// kinda ugly; we use -DCOMPILE_DLL to combine two .cc files into one
-#ifndef COMPILE_DLL
+// we have to do this because the jpeg libraries use the symbol 'INT32'
+#define INT32 WIN32_INT32
 
 // this has to precede the others so we don't get collisions on min/max
+#include <org/xwt/js/JS.h>
 #include <org/xwt/Box.h>
 
 #include <stdint.h>
 #include <java/util/Hashtable.h>
 #include <org/xwt/Box.h>
 #include <org/xwt/Surface.h>
-#include <org/xwt/DoubleBuffer.h>
+#include <org/xwt/PixelBuffer.h>
 #include <org/xwt/Picture.h>
 #include <org/xwt/Platform.h>
-#include <org/xwt/Platform$ParsedFont.h>
 #include <org/xwt/plat/Win32.h>
-#include <org/xwt/plat/Win32$Win32Font.h>
 #include <org/xwt/plat/Win32$Win32Surface.h>
-#include <org/xwt/plat/Win32$Win32DoubleBuffer.h>
+#include <org/xwt/plat/Win32$Win32PixelBuffer.h>
 #include <org/xwt/plat/Win32$Win32Picture.h>
+#include <org/xwt/util/Log.h>
 #include <org/xwt/util/Semaphore.h>
 
 // for debugging
@@ -61,25 +62,6 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
     }
 }
 
-// This function iterates over each family (lparam == 0), and then over each size (lparam == 1)
-int CALLBACK fontproc(const LOGFONTA* enumlogfont, const TEXTMETRICA* tm, long unsigned int type, LPARAM lparam) {
-
-    if (lparam == 0) {
-        LOGFONT lf;
-        lf.lfCharSet = ANSI_CHARSET;
-        strncpy(lf.lfFaceName, enumlogfont->lfFaceName, 32);
-        lf.lfPitchAndFamily = 0;
-        EnumFontFamiliesEx((HDC)org::xwt::plat::Win32::desktop_dc, &lf, fontproc, 1, 0);
-
-    } else {
-        org::xwt::plat::Win32::addFont(JvNewStringLatin1(enumlogfont->lfFaceName),
-                                       ((type & RASTER_FONTTYPE) == 0) ? 0 : tm->tmHeight,
-                                       tm->tmItalic == 0 ? 0 : 1, 
-                                       tm->tmWeight <= 400 ? 0 : 1);
-    }
-    return 1;
-}
-
 
 // Initialization ////////////////////////////////////////////////////////////////////
 
@@ -183,13 +165,6 @@ void org::xwt::plat::Win32::natInit() {
     org::xwt::plat::Win32::sizewe_cursor = (jint)LoadCursor(NULL, IDC_SIZEWE);
     org::xwt::plat::Win32::hand_cursor = (jint)CreateCursor(GetModuleHandle(NULL), 14, 1, 32, 32, hand_cursor_and, hand_cursor_xor);
 
-    // enumerate fonts
-    LOGFONT lf;
-    lf.lfCharSet = ANSI_CHARSET;
-    lf.lfFaceName[0] = 0;
-    lf.lfPitchAndFamily = 0;
-    EnumFontFamiliesEx((HDC)desktop_dc, &lf, fontproc, 0, 0);
-
     messagePumpThread = (jint)GetCurrentThreadId();
     messagePumpStarted->release();
 
@@ -205,22 +180,31 @@ void org::xwt::plat::Win32::natInit() {
             sprintf(buf, "XWT_WINDOW_CLASS_%i", window_class_counter++);
 
             WNDCLASSEX wc;
-            wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
+            wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
             wc.lpfnWndProc = WndProc;
             wc.cbClsExtra = 0;
             wc.cbSize = sizeof(WNDCLASSEX);
             wc.cbWndExtra = 0;
             wc.hInstance = GetModuleHandle(NULL);
-            wc.hIcon = NULL;
-            wc.hIconSm = NULL;
-            wc.hCursor = NULL;
-            wc.hbrBackground = (HBRUSH)(COLOR_SCROLLBAR + 1);
-            wc.lpszMenuName = NULL;
+            wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+            wc.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL),
+                                          MAKEINTRESOURCE(5),
+                                          IMAGE_ICON,
+                                          GetSystemMetrics(SM_CXSMICON),
+                                          GetSystemMetrics(SM_CYSMICON),
+                                          LR_DEFAULTCOLOR);
+            wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+            wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+            wc.lpszMenuName = "menu";
             wc.lpszClassName = buf;
             RegisterClassEx(&wc);
+
+            surface->hwnd = (jint)CreateWindow(wc.lpszClassName, TEXT(""),
+                                               msg.wParam ? WS_NORMAL : WS_POPUP,
+                                               200, 200, 100, 100,
+                                               (HWND__*)NULL, (HMENU__*)NULL,
+                                               GetModuleHandle(NULL), (LPVOID)NULL);
             
-            surface->hwnd = (jint)CreateWindow(wc.lpszClassName, TEXT(""), msg.wParam ? WS_NORMAL : WS_POPUP, 200, 200, 100, 100,
-                                               (HWND__*)NULL, (HMENU__*)NULL, GetModuleHandle(NULL), (LPVOID)NULL);
             SetFocus((HWND)surface->hwnd);
             surface->hwndCreated->release();
             
@@ -237,6 +221,39 @@ void org::xwt::plat::Win32::natInit() {
 
 // Platform Methods ///////////////////////////////////////////////////////////////////
 
+jstring org::xwt::plat::Win32::_getEnv(jstring key) {
+    int len = JvGetStringUTFLength(key);
+    char buf[len + 1];
+    JvGetStringUTFRegion(key, 0, len, buf);
+    buf[len] = '\0';
+    char buf2[1024];
+    DWORD ret = GetEnvironmentVariable(buf, buf2, 1024);
+    if (ret > 0 && ret < 1024) return JvNewStringLatin1(buf2);
+    return NULL;
+}
+
+jstring org::xwt::plat::Win32::_fileDialog(jstring suggestedFileName, jboolean write) {
+
+    char buf[1024];
+    OPENFILENAME ofn;
+    memset(buf, 0, 1024);
+    memset(&ofn, 0, sizeof(OPENFILENAME));
+
+    if (suggestedFileName != NULL)
+        JvGetStringUTFRegion(suggestedFileName, 0, min(1023, JvGetStringUTFLength(suggestedFileName)), buf);
+    
+    ofn.lStructSize = sizeof(OPENFILENAME);
+    ofn.nMaxCustFilter = 0;
+    ofn.lpstrFile = buf;
+    ofn.nMaxFile = 1024;
+
+    if (write) ofn.Flags |= OFN_OVERWRITEPROMPT;
+    ofn.Flags |= OFN_HIDEREADONLY;
+
+    int ret = write ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn);
+    return ret == 0 ? NULL : JvNewStringLatin1(buf);
+}
+
 void org::xwt::plat::Win32::__detectProxy(JArray<jstring>* container) {
 
     HKEY hkey;
@@ -301,7 +318,7 @@ void org::xwt::plat::Win32::_criticalAbort(jstring message) {
     char buf[JvGetStringUTFLength(message) + 1];
     buf[JvGetStringUTFLength(message)] = '\0';
     JvGetStringUTFRegion(message, 0, JvGetStringUTFLength(message), buf);
-    MessageBox (NULL, buf, "XWT Critical Abort", MB_OK | MB_ICONSTOP | MB_TASKMODAL | MB_SETFOREGROUND);
+    MessageBox (NULL, buf, "XWT Cannot Continue", MB_OK | MB_ICONSTOP | MB_TASKMODAL | MB_SETFOREGROUND);
     java::lang::System::exit(-1);
 }
 
@@ -317,50 +334,6 @@ jint org::xwt::plat::Win32::_getScreenHeight() {
     return rect.bottom - rect.top;
 }
 
-org::xwt::plat::Win32$Win32Font* org::xwt::plat::Win32::mapFont(org::xwt::Platform$ParsedFont* pf) {
-    org::xwt::plat::Win32$Win32Font* ret = new org::xwt::plat::Win32$Win32Font();
-    LOGFONT logfont;
-    memset(&logfont, 0, sizeof(LOGFONT));
-    logfont.lfHeight = -MulDiv(pf->size, GetDeviceCaps((HDC)org::xwt::plat::Win32::desktop_dc, LOGPIXELSY), 72);
-    if (pf->italic) logfont.lfItalic = 1;
-    if (pf->bold) logfont.lfWeight = FW_BOLD;
-    logfont.lfCharSet = ANSI_CHARSET;
-
-    JvGetStringUTFRegion(pf->name, 0, min(31, JvGetStringUTFLength(pf->name)), logfont.lfFaceName);
-    logfont.lfFaceName[min(31, JvGetStringUTFLength(pf->name))] = 0;
-
-    ret->hfont = (jint)CreateFontIndirect(&logfont);
-    SelectObject((HDC)desktop_dc, (HFONT)(ret->hfont));
-
-    TEXTMETRIC tm;
-    GetTextMetrics((HDC)desktop_dc, &tm);
-    POINT p;
-    p.x = 0; p.y = tm.tmAscent;
-    LPtoDP((HDC)desktop_dc, &p, 1); 
-    ret->maxAscent = p.y;
-
-    p.x = 0; p.y = tm.tmDescent;
-    LPtoDP((HDC)desktop_dc, &p, 1);
-    ret->maxDescent = p.y;
-
-    return ret;
-}
-
-jint org::xwt::plat::Win32::_stringWidth(jstring font, jstring text) {
-
-    HFONT hfont = (HFONT)(getFont(font)->hfont);
-    SelectObject((HDC)org::xwt::plat::Win32::desktop_dc, hfont);
-
-    int len = min(1024, JvGetStringUTFLength(text));
-    char buf[len + 1];
-    buf[len] = '\0';
-    JvGetStringUTFRegion(text, 0, len, buf);
-    
-    SIZE size;
-    GetTextExtentPoint32((HDC)org::xwt::plat::Win32::desktop_dc, buf, len, &size);
-    return size.cx;
-}
-
 jboolean org::xwt::plat::Win32::_newBrowserWindow_(jstring url) {
 
     int len = min(2048, JvGetStringUTFLength(url));
@@ -380,7 +353,7 @@ jboolean org::xwt::plat::Win32::_newBrowserWindow_(jstring url) {
 }
 
 
-// Win32DoubleBuffer /////////////////////////////////////////////////////////////////////////
+// Win32PixelBuffer /////////////////////////////////////////////////////////////////////////
 
 // This is a scratch area; when blitting a translucent image, we copy the underlying data here first.
 // Since all drawing operations are single-threaded, it's safe to use a global here.
@@ -390,25 +363,28 @@ static jint* scratch_bits = NULL;
 static jint scratch_w = 0;
 static jint scratch_h = 0;
 
-#define BLT(dest, dx1, dy1, dx2, dy2, src, sx1, sy1, sx2, sy2, op)                                   \
-    if ((dx2 - dx1 == sx2 - sx1) && (dy2 - dy1 == sy2 - sy1))                                        \
-        BitBlt(dest, dx1, dy1, dx2 - dx1, dy2 - dy1, src, sx1, sy1, op);                             \
-    else                                                                                             \
-        StretchBlt(dest, dx1, dy1, dx2 - dx1, dy2 - dy1, src, sx1, sy1, sx2 - sx1, sy2 - sy1, op);
-        
-void org::xwt::plat::Win32$Win32DoubleBuffer::drawPicture(org::xwt::Picture* source0,
-                                                          jint dx1, jint dy1, jint dx2, jint dy2,
-                                                          jint sx1, jint sy1, jint sx2, jint sy2) {
+#define max(a,b) ((a)>(b)?(a):(b))
+#define min(a,b) ((a)<(b)?(a):(b))
 
+void org::xwt::plat::Win32$Win32PixelBuffer::drawPicture(org::xwt::Picture* source0,
+                                                         jint dx, jint dy,
+                                                         jint cx1, jint cy1, jint cx2, jint cy2,
+                                                         jint rgb, jboolean alphaOnly) {
     org::xwt::plat::Win32$Win32Picture* source = (org::xwt::plat::Win32$Win32Picture*)source0;
 
+    cx1 = max(dx, cx1);
+    cy1 = max(dy, cy1);
+    cx2 = min(dx + source->getWidth(), cx2);
+    cy2 = min(dy + source->getHeight(), cy2);
+    if (cx1 >= cx2 || cy1 >= cy2) return; 
+
     if (source->hasalpha) {
 
-        if (scratch == NULL || scratch_w < dx2 - dx1 || scratch_h < dy2 - dy1) {
+        if (scratch == NULL || scratch_w < cx2 - cx1 || scratch_h < cy2 - cy1) {
             if (scratch_dc != NULL) DeleteDC(scratch_dc);
             if (scratch != NULL) DeleteObject(scratch);
-            scratch_w = max(dx2 - dx1, scratch_w);
-            scratch_h = max(dy2 - dy1, scratch_h);
+            scratch_w = max(cx2 - cx1, scratch_w);
+            scratch_h = max(cy2 - cy1, scratch_h);
 
             BITMAPINFO bitmapinfo;
             memset(&bitmapinfo, 0, sizeof(BITMAPINFO));
@@ -426,57 +402,42 @@ void org::xwt::plat::Win32$Win32DoubleBuffer::drawPicture(org::xwt::Picture* sou
         }
 
         // copy from screen to scratch
-        BitBlt((HDC)scratch_dc, 0, 0, dx2 - dx1, dy2 - dy1, (HDC)hdc, dx1, dy1, SRCCOPY);
+        BitBlt((HDC)scratch_dc, 0, 0, cx2 - cx1, cy2 - cy1, (HDC)hdc, cx1, cy1, SRCCOPY);
 
         // apply alpha-blending to scratch
         jint* dat = elements(source->data);
 
-        for(int x = max(clipx1, dx1) - dx1; x < min(clipx2, dx2) - dx1; x++)
-            for(int y = max(clipy1, dy1) - dy1; y < min(clipy2, dy2) - dy1; y++) {
-                int sx = (x * (sx2 - sx1)) / (dx2 - dx1) + sx1;
-                int sy = (y * (sy2 - sy1)) / (dy2 - dy1) + sy1;
-                jint dst = scratch_bits[y * scratch_w + x];
-                jint src = dat[sy * source->getWidth() + sx];
-                jint alpha = (src & 0xFF000000) >> 24;
+        for(int x = cx1; x < cx2; x++)
+            for(int y = cy1; y < cy2; y++) {
+                jint dst = scratch_bits[(y - dy) * scratch_w + (x - dx)];
+
+                // FEATURE: see if we can leverage GDI to do something more clever here with alphaOnly
+                jint src = alphaOnly ? rgb : dat[(y - dy) * source->getWidth() + x - dx];
+                jint alpha = (dat[(y - dy) * source->getWidth() + x - dx] & 0xFF000000) >> 24;
                 jint r = (((src & 0x00FF0000) >> 16) * alpha + ((dst & 0x00FF0000) >> 16) * (0xFF - alpha)) / 0xFF;
                 jint g = (((src & 0x0000FF00) >> 8)  * alpha + ((dst & 0x0000FF00) >> 8)  * (0xFF - alpha)) / 0xFF;
                 jint b = (((src & 0x000000FF))       * alpha + ((dst & 0x000000FF))       * (0xFF - alpha)) / 0xFF;
-                scratch_bits[y * scratch_w + x] = (r << 16) | (g << 8) | b;
+                scratch_bits[(y - dy) * scratch_w + (x - dx)] = (r << 16) | (g << 8) | b;
             }
 
         // copy back from scratch to screen
-        BitBlt((HDC)hdc, dx1, dy1, dx2 - dx1, dy2 - dy1, (HDC)scratch_dc, 0, 0, SRCCOPY);
+        BitBlt((HDC)hdc, cx1, cy1, cx2 - cx1, cy2 - cy1, (HDC)scratch_dc, 0, 0, SRCCOPY);
 
     } else {
+
+        // FIXME: support alphaOnly case here
         if (source->hasmask) {
-            BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->maskdc, sx1, sy1, sx2, sy2, SRCAND);
-            BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->hdc, sx1, sy1, sx2, sy2, SRCPAINT);
+            BitBlt((HDC)hdc, cx1, cy1, cx2 - cx1, cy2 - cy1, (HDC)source->maskdc, cx1 - dx, cy1 - dy, SRCAND);
+            BitBlt((HDC)hdc, cx1, cy1, cx2 - cx1, cy2 - cy1, (HDC)source->hdc, cx1 - dx, cy1 - dy, SRCPAINT);
         } else {
-            BLT((HDC)hdc, dx1, dy1, dx2, dy2, (HDC)source->hdc, sx1, sy1, sx2, sy2, SRCCOPY);
+            BitBlt((HDC)hdc, cx1, cy1, cx2 - cx1, cy2 - cy1, (HDC)source->hdc, cx1 - dx, cy1 - dy, SRCCOPY);
         }
 
     }
 
 }
 
-void org::xwt::plat::Win32$Win32DoubleBuffer::drawString(jstring font, jstring text, jint x, jint y, jint color) {
-
-    org::xwt::plat::Win32$Win32Font* wf = org::xwt::plat::Win32::getFont(font);
-    SelectObject((HDC)hdc, (HFONT)(wf->hfont));
-
-    // Platform API passes us the y-pos of the bottom of the text; we need the top
-    y -= wf->maxAscent;
-
-    int len = min(1024, JvGetStringUTFLength(text));
-    char buf[len + 1];
-    buf[len] = '\0';
-    JvGetStringUTFRegion(text, 0, len, buf);
-
-    SetTextColor((HDC)hdc, PALETTERGB((color & 0xFF0000) >> 16, (color & 0xFF00) >> 8, color & 0xFF));
-    TextOut((HDC)hdc, x, y, buf, len);
-}
-
-void org::xwt::plat::Win32$Win32DoubleBuffer::fillRect(jint x, jint y, jint x2, jint y2, jint color) {
+void org::xwt::plat::Win32$Win32PixelBuffer::fillRect(jint x, jint y, jint x2, jint y2, jint color) {
     jint w = x2 - x;
     jint h = y2 - y;
 
@@ -488,25 +449,20 @@ void org::xwt::plat::Win32$Win32DoubleBuffer::fillRect(jint x, jint y, jint x2,
     DeleteObject(brush);
 }
 
-void org::xwt::plat::Win32$Win32Surface::blit(org::xwt::DoubleBuffer* s, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
-    BitBlt((HDC)hdc, dx, dy, dx2 - dx, dy2 - dy, (HDC)(((org::xwt::plat::Win32$Win32DoubleBuffer*)s)->hdc), sx, sy, SRCCOPY);
+void org::xwt::plat::Win32$Win32Surface::blit(org::xwt::PixelBuffer* s, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
+    // we create the DC lazily to get around some strange race condition in WinXP
+    if (hdc == 0) hdc = (jint)GetDC((HWND)hwnd);
+    BitBlt((HDC)hdc, dx, dy, dx2 - dx, dy2 - dy, (HDC)(((org::xwt::plat::Win32$Win32PixelBuffer*)s)->hdc), sx, sy, SRCCOPY);
 }
 
-void org::xwt::plat::Win32$Win32DoubleBuffer::natInit() {
+void org::xwt::plat::Win32$Win32PixelBuffer::natInit() {
     hbitmap = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
     hdc = (jint)CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
     SetBkMode((HDC)hdc, TRANSPARENT);
     SelectObject((HDC)hdc, (HBITMAP)hbitmap);
 }
 
-void org::xwt::plat::Win32$Win32DoubleBuffer::setClip(jint x, jint y, jint x2, jint y2) {
-    clipx1 = x; clipx2 = x2; clipy1 = y; clipy2 = y2;
-    HRGN hrgn = CreateRectRgn(x, y, x2, y2);
-    SelectClipRgn((HDC)hdc, hrgn);
-    DeleteObject(hrgn);
-}
-
-void org::xwt::plat::Win32$Win32DoubleBuffer::finalize() {
+void org::xwt::plat::Win32$Win32PixelBuffer::finalize() {
     DeleteObject((void*)hdc);
     DeleteObject((void*)hbitmap);
 }
@@ -520,18 +476,18 @@ void org::xwt::plat::Win32$Win32Picture::natInit() {
     BITMAPINFO bitmapinfo;
     memset(&bitmapinfo, 0, sizeof(BITMAPINFO));
     bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
-    bitmapinfo.bmiHeader.biWidth = w;
-    bitmapinfo.bmiHeader.biHeight = -1 * h;
+    bitmapinfo.bmiHeader.biWidth = width;
+    bitmapinfo.bmiHeader.biHeight = -1 * height;
     bitmapinfo.bmiHeader.biPlanes = 1;
     bitmapinfo.bmiHeader.biBitCount = 32;
     bitmapinfo.bmiHeader.biCompression = BI_RGB;
 
-    hbitmap = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
+    hbitmap = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, width, height);
     hdc = (jint)CreateCompatibleDC((HDC)org::xwt::plat::Win32::desktop_dc);
     SelectObject((HDC)hdc, (HBITMAP)hbitmap);
     uint32_t* dat = (uint32_t*)elements(data);
     for(int i=0; i<data->length; i++) if ((dat[i] & 0xFF000000) == 0x00000000) dat[i] = 0x00000000;
-    StretchDIBits((HDC)hdc, 0, 0, w, h, 0, 0, w, h, elements(data), &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
+    StretchDIBits((HDC)hdc, 0, 0, width, height, 0, 0, width, height, elements(data), &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
 
     jint _copy[min(1024, data->length)];
     jint* copy = data->length > 1024 ? (jint*)malloc(data->length * 4) : _copy;
@@ -556,10 +512,10 @@ void org::xwt::plat::Win32$Win32Picture::natInit() {
     }
 
     //    hmask = (jint)CreateBitmap(w, h, 1, 1, NULL);
-    hmask = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, w, h);
+    hmask = (jint)CreateCompatibleBitmap((HDC)org::xwt::plat::Win32::desktop_dc, width, height);
     maskdc = (jint)CreateCompatibleDC(NULL);
     SelectObject((HDC)maskdc, (HBITMAP)hmask);
-    StretchDIBits((HDC)maskdc, 0, 0, w, h, 0, 0, w, h, copy, &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
+    StretchDIBits((HDC)maskdc, 0, 0, width, height, 0, 0, width, height, copy, &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);
     if (data->length > 1024) free(copy);
 }
 
@@ -578,7 +534,6 @@ void org::xwt::plat::Win32$Win32Surface::natInit(jboolean framed) {
     // GC_enable_incremental();
 
     ShowWindow ((HWND)hwnd, SW_SHOWDEFAULT);
-    hdc = (jint)GetDC((HWND)hwnd);
 }
 
 void org::xwt::plat::Win32$Win32Surface::finalize() { /* DeleteObject((void*)hwnd); */ }
@@ -590,23 +545,23 @@ void org::xwt::plat::Win32$Win32Surface::_setMinimized(jboolean m) { ShowWindow(
 void org::xwt::plat::Win32$Win32Surface::_setMaximized(jboolean m) { ShowWindow((HWND)hwnd, m ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL); }
 void org::xwt::plat::Win32$Win32Surface::postCursorChange() { PostMessage((HWND)hwnd, WM_USER_SETCURSOR, 0, 0); }
 
-void org::xwt::plat::Win32$Win32Surface::setLocation(jint x, jint y) {
+void org::xwt::plat::Win32$Win32Surface::setLocation() {
     POINT point;
     RECT rect;
     point.x = 0;
     point.y = 0;
     ClientToScreen((HWND)hwnd, &point);
     GetWindowRect((HWND)hwnd, &rect);
-    SetWindowPos((HWND)hwnd, NULL, x - (point.x - rect.left), y - (point.y - rect.top), 0, 0, SWP_NOZORDER | SWP_NOSIZE);
+    SetWindowPos((HWND)hwnd, NULL, root->x - (point.x - rect.left), root->y - (point.y - rect.top), 0, 0, SWP_NOZORDER | SWP_NOSIZE);
 }
 
-void org::xwt::plat::Win32$Win32Surface::setSize(jint w, jint h) {
+void org::xwt::plat::Win32$Win32Surface::_setSize(jint w, jint h) {
     RECT client_rect, window_rect;
     GetClientRect((HWND)hwnd, &client_rect);
     GetWindowRect((HWND)hwnd, &window_rect);
-    int addwidth = (window_rect.right - window_rect.left) - (client_rect.right - client_rect.left);
-    int addheight = (window_rect.bottom - window_rect.top) - (client_rect.bottom - client_rect.top);
-    SetWindowPos((HWND)hwnd, NULL, 0, 0, w + addwidth, h + addheight, SWP_NOZORDER | SWP_NOMOVE);
+    int width = (window_rect.right - window_rect.left) - (client_rect.right - client_rect.left) + w;
+    int height = (window_rect.bottom - window_rect.top) - (client_rect.bottom - client_rect.top) + h;
+    SetWindowPos((HWND)hwnd, NULL, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE);
 }
 
 void org::xwt::plat::Win32$Win32Surface::setTitleBarText(java::lang::String* title) {
@@ -623,11 +578,14 @@ void org::xwt::plat::Win32$Win32Surface::setIcon(org::xwt::Picture* p0) {
     int icon_width = GetSystemMetrics(SM_CXSMICON);
     int icon_height = GetSystemMetrics(SM_CYSMICON);
 
+    // we create the DC lazily to get around some strange race condition in WinXP
+    if (hdc == 0) hdc = (jint)GetDC((HWND)hwnd);
+
     // create the bitmap
     HBITMAP bit = CreateCompatibleBitmap((HDC)hdc, icon_width, icon_height);
     HDC memdc = CreateCompatibleDC((HDC)hdc);
     SelectObject(memdc, bit);
-    BLT((HDC)memdc, 0, 0, icon_width, icon_height, (HDC)(p->hdc), 0, 0, p->getWidth(), p->getHeight(), SRCCOPY);
+    BitBlt((HDC)memdc, 0, 0, icon_width, icon_height, (HDC)(p->hdc), 0, 0, SRCCOPY);
 
     // create the mask
     jint* dat = elements(p->data);
@@ -660,17 +618,19 @@ jint org::xwt::plat::Win32$Win32Surface::WndProc(jint _hwnd, jint _iMsg, jint _w
 
     int oldmousex, oldmousey;
     MINMAXINFO* mmi;
+    int resizable;
     POINT point;
     HWND hwnd2;
     RECT rect, rect2;
+    RECT client_rect, window_rect;
     jboolean newinside;
     int16_t mouse_x;
     int16_t mouse_y;
+    int addwidth, addheight;
 
     switch(iMsg) {
     case WM_DEVMODECHANGE: break;    // FEATURE: color depth changed
     case WM_DISPLAYCHANGE: break;    // FEATURE: screen size changed
-    case WM_FONTCHANGE: break;       // FEATURE: set of fonts changed
     case WM_MOUSEWHEEL: break;       // FEATURE: Mouse Wheel
 
     case WM_SYSKEYDOWN: if (GetKeyState(VK_MENU) >> (sizeof(SHORT) * 8 - 1) == 0) return 0;
@@ -772,11 +732,16 @@ jint org::xwt::plat::Win32$Win32Surface::WndProc(jint _hwnd, jint _iMsg, jint _w
         return 0;
 
     case WM_GETMINMAXINFO:
+        GetClientRect((HWND)hwnd, &client_rect);
+        GetWindowRect((HWND)hwnd, &window_rect);
+        addwidth = (window_rect.right - window_rect.left) - (client_rect.right - client_rect.left);
+        addheight = (window_rect.bottom - window_rect.top) - (client_rect.bottom - client_rect.top);
         mmi = (MINMAXINFO*)lParam;
-        mmi->ptMinTrackSize.x = root->dmin(0);
-        mmi->ptMinTrackSize.y = root->dmin(1);
-        mmi->ptMaxTrackSize.x = root->dmax(0);
-        mmi->ptMaxTrackSize.y = root->dmax(1);
+        mmi->ptMinTrackSize.x = ((uint32_t)root->minwidth) + addwidth;
+        mmi->ptMinTrackSize.y = ((uint32_t)root->minheight) + addheight;
+        resizable = !((root->minwidth == root->maxwidth) && (root->minheight == root->maxheight));
+        mmi->ptMaxTrackSize.x = resizable ? org::xwt::plat::Win32::getScreenWidth() : mmi->ptMinTrackSize.x;
+        mmi->ptMaxTrackSize.y = resizable ? org::xwt::plat::Win32::getScreenHeight() : mmi->ptMinTrackSize.y;
         return 0;
         
     case WM_PAINT: 
@@ -797,13 +762,13 @@ jint org::xwt::plat::Win32$Win32Surface::WndProc(jint _hwnd, jint _iMsg, jint _w
 
 static char keyarr [256] = { 0 };
 static jstring keyToString(WPARAM wParam) {
-    char arr[4];
+    char arr[8];
     keyarr[VK_CAPITAL] = GetKeyState(VK_CAPITAL);
     keyarr[VK_LSHIFT] = GetKeyState(VK_LSHIFT);
     keyarr[VK_RSHIFT] = GetKeyState(VK_RSHIFT);
     keyarr[VK_SHIFT] = GetKeyState(VK_SHIFT);
-    
-    if (ToAscii(wParam, 0, (BYTE*)keyarr, (WORD*)arr, 0) == 1) {
+
+    if (ToAsciiEx(wParam, 0, (BYTE*)keyarr, (WORD*)arr, 0, GetKeyboardLayout(0)) == 1) {
         switch (arr[0]) {
         case '\t': return JvNewStringLatin1("tab");
         case 0x1b: return JvNewStringLatin1("escape");
@@ -861,317 +826,3 @@ static jstring keyToString(WPARAM wParam) {
     }
     return NULL;
 }
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////
-
-#else /* COMPILE_DLL */
-
-
-//
-// A simple DLL to invoke xwt.exe and pass it any arguments found in the <object/> tag
-//
-
-#include <windows.h>
-#include <initguid.h>
-#include <objbase.h>
-#include <oaidl.h>
-#include <oleauto.h>
-#include <olectl.h>
-
-
-// Globals ////////////////////////////////////////////////////////////////////////
-
-using namespace std;
-
-#define CLSID_STRING_SIZE 39
-
-const char XWT_friendlyName[] = "XWT ActiveX Control (build " BUILDID ")";
-const char XWT_versionIndependantProgramID[] = "XWT.ActiveX";
-const char XWT_programID[] = "XWT.ActiveX (build " BUILDID ")";
-extern "C" const CLSID XWT_clsid = CLSID_STRUCT;
-static HMODULE g_hModule = NULL;    //DLL handle
-
-
-
-
-// Superclasses ////////////////////////////////////////////////////////////////////////
-
-// Option bit definitions for IObjectSafety:
-#define INTERFACESAFE_FOR_UNTRUSTED_CALLER  0x00000001  // Caller of interface may be untrusted
-#define INTERFACESAFE_FOR_UNTRUSTED_DATA    0x00000002  // Data passed into interface may be untrusted
-
-// {CB5BDC81-93C1-11cf-8F20-00805F2CD064}
-DEFINE_GUID(IID_IObjectSafety, 0xcb5bdc81, 0x93c1, 0x11cf, 0x8f, 0x20, 0x0, 0x80, 0x5f, 0x2c, 0xd0, 0x64);
-
-interface IObjectSafety : public IUnknown {
- public:
-    virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD __RPC_FAR *pdwSupportedOptions, DWORD __RPC_FAR *pdwEnabledOptions) = 0;
-    virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions) = 0;
-};
-
-interface IShoeHorn : IPersistPropertyBag, IObjectSafety { };
-
-
-
-// Entry Points ////////////////////////////////////////////////////////////////////////
-
-// to get mingw to stop nagging me
-int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { }
-
-// determines whether or not the DLL can be unloaded; always allow this since we don't do too much
-STDAPI __declspec(dllexport) DllCanUnloadNow(void) { return S_OK; }
-
-extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID /*lpReserved*/) {
-    if (dwReason == DLL_PROCESS_ATTACH) g_hModule = (HINSTANCE)hModule;
-    return TRUE;
-}
-
-
-
-// Other ///////////////////////////////////////////////////////////////////////////////////
-
-// simple assert() replacement that pops open a message box if there are errors
-void check(int val, char* message) {
-    if (!val) {
-        MessageBox (NULL, message, "XWT Critical Abort", MB_OK | MB_ICONSTOP | MB_TASKMODAL | MB_SETFOREGROUND);
-        exit(-1);
-    }
-}
-
-void clsidToString(const CLSID& clsid, char* str, int length) {
-    check(length >= CLSID_STRING_SIZE, "clsidToString(): string too short");
-       LPOLESTR wide_str = NULL;
-       HRESULT hr = StringFromCLSID(clsid, &wide_str);
-       check(SUCCEEDED(hr), "StringFromCLSID() failed in clsidToString()");
-       wcstombs(str, wide_str, length);
-       CoTaskMemFree(wide_str);
-}
-
-void setRegistryKey(const char* key, const char* subkey, const char* value) {
-       HKEY hKey;
-       char keyBuf[1024];
-       strcpy(keyBuf, key);
-       if (subkey != NULL) {
-               strcat(keyBuf, "\\");
-               strcat(keyBuf, subkey );
-       }
-       long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, keyBuf, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
-       if (value != NULL)
-        check(RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)value, strlen(value) + 1) == ERROR_SUCCESS,
-              "RegSetValueEx() failed in setRegistryKey()");
-       RegCloseKey(hKey);
-}
-
-void deleteRegistryKey(HKEY parent, const char* target) {
-       HKEY hKeyChild;
-       RegOpenKeyEx(parent, target, 0, KEY_ALL_ACCESS, &hKeyChild);
-
-       // Iterate over children, deleting them
-       FILETIME time;
-       char szBuffer[256];
-       DWORD dwSize = 256;
-       while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time) == S_OK) {
-               deleteRegistryKey(hKeyChild, szBuffer);
-               dwSize = 256;
-       }
-
-       RegCloseKey(hKeyChild);
-       RegDeleteKey(parent, target);
-}
-
-STDAPI __declspec(dllexport) DllRegisterServer(void) {
-       char moduleName[512];
-    HRESULT result = GetModuleFileName(g_hModule, moduleName, sizeof(moduleName)/sizeof(char));
-       check(result, "GetModuleFileName() failed in RegisterServer()");
-
-       char clsidString[CLSID_STRING_SIZE];
-       clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
-
-       // build the key
-       char key[64];
-       strcpy(key, "CLSID\\");
-       strcat(key, clsidString);
-  
-       setRegistryKey(key, NULL, XWT_friendlyName);
-       setRegistryKey(key, "InprocServer32", moduleName);
-       setRegistryKey(key, "ProgID", XWT_programID);
-       setRegistryKey(key, "VersionIndependentProgID", XWT_versionIndependantProgramID);
-       setRegistryKey(XWT_versionIndependantProgramID, NULL, XWT_friendlyName); 
-       setRegistryKey(XWT_versionIndependantProgramID, "CLSID", clsidString);
-       setRegistryKey(XWT_versionIndependantProgramID, "CurVer", XWT_programID);
-       setRegistryKey(XWT_programID, NULL, XWT_friendlyName); 
-       setRegistryKey(XWT_programID, "CLSID", clsidString);
-       return S_OK;
-}
-
-STDAPI __declspec(dllexport) DllUnregisterServer(void) {
-       char clsidString[CLSID_STRING_SIZE];
-       clsidToString(XWT_clsid, clsidString, sizeof(clsidString));
-
-       // build the key
-       char key[64];
-       strcpy(key, "CLSID\\");
-       strcat(key, clsidString);
-
-       deleteRegistryKey(HKEY_CLASSES_ROOT, key);
-       deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_versionIndependantProgramID);
-       deleteRegistryKey(HKEY_CLASSES_ROOT, XWT_programID);
-       return S_OK;
-}
-
-
-
-// ShoeHorn //////////////////////////////////////////////////////////////////////////////////
-
-class ShoeHorn : public IShoeHorn {
-    public:
-    virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
-        if(iid == IID_IUnknown) *ppv = static_cast<IShoeHorn*>(this);
-        else if(iid == XWT_clsid) *ppv = static_cast<IShoeHorn*>(this);
-        else if(iid == IID_IPersistPropertyBag) *ppv = static_cast<IPersistPropertyBag*>(this);
-        else if(iid == IID_IObjectSafety) *ppv = static_cast<IObjectSafety*>(this);
-        else { *ppv = NULL; return E_NOINTERFACE; }
-        reinterpret_cast<IUnknown*>(*ppv)->AddRef();
-        return S_OK;
-    }
-    virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
-    virtual ULONG __stdcall Release() {
-        if(InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; }
-        return m_cRef;
-    }
-    virtual HRESULT __stdcall GetClassID(CLSID*) { return S_OK; }
-    virtual HRESULT __stdcall InitNew() { return S_OK; }
-    virtual HRESULT __stdcall Save(IPropertyBag*, int, int) { return S_OK; }
-    virtual HRESULT __stdcall SetInterfaceSafetyOptions(REFIID riid, DWORD pdwSupportedOptions, DWORD pdwEnabledOptions) { return S_OK; }
-    virtual HRESULT __stdcall GetInterfaceSafetyOptions(REFIID riid, DWORD* pdwSupportedOptions, DWORD* pdwEnabledOptions) {
-        if (pdwSupportedOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
-        if (pdwEnabledOptions != NULL) *pdwSupportedOptions |= INTERFACESAFE_FOR_UNTRUSTED_DATA;
-        return S_OK;
-    }
-
-    virtual HRESULT __stdcall Load(IPropertyBag* pPropBag, IErrorLog* pErrorLog) {
-        VARIANT v;
-        v.vt = VT_BSTR;
-        HRESULT hrRead;
-        
-        WCHAR wc[100];
-        char url[100];
-        
-        MultiByteToWideChar(CP_ACP, 0, "initial-xwar-url", -1, wc, 100);
-        pPropBag->Read(wc, &v, pErrorLog);
-        check(WideCharToMultiByte(CP_ACP, 0, v.bstrVal, -1, url, 100, NULL, NULL),
-              "WideCharToMultiByte() failed in ShoeHorn::Load()");
-        
-        HKEY hkey;
-        LONG result = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ActiveX Cache", &hkey);
-        check(result == ERROR_SUCCESS, "RegOpenKey() failed in ShoeHorn::Load()");
-        
-        // iterate over all the activex cache locations until we find ourselves
-        for(int i=0; i<9; i++) {
-            DWORD buflen = 999;
-            char buf[1000];
-            VALENT valents[20];
-            DWORD type;
-            char which[2];
-
-            which[0] = '0' + i;
-            which[1] = '\0';
-            result = RegQueryValueEx(hkey, which, NULL, &type, (BYTE*)buf, &buflen);
-            if (result != ERROR_SUCCESS)
-                if (i == 0) {
-                    check(0, "RegQueryValueEx() failed in ShoeHorn::Load()");
-                } else {
-                    break;
-                }
-            buf[buflen] = '\0';
-            
-            char cmdline[200];
-            for(int i=0; i<200; i++) cmdline[i] = '\0';
-            strncpy(cmdline, buf, 200);
-            strncpy(cmdline + strlen(cmdline), "\\xwt-" BUILDID ".exe", 200 - strlen(cmdline));
-            strncpy(cmdline + strlen(cmdline), " ", 200 - strlen(cmdline));
-            strncpy(cmdline + strlen(cmdline), url, 200 - strlen(cmdline));
-            
-            PROCESS_INFORMATION pInfo;
-            STARTUPINFO sInfo;
-            sInfo.cb = sizeof(STARTUPINFO);
-            sInfo.lpReserved = NULL;
-            sInfo.lpReserved2 = NULL;
-            sInfo.cbReserved2 = 0;
-            sInfo.lpDesktop = NULL;
-            sInfo.lpTitle = NULL;
-            sInfo.dwFlags = 0;
-            sInfo.dwX = 0;
-            sInfo.dwY = 0;
-            sInfo.dwFillAttribute = 0;
-            sInfo.wShowWindow = SW_SHOW;
-            BOOL b = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo);
-            if (b) return S_OK;
-        }
-
-        check(0, "unable to locate xwt-" BUILDID ".exe in ActiveX cache folders");
-    }
-
-    ShoeHorn() : m_cRef(1) { };
-    ~ShoeHorn() { };
-    private: long m_cRef;
-};
-
-
-
-
-// ClassFactory //////////////////////////////////////////////////////////////////////////
-
-class ClassFactory : public IClassFactory {
-    public:
-    virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) {
-        if(iid == IID_IUnknown) *ppv = static_cast<IClassFactory*>(this);
-        else if(iid == IID_IClassFactory) *ppv = static_cast<IClassFactory*>(this);
-        else {
-            *ppv = NULL;
-            return E_NOINTERFACE;
-        }
-        reinterpret_cast<IUnknown*>(*ppv)->AddRef();
-        return S_OK;
-    }
-
-    ClassFactory() : m_cRef(1) { }
-    ~ClassFactory() { }
-    virtual HRESULT __stdcall LockServer(BOOL bLock) { return S_OK; }
-    virtual ULONG __stdcall AddRef() { return InterlockedIncrement(&m_cRef); }
-    virtual ULONG __stdcall Release() {
-        if(InterlockedDecrement(&m_cRef) == 0) {
-            delete this;
-            return 0;
-        }
-        return m_cRef;
-    }
-
-    virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) {
-        if(pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION;
-        ShoeHorn* s = new ShoeHorn;
-        if(s == NULL) return E_OUTOFMEMORY;
-        HRESULT hr = s->QueryInterface(iid, ppv);
-        s->Release();
-        return hr;
-    }
-    
-    private: long m_cRef;
-};
-
-
-extern "C" __stdcall HRESULT DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) {
-    if(clsid != XWT_clsid) return CLASS_E_CLASSNOTAVAILABLE;
-    ClassFactory* pFactory = new ClassFactory; 
-    if(pFactory == NULL) return E_OUTOFMEMORY;
-    HRESULT hr = pFactory->QueryInterface(iid, ppv);
-    pFactory->Release();
-    return hr;
-}
-
-#endif