set most of trunk svn property eol-style:native
[reactos.git] / reactos / base / applications / imagesoft / imgedwnd.c
index 340f025..8d8161b 100644 (file)
-#include <precomp.h>\r
-\r
-static const TCHAR szImageEditWndClass[] = TEXT("ImageSoftEditWndClass");\r
-\r
-#define IMAGE_FRAME_SIZE    1\r
-\r
-\r
-static VOID\r
-EditWndUpdateScrollInfo(PEDIT_WND_INFO Info)\r
-{\r
-    SCROLLINFO si;\r
-    RECT rcClient;\r
-\r
-    GetClientRect(Info->hSelf,\r
-                  &rcClient);\r
-\r
-    si.cbSize = sizeof(si);\r
-    si.fMask = SIF_PAGE | SIF_RANGE;\r
-    si.nPage = rcClient.right - (2 * IMAGE_FRAME_SIZE);\r
-    si.nMin = 0;\r
-    si.nMax = Info->Width;\r
-\r
-    SetScrollInfo(Info->hSelf,\r
-                  SB_HORZ,\r
-                  &si,\r
-                  TRUE);\r
-\r
-    si.nPage = rcClient.bottom - (2 * IMAGE_FRAME_SIZE);\r
-    si.nMax = Info->Height;\r
-    SetScrollInfo(Info->hSelf,\r
-                  SB_VERT,\r
-                  &si,\r
-                  TRUE);\r
-}\r
-\r
-static BOOL\r
-InitEditWnd(PEDIT_WND_INFO Info)\r
-{\r
-    BITMAPFILEHEADER bmfh;\r
-    PBITMAPINFO pbmi = NULL;\r
-    PBYTE pBits;\r
-    HANDLE hFile;\r
-    BITMAP bitmap;\r
-\r
-    Info->Zoom = 100;\r
-\r
-    if (Info->OpenInfo != NULL)\r
-    {\r
-        HDC hDC = GetDC(Info->hSelf);\r
-        Info->hDCMem = CreateCompatibleDC(hDC);\r
-        ReleaseDC(Info->hSelf, hDC);\r
-\r
-        if (Info->OpenInfo->CreateNew)\r
-        {\r
-            /* FIXME: convert this to a DIB Section */\r
-            /* set bitmap dimensions */\r
-            Info->Width = Info->OpenInfo->New.Width;\r
-            Info->Height = Info->OpenInfo->New.Height;\r
-\r
-        }\r
-        else\r
-        {\r
-            DWORD InfoSize, BytesRead;\r
-            BOOL bSuccess;\r
-\r
-            hFile = CreateFile(Info->OpenInfo->Open.lpImagePath,\r
-                               GENERIC_READ,\r
-                               FILE_SHARE_READ,\r
-                               NULL,\r
-                               OPEN_EXISTING,\r
-                               FILE_FLAG_SEQUENTIAL_SCAN,\r
-                               NULL);\r
-            if (hFile == INVALID_HANDLE_VALUE)\r
-                return FALSE;\r
-\r
-            bSuccess = ReadFile(hFile,\r
-                                &bmfh,\r
-                                sizeof(BITMAPFILEHEADER),\r
-                                &BytesRead,\r
-                                NULL);\r
-\r
-            if ( bSuccess && (BytesRead == sizeof(BITMAPFILEHEADER))\r
-                            /* FIXME: Why is this failing?? */\r
-                          /*&& (bmfh.bfType == *(WORD *)_T("BM"))*/)\r
-            {\r
-                InfoSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);\r
-\r
-                pbmi = HeapAlloc(ProcessHeap,\r
-                                 0,\r
-                                 InfoSize);\r
-\r
-                bSuccess = ReadFile(hFile,\r
-                                    pbmi,\r
-                                    InfoSize,\r
-                                    &BytesRead,\r
-                                    NULL);\r
-\r
-                if (bSuccess && (BytesRead == InfoSize))\r
-                {\r
-                    Info->hBitmap = CreateDIBSection(NULL,\r
-                                                     pbmi,\r
-                                                     DIB_RGB_COLORS,\r
-                                                     (VOID *)&pBits,\r
-                                                     NULL,\r
-                                                     0);\r
-                    if (Info->hBitmap != NULL)\r
-                    {\r
-                        ReadFile(hFile,\r
-                                 pBits,\r
-                                 bmfh.bfSize - bmfh.bfOffBits,\r
-                                 &BytesRead,\r
-                                 NULL);\r
-                    }\r
-                    else\r
-                    {\r
-                        goto fail;\r
-                    }\r
-                }\r
-                else\r
-                {\r
-                    goto fail;\r
-                }\r
-            }\r
-            else\r
-            {\r
-                if (! bSuccess)\r
-                    GetError(0);\r
-\r
-                goto fail;\r
-            }\r
-\r
-            CloseHandle(hFile);\r
-\r
-            HeapFree(ProcessHeap,\r
-                     0,\r
-                     pbmi);\r
-        }\r
-\r
-        Info->OpenInfo = NULL;\r
-    }\r
-\r
-    /* get bitmap dimensions */\r
-    GetObject(Info->hBitmap,\r
-                  sizeof(BITMAP),\r
-                  &bitmap);\r
-\r
-    Info->Width = bitmap.bmWidth;\r
-    Info->Height = bitmap.bmHeight;\r
-\r
-    EditWndUpdateScrollInfo(Info);\r
-\r
-    /* Add image editor to the list */\r
-    Info->Next = Info->MainWnd->ImageEditors;\r
-    Info->MainWnd->ImageEditors = Info;\r
-\r
-    InvalidateRect(Info->hSelf,\r
-                   NULL,\r
-                   TRUE);\r
-\r
-    /* FIXME - if returning FALSE, remove the image editor from the list! */\r
-    return TRUE;\r
-\r
-\r
-fail:\r
-    if (! hFile)\r
-        CloseHandle(hFile);\r
-\r
-    if (! pbmi)\r
-        HeapFree(ProcessHeap,\r
-                 0,\r
-                 pbmi);\r
-\r
-    return FALSE;\r
-}\r
-\r
-static VOID\r
-DestroyEditWnd(PEDIT_WND_INFO Info)\r
-{\r
-    PEDIT_WND_INFO *PrevEditor;\r
-    PEDIT_WND_INFO Editor;\r
-\r
-    DeleteDC(Info->hDCMem);\r
-\r
-    /* FIXME - free resources and run down editor */\r
-\r
-    /* Remove the image editor from the list */\r
-    PrevEditor = &Info->MainWnd->ImageEditors;\r
-    Editor = Info->MainWnd->ImageEditors;\r
-    do\r
-    {\r
-        if (Editor == Info)\r
-        {\r
-            *PrevEditor = Info->Next;\r
-            break;\r
-        }\r
-        PrevEditor = &Editor->Next;\r
-        Editor = Editor->Next;\r
-    } while (Editor != NULL);\r
-}\r
-\r
-static VOID\r
-ImageEditWndRepaint(PEDIT_WND_INFO Info,\r
-                    HDC hDC,\r
-                    LPPAINTSTRUCT lpps)\r
-{\r
-    HBITMAP hOldBitmap;\r
-\r
-    if (Info->hBitmap)\r
-    {\r
-        hOldBitmap = (HBITMAP) SelectObject(Info->hDCMem,\r
-                                            Info->hBitmap);\r
-\r
-        BitBlt(hDC,\r
-               lpps->rcPaint.left,\r
-               lpps->rcPaint.top,\r
-               lpps->rcPaint.right - lpps->rcPaint.left,\r
-               lpps->rcPaint.bottom - lpps->rcPaint.top,\r
-               Info->hDCMem,\r
-               lpps->rcPaint.left,\r
-               lpps->rcPaint.top,\r
-               SRCCOPY);\r
-\r
-        Info->hBitmap = SelectObject(Info->hDCMem, hOldBitmap);\r
-    }\r
-}\r
-\r
-static LRESULT CALLBACK\r
-ImageEditWndProc(HWND hwnd,\r
-                 UINT uMsg,\r
-                 WPARAM wParam,\r
-                 LPARAM lParam)\r
-{\r
-    PEDIT_WND_INFO Info;\r
-    LRESULT Ret = 0;\r
-    HDC hDC;\r
-    static INT xMouse, yMouse;\r
-    static BOOL bLeftButtonDown, bRightButtonDown;\r
-\r
-    /* Get the window context */\r
-    Info = (PEDIT_WND_INFO)GetWindowLongPtr(hwnd,\r
-                                            GWLP_USERDATA);\r
-    if (Info == NULL && uMsg != WM_CREATE)\r
-    {\r
-        goto HandleDefaultMessage;\r
-    }\r
-\r
-    switch (uMsg)\r
-    {\r
-        case WM_CREATE:\r
-        {\r
-            Info = (PEDIT_WND_INFO)(((LPMDICREATESTRUCT)((LPCREATESTRUCT)lParam)->lpCreateParams)->lParam);\r
-            Info->hSelf = hwnd;\r
-\r
-            SetWindowLongPtr(hwnd,\r
-                             GWLP_USERDATA,\r
-                             (LONG_PTR)Info);\r
-\r
-            if (!InitEditWnd(Info))\r
-            {\r
-                Ret = (LRESULT)-1;\r
-                break;\r
-            }\r
-            break;\r
-        }\r
-\r
-        case WM_ERASEBKGND:\r
-            if (Info->Width != 0 && Info->Height != 0)\r
-            {\r
-                Ret = TRUE;\r
-            }\r
-            break;\r
-\r
-        case WM_LBUTTONDOWN:\r
-            if (! bRightButtonDown)\r
-                SetCapture(Info->hSelf);\r
-\r
-            bLeftButtonDown = TRUE;\r
-            xMouse = LOWORD(lParam);\r
-            yMouse = HIWORD(lParam);\r
-\r
-            SetCursor(LoadCursor(hInstance,\r
-                                 MAKEINTRESOURCE(IDC_PAINTBRUSHCURSORMOUSEDOWN)));\r
-        break;\r
-\r
-        case WM_LBUTTONUP:\r
-            if (bLeftButtonDown)\r
-                SetCapture(NULL);\r
-\r
-            bLeftButtonDown = FALSE;\r
-\r
-        break;\r
-\r
-        case WM_RBUTTONDOWN:\r
-            if (! bLeftButtonDown)\r
-                SetCapture(Info->hSelf);\r
-\r
-            bRightButtonDown = TRUE;\r
-            xMouse = LOWORD(lParam);\r
-            yMouse = HIWORD(lParam);\r
-\r
-            SetCursor(LoadCursor(hInstance,\r
-                                 MAKEINTRESOURCE(IDC_PAINTBRUSHCURSORMOUSEDOWN)));\r
-        break;\r
-\r
-        case WM_RBUTTONUP:\r
-            if (bRightButtonDown)\r
-                SetCapture(NULL);\r
-\r
-            bRightButtonDown = FALSE;\r
-\r
-        break;\r
-\r
-        case WM_MOUSEMOVE:\r
-        {\r
-            HPEN hPen, hPenOld;\r
-\r
-            if (!bLeftButtonDown && !bRightButtonDown)\r
-                break;\r
-\r
-            hDC = GetDC(Info->hSelf);\r
-\r
-            SelectObject(Info->hDCMem,\r
-                         Info->hBitmap);\r
-\r
-            if (bLeftButtonDown)\r
-                hPen = CreatePen(PS_SOLID,\r
-                                 3,\r
-                                 RGB(0, 0, 0));\r
-            else\r
-                hPen = CreatePen(PS_SOLID,\r
-                                 3,\r
-                                 RGB(255, 255, 255));\r
-\r
-            hPenOld = SelectObject(hDC,\r
-                                   hPen);\r
-\r
-            MoveToEx(hDC,\r
-                     xMouse,\r
-                     yMouse,\r
-                     NULL);\r
-\r
-            MoveToEx(Info->hDCMem,\r
-                     xMouse,\r
-                     yMouse,\r
-                     NULL);\r
-\r
-            xMouse = (short)LOWORD(lParam);\r
-            yMouse = (short)HIWORD(lParam);\r
-\r
-            LineTo(hDC,\r
-                   xMouse,\r
-                   yMouse);\r
-\r
-            LineTo(Info->hDCMem,\r
-                   xMouse,\r
-                   yMouse);\r
-\r
-            DeleteObject(SelectObject(hDC,\r
-                                      hPenOld));\r
-\r
-            ReleaseDC(Info->hSelf,\r
-                      hDC);\r
-        }\r
-        break;\r
-\r
-        case WM_PAINT:\r
-        {\r
-            if (Info->Width != 0 && Info->Height != 0)\r
-            {\r
-                PAINTSTRUCT ps;\r
-                HDC hDC;\r
-\r
-                hDC = BeginPaint(hwnd,\r
-                                 &ps);\r
-                if (hDC != NULL)\r
-                {\r
-                    ImageEditWndRepaint(Info,\r
-                                        hDC,\r
-                                        &ps);\r
-\r
-                    EndPaint(hwnd,\r
-                             &ps);\r
-                }\r
-            }\r
-            break;\r
-        }\r
-\r
-        case WM_SIZE:\r
-        {\r
-            EditWndUpdateScrollInfo(Info);\r
-            goto HandleDefaultMessage;\r
-        }\r
-\r
-        case WM_MENUSELECT:\r
-        case WM_ENTERMENULOOP:\r
-        case WM_EXITMENULOOP:\r
-            /* forward these messages to the main window procedure */\r
-            Ret = SendMessage(Info->MainWnd->hSelf,\r
-                              uMsg,\r
-                              wParam,\r
-                              lParam);\r
-            break;\r
-\r
-        case WM_MDIACTIVATE:\r
-            /* Switch the main window context if neccessary */\r
-            MainWndSwitchEditorContext(Info->MainWnd,\r
-                                       (HWND)wParam,\r
-                                       (HWND)lParam);\r
-            break;\r
-\r
-        case WM_DESTROY:\r
-        {\r
-            DestroyEditWnd(Info);\r
-\r
-            HeapFree(ProcessHeap,\r
-                     0,\r
-                     Info);\r
-            SetWindowLongPtr(hwnd,\r
-                             GWLP_USERDATA,\r
-                             0);\r
-            break;\r
-        }\r
-\r
-        default:\r
-HandleDefaultMessage:\r
-            Ret = DefMDIChildProc(hwnd,\r
-                                  uMsg,\r
-                                  wParam,\r
-                                  lParam);\r
-            break;\r
-    }\r
-\r
-    return Ret;\r
-}\r
-\r
-VOID\r
-SetImageEditorEnvironment(PEDIT_WND_INFO Info,\r
-                          BOOL Setup)\r
-{\r
-    if (Setup)\r
-    {\r
-        /* FIXME - setup editor environment (e.g. show toolbars, enable menus etc) */\r
-    }\r
-    else\r
-    {\r
-        /* FIXME - cleanup editor environment (e.g. hide toolbars, disable menus etc) */\r
-    }\r
-}\r
-\r
-BOOL\r
-CreateImageEditWindow(struct _MAIN_WND_INFO *MainWnd,\r
-                      POPEN_IMAGE_EDIT_INFO OpenInfo)\r
-{\r
-    PEDIT_WND_INFO Info;\r
-    HWND hWndEditor;\r
-    LONG Width, Height;\r
-\r
-    Info = HeapAlloc(ProcessHeap,\r
-                     0,\r
-                     sizeof(EDIT_WND_INFO));\r
-    if (Info != NULL)\r
-    {\r
-        ZeroMemory(Info,\r
-                   sizeof(EDIT_WND_INFO));\r
-        Info->MainWnd = MainWnd;\r
-        Info->MdiEditorType = metImageEditor;\r
-        Info->OpenInfo = OpenInfo;\r
-\r
-        if (OpenInfo->CreateNew)\r
-        {\r
-            Width = OpenInfo->New.Width;\r
-            Height = OpenInfo->New.Height;\r
-        }\r
-        else\r
-        {\r
-            Width = CW_USEDEFAULT;\r
-            Height = CW_USEDEFAULT;\r
-        }\r
-\r
-        hWndEditor = CreateMDIWindow(szImageEditWndClass,\r
-                                     OpenInfo->lpImageName,\r
-                                     WS_HSCROLL | WS_VSCROLL | WS_MAXIMIZE,\r
-                                     200,\r
-                                     200,\r
-                                     Width,\r
-                                     Height,\r
-                                     MainWnd->hMdiClient,\r
-                                     hInstance,\r
-                                     (LPARAM)Info);\r
-\r
-        if (hWndEditor != NULL)\r
-        {\r
-            return TRUE;\r
-        }\r
-\r
-        HeapFree(ProcessHeap,\r
-                 0,\r
-                 Info);\r
-    }\r
-\r
-    return FALSE;\r
-}\r
-\r
-BOOL\r
-InitImageEditWindowImpl(VOID)\r
-{\r
-    WNDCLASSEX wc = {0};\r
-\r
-    wc.cbSize = sizeof(WNDCLASSEX);\r
-    wc.style = CS_HREDRAW | CS_VREDRAW;\r
-    wc.lpfnWndProc = ImageEditWndProc;\r
-    wc.hInstance = hInstance;\r
-    wc.hIcon = LoadIcon(hInstance,\r
-                        MAKEINTRESOURCE(IDI_IMAGESOFTICON));\r
-    wc.hCursor = LoadCursor(hInstance,\r
-                            MAKEINTRESOURCE(IDC_PAINTBRUSHCURSOR));\r
-    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);\r
-    wc.lpszClassName = szImageEditWndClass;\r
-    wc.hIconSm = (HICON)LoadImage(hInstance,\r
-                                  MAKEINTRESOURCE(IDI_IMAGESOFTICON),\r
-                                  IMAGE_ICON,\r
-                                  16,\r
-                                  16,\r
-                                  LR_SHARED);\r
-\r
-    return RegisterClassEx(&wc) != (ATOM)0;\r
-}\r
-\r
-VOID\r
-UninitImageEditWindowImpl(VOID)\r
-{\r
-    UnregisterClass(szImageEditWndClass,\r
-                    hInstance);\r
-}\r
+#include <precomp.h>
+
+static const TCHAR szImageEditWndClass[] = TEXT("ImageSoftEditWndClass");
+
+#define IMAGE_FRAME_SIZE    1
+
+
+static VOID
+EditWndUpdateScrollInfo(PEDIT_WND_INFO Info)
+{
+    SCROLLINFO si;
+    RECT rcClient;
+
+    GetClientRect(Info->hSelf,
+                  &rcClient);
+
+    si.cbSize = sizeof(si);
+    si.fMask = SIF_PAGE | SIF_RANGE;
+    si.nPage = rcClient.right - (2 * IMAGE_FRAME_SIZE);
+    si.nMin = 0;
+    si.nMax = Info->Width;
+
+    SetScrollInfo(Info->hSelf,
+                  SB_HORZ,
+                  &si,
+                  TRUE);
+
+    si.nPage = rcClient.bottom - (2 * IMAGE_FRAME_SIZE);
+    si.nMax = Info->Height;
+    SetScrollInfo(Info->hSelf,
+                  SB_VERT,
+                  &si,
+                  TRUE);
+}
+
+static BOOL
+InitEditWnd(PEDIT_WND_INFO Info)
+{
+    BITMAPFILEHEADER bmfh;
+    PBITMAPINFO pbmi = NULL;
+    PBYTE pBits;
+    HANDLE hFile;
+    BITMAP bitmap;
+
+    Info->Zoom = 100;
+
+    if (Info->OpenInfo != NULL)
+    {
+        HDC hDC = GetDC(Info->hSelf);
+        Info->hDCMem = CreateCompatibleDC(hDC);
+        ReleaseDC(Info->hSelf, hDC);
+
+        if (Info->OpenInfo->CreateNew)
+        {
+            /* FIXME: convert this to a DIB Section */
+            /* set bitmap dimensions */
+            Info->Width = Info->OpenInfo->New.Width;
+            Info->Height = Info->OpenInfo->New.Height;
+
+        }
+        else
+        {
+            DWORD InfoSize, BytesRead;
+            BOOL bSuccess;
+
+            hFile = CreateFile(Info->OpenInfo->Open.lpImagePath,
+                               GENERIC_READ,
+                               FILE_SHARE_READ,
+                               NULL,
+                               OPEN_EXISTING,
+                               FILE_FLAG_SEQUENTIAL_SCAN,
+                               NULL);
+            if (hFile == INVALID_HANDLE_VALUE)
+                return FALSE;
+
+            bSuccess = ReadFile(hFile,
+                                &bmfh,
+                                sizeof(BITMAPFILEHEADER),
+                                &BytesRead,
+                                NULL);
+
+            if ( bSuccess && (BytesRead == sizeof(BITMAPFILEHEADER))
+                            /* FIXME: Why is this failing?? */
+                          /*&& (bmfh.bfType == *(WORD *)_T("BM"))*/)
+            {
+                InfoSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
+
+                pbmi = HeapAlloc(ProcessHeap,
+                                 0,
+                                 InfoSize);
+
+                bSuccess = ReadFile(hFile,
+                                    pbmi,
+                                    InfoSize,
+                                    &BytesRead,
+                                    NULL);
+
+                if (bSuccess && (BytesRead == InfoSize))
+                {
+                    Info->hBitmap = CreateDIBSection(NULL,
+                                                     pbmi,
+                                                     DIB_RGB_COLORS,
+                                                     (VOID *)&pBits,
+                                                     NULL,
+                                                     0);
+                    if (Info->hBitmap != NULL)
+                    {
+                        ReadFile(hFile,
+                                 pBits,
+                                 bmfh.bfSize - bmfh.bfOffBits,
+                                 &BytesRead,
+                                 NULL);
+                    }
+                    else
+                    {
+                        goto fail;
+                    }
+                }
+                else
+                {
+                    goto fail;
+                }
+            }
+            else
+            {
+                if (! bSuccess)
+                    GetError(0);
+
+                goto fail;
+            }
+
+            CloseHandle(hFile);
+
+            HeapFree(ProcessHeap,
+                     0,
+                     pbmi);
+        }
+
+        Info->OpenInfo = NULL;
+    }
+
+    /* get bitmap dimensions */
+    GetObject(Info->hBitmap,
+                  sizeof(BITMAP),
+                  &bitmap);
+
+    Info->Width = bitmap.bmWidth;
+    Info->Height = bitmap.bmHeight;
+
+    EditWndUpdateScrollInfo(Info);
+
+    /* Add image editor to the list */
+    Info->Next = Info->MainWnd->ImageEditors;
+    Info->MainWnd->ImageEditors = Info;
+
+    InvalidateRect(Info->hSelf,
+                   NULL,
+                   TRUE);
+
+    /* FIXME - if returning FALSE, remove the image editor from the list! */
+    return TRUE;
+
+
+fail:
+    if (! hFile)
+        CloseHandle(hFile);
+
+    if (! pbmi)
+        HeapFree(ProcessHeap,
+                 0,
+                 pbmi);
+
+    return FALSE;
+}
+
+static VOID
+DestroyEditWnd(PEDIT_WND_INFO Info)
+{
+    PEDIT_WND_INFO *PrevEditor;
+    PEDIT_WND_INFO Editor;
+
+    DeleteDC(Info->hDCMem);
+
+    /* FIXME - free resources and run down editor */
+
+    /* Remove the image editor from the list */
+    PrevEditor = &Info->MainWnd->ImageEditors;
+    Editor = Info->MainWnd->ImageEditors;
+    do
+    {
+        if (Editor == Info)
+        {
+            *PrevEditor = Info->Next;
+            break;
+        }
+        PrevEditor = &Editor->Next;
+        Editor = Editor->Next;
+    } while (Editor != NULL);
+}
+
+static VOID
+ImageEditWndRepaint(PEDIT_WND_INFO Info,
+                    HDC hDC,
+                    LPPAINTSTRUCT lpps)
+{
+    HBITMAP hOldBitmap;
+
+    if (Info->hBitmap)
+    {
+        hOldBitmap = (HBITMAP) SelectObject(Info->hDCMem,
+                                            Info->hBitmap);
+
+        BitBlt(hDC,
+               lpps->rcPaint.left,
+               lpps->rcPaint.top,
+               lpps->rcPaint.right - lpps->rcPaint.left,
+               lpps->rcPaint.bottom - lpps->rcPaint.top,
+               Info->hDCMem,
+               lpps->rcPaint.left,
+               lpps->rcPaint.top,
+               SRCCOPY);
+
+        Info->hBitmap = SelectObject(Info->hDCMem, hOldBitmap);
+    }
+}
+
+static LRESULT CALLBACK
+ImageEditWndProc(HWND hwnd,
+                 UINT uMsg,
+                 WPARAM wParam,
+                 LPARAM lParam)
+{
+    PEDIT_WND_INFO Info;
+    LRESULT Ret = 0;
+    HDC hDC;
+    static INT xMouse, yMouse;
+    static BOOL bLeftButtonDown, bRightButtonDown;
+
+    /* Get the window context */
+    Info = (PEDIT_WND_INFO)GetWindowLongPtr(hwnd,
+                                            GWLP_USERDATA);
+    if (Info == NULL && uMsg != WM_CREATE)
+    {
+        goto HandleDefaultMessage;
+    }
+
+    switch (uMsg)
+    {
+        case WM_CREATE:
+        {
+            Info = (PEDIT_WND_INFO)(((LPMDICREATESTRUCT)((LPCREATESTRUCT)lParam)->lpCreateParams)->lParam);
+            Info->hSelf = hwnd;
+
+            SetWindowLongPtr(hwnd,
+                             GWLP_USERDATA,
+                             (LONG_PTR)Info);
+
+            if (!InitEditWnd(Info))
+            {
+                Ret = (LRESULT)-1;
+                break;
+            }
+            break;
+        }
+
+        case WM_ERASEBKGND:
+            if (Info->Width != 0 && Info->Height != 0)
+            {
+                Ret = TRUE;
+            }
+            break;
+
+        case WM_LBUTTONDOWN:
+            if (! bRightButtonDown)
+                SetCapture(Info->hSelf);
+
+            bLeftButtonDown = TRUE;
+            xMouse = LOWORD(lParam);
+            yMouse = HIWORD(lParam);
+
+            SetCursor(LoadCursor(hInstance,
+                                 MAKEINTRESOURCE(IDC_PAINTBRUSHCURSORMOUSEDOWN)));
+        break;
+
+        case WM_LBUTTONUP:
+            if (bLeftButtonDown)
+                SetCapture(NULL);
+
+            bLeftButtonDown = FALSE;
+
+        break;
+
+        case WM_RBUTTONDOWN:
+            if (! bLeftButtonDown)
+                SetCapture(Info->hSelf);
+
+            bRightButtonDown = TRUE;
+            xMouse = LOWORD(lParam);
+            yMouse = HIWORD(lParam);
+
+            SetCursor(LoadCursor(hInstance,
+                                 MAKEINTRESOURCE(IDC_PAINTBRUSHCURSORMOUSEDOWN)));
+        break;
+
+        case WM_RBUTTONUP:
+            if (bRightButtonDown)
+                SetCapture(NULL);
+
+            bRightButtonDown = FALSE;
+
+        break;
+
+        case WM_MOUSEMOVE:
+        {
+            HPEN hPen, hPenOld;
+
+            if (!bLeftButtonDown && !bRightButtonDown)
+                break;
+
+            hDC = GetDC(Info->hSelf);
+
+            SelectObject(Info->hDCMem,
+                         Info->hBitmap);
+
+            if (bLeftButtonDown)
+                hPen = CreatePen(PS_SOLID,
+                                 3,
+                                 RGB(0, 0, 0));
+            else
+                hPen = CreatePen(PS_SOLID,
+                                 3,
+                                 RGB(255, 255, 255));
+
+            hPenOld = SelectObject(hDC,
+                                   hPen);
+
+            MoveToEx(hDC,
+                     xMouse,
+                     yMouse,
+                     NULL);
+
+            MoveToEx(Info->hDCMem,
+                     xMouse,
+                     yMouse,
+                     NULL);
+
+            xMouse = (short)LOWORD(lParam);
+            yMouse = (short)HIWORD(lParam);
+
+            LineTo(hDC,
+                   xMouse,
+                   yMouse);
+
+            LineTo(Info->hDCMem,
+                   xMouse,
+                   yMouse);
+
+            DeleteObject(SelectObject(hDC,
+                                      hPenOld));
+
+            ReleaseDC(Info->hSelf,
+                      hDC);
+        }
+        break;
+
+        case WM_PAINT:
+        {
+            if (Info->Width != 0 && Info->Height != 0)
+            {
+                PAINTSTRUCT ps;
+                HDC hDC;
+
+                hDC = BeginPaint(hwnd,
+                                 &ps);
+                if (hDC != NULL)
+                {
+                    ImageEditWndRepaint(Info,
+                                        hDC,
+                                        &ps);
+
+                    EndPaint(hwnd,
+                             &ps);
+                }
+            }
+            break;
+        }
+
+        case WM_SIZE:
+        {
+            EditWndUpdateScrollInfo(Info);
+            goto HandleDefaultMessage;
+        }
+
+        case WM_MENUSELECT:
+        case WM_ENTERMENULOOP:
+        case WM_EXITMENULOOP:
+            /* forward these messages to the main window procedure */
+            Ret = SendMessage(Info->MainWnd->hSelf,
+                              uMsg,
+                              wParam,
+                              lParam);
+            break;
+
+        case WM_MDIACTIVATE:
+            /* Switch the main window context if neccessary */
+            MainWndSwitchEditorContext(Info->MainWnd,
+                                       (HWND)wParam,
+                                       (HWND)lParam);
+            break;
+
+        case WM_DESTROY:
+        {
+            DestroyEditWnd(Info);
+
+            HeapFree(ProcessHeap,
+                     0,
+                     Info);
+            SetWindowLongPtr(hwnd,
+                             GWLP_USERDATA,
+                             0);
+            break;
+        }
+
+        default:
+HandleDefaultMessage:
+            Ret = DefMDIChildProc(hwnd,
+                                  uMsg,
+                                  wParam,
+                                  lParam);
+            break;
+    }
+
+    return Ret;
+}
+
+VOID
+SetImageEditorEnvironment(PEDIT_WND_INFO Info,
+                          BOOL Setup)
+{
+    if (Setup)
+    {
+        /* FIXME - setup editor environment (e.g. show toolbars, enable menus etc) */
+    }
+    else
+    {
+        /* FIXME - cleanup editor environment (e.g. hide toolbars, disable menus etc) */
+    }
+}
+
+BOOL
+CreateImageEditWindow(struct _MAIN_WND_INFO *MainWnd,
+                      POPEN_IMAGE_EDIT_INFO OpenInfo)
+{
+    PEDIT_WND_INFO Info;
+    HWND hWndEditor;
+    LONG Width, Height;
+
+    Info = HeapAlloc(ProcessHeap,
+                     0,
+                     sizeof(EDIT_WND_INFO));
+    if (Info != NULL)
+    {
+        ZeroMemory(Info,
+                   sizeof(EDIT_WND_INFO));
+        Info->MainWnd = MainWnd;
+        Info->MdiEditorType = metImageEditor;
+        Info->OpenInfo = OpenInfo;
+
+        if (OpenInfo->CreateNew)
+        {
+            Width = OpenInfo->New.Width;
+            Height = OpenInfo->New.Height;
+        }
+        else
+        {
+            Width = CW_USEDEFAULT;
+            Height = CW_USEDEFAULT;
+        }
+
+        hWndEditor = CreateMDIWindow(szImageEditWndClass,
+                                     OpenInfo->lpImageName,
+                                     WS_HSCROLL | WS_VSCROLL | WS_MAXIMIZE,
+                                     200,
+                                     200,
+                                     Width,
+                                     Height,
+                                     MainWnd->hMdiClient,
+                                     hInstance,
+                                     (LPARAM)Info);
+
+        if (hWndEditor != NULL)
+        {
+            return TRUE;
+        }
+
+        HeapFree(ProcessHeap,
+                 0,
+                 Info);
+    }
+
+    return FALSE;
+}
+
+BOOL
+InitImageEditWindowImpl(VOID)
+{
+    WNDCLASSEX wc = {0};
+
+    wc.cbSize = sizeof(WNDCLASSEX);
+    wc.style = CS_HREDRAW | CS_VREDRAW;
+    wc.lpfnWndProc = ImageEditWndProc;
+    wc.hInstance = hInstance;
+    wc.hIcon = LoadIcon(hInstance,
+                        MAKEINTRESOURCE(IDI_IMAGESOFTICON));
+    wc.hCursor = LoadCursor(hInstance,
+                            MAKEINTRESOURCE(IDC_PAINTBRUSHCURSOR));
+    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+    wc.lpszClassName = szImageEditWndClass;
+    wc.hIconSm = (HICON)LoadImage(hInstance,
+                                  MAKEINTRESOURCE(IDI_IMAGESOFTICON),
+                                  IMAGE_ICON,
+                                  16,
+                                  16,
+                                  LR_SHARED);
+
+    return RegisterClassEx(&wc) != (ATOM)0;
+}
+
+VOID
+UninitImageEditWindowImpl(VOID)
+{
+    UnregisterClass(szImageEditWndClass,
+                    hInstance);
+}