[MSPAINT_NEW] turn the history into an ImageModel
authorBenedikt Freisen <b.freisen@gmx.net>
Tue, 7 Jul 2015 11:56:37 +0000 (11:56 +0000)
committerBenedikt Freisen <b.freisen@gmx.net>
Tue, 7 Jul 2015 11:56:37 +0000 (11:56 +0000)
svn path=/trunk/; revision=68372

14 files changed:
reactos/base/applications/mspaint_new/definitions.h
reactos/base/applications/mspaint_new/dialogs.cpp
reactos/base/applications/mspaint_new/globalvar.h
reactos/base/applications/mspaint_new/history.cpp
reactos/base/applications/mspaint_new/history.h
reactos/base/applications/mspaint_new/imgarea.cpp
reactos/base/applications/mspaint_new/imgarea.h
reactos/base/applications/mspaint_new/main.cpp
reactos/base/applications/mspaint_new/miniature.cpp
reactos/base/applications/mspaint_new/mouse.cpp
reactos/base/applications/mspaint_new/scrollbox.cpp
reactos/base/applications/mspaint_new/selection.cpp
reactos/base/applications/mspaint_new/sizebox.cpp
reactos/base/applications/mspaint_new/winproc.cpp

index 1871fdd..ce6e905 100644 (file)
 #define WM_TOOLSMODELZOOMCHANGED (WM_APP + 2)
 #define WM_PALETTEMODELCOLORCHANGED (WM_APP + 3)
 #define WM_PALETTEMODELPALETTECHANGED (WM_APP + 4)
+#define WM_IMAGEMODELDIMENSIONSCHANGED (WM_APP + 5)
+#define WM_IMAGEMODELIMAGECHANGED (WM_APP + 6)
index af6a687..b457206 100644 (file)
@@ -79,8 +79,8 @@ ATTDlgWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
             TCHAR strrc[100];
             TCHAR res[100];
 
-            widthSetInDlg = imgXRes;
-            heightSetInDlg = imgYRes;
+            widthSetInDlg = imageModel.GetWidth();
+            heightSetInDlg = imageModel.GetHeight();
 
             CheckDlgButton(hwnd, IDD_ATTRIBUTESRB3, BST_CHECKED);
             CheckDlgButton(hwnd, IDD_ATTRIBUTESRB5, BST_CHECKED);
@@ -119,8 +119,8 @@ ATTDlgWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                     EndDialog(hwnd, 0);
                     break;
                 case IDD_ATTRIBUTESSTANDARD:
-                    widthSetInDlg = imgXRes;
-                    heightSetInDlg = imgYRes;
+                    widthSetInDlg = imageModel.GetWidth();
+                    heightSetInDlg = imageModel.GetHeight();
                     CheckDlgButton(hwnd, IDD_ATTRIBUTESRB3, BST_CHECKED);
                     CheckDlgButton(hwnd, IDD_ATTRIBUTESRB5, BST_CHECKED);
                     SetDlgItemInt(hwnd, IDD_ATTRIBUTESEDIT1, widthSetInDlg, FALSE);
index 0e56a17..270a3e5 100644 (file)
@@ -24,19 +24,14 @@ extern HDC hDrawingDC;
 extern HDC hSelDC;
 extern int *bmAddress;
 extern BITMAPINFO bitmapinfo;
-extern int imgXRes;
-extern int imgYRes;
 
 extern int widthSetInDlg;
 extern int heightSetInDlg;
 
 extern STRETCHSKEW stretchSkew;
 
-extern HBITMAP hBms[HISTORYSIZE];
-extern int currInd;
-extern int undoSteps;
-extern int redoSteps;
-extern BOOL imageSaved;
+class ImageModel;
+extern ImageModel imageModel;
 
 extern POINT start;
 extern POINT last;
index 7c73304..0d4a27d 100644 (file)
 
 /* FUNCTIONS ********************************************************/
 
-extern void updateCanvasAndScrollbars(void);
+void ImageModel::NotifyDimensionsChanged()
+{
+    imageArea.SendMessage(WM_IMAGEMODELDIMENSIONSCHANGED);
+}
 
-void
-setImgXYRes(int x, int y)
+void ImageModel::NotifyImageChanged()
 {
-    if ((imgXRes != x) || (imgYRes != y))
-    {
-        imgXRes = x;
-        imgYRes = y;
-        updateCanvasAndScrollbars();
-    }
+    imageArea.SendMessage(WM_IMAGEMODELIMAGECHANGED);
 }
 
-void
-newReversible()
+void ImageModel::CopyPrevious()
 {
     DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]);
     hBms[(currInd + 1) % HISTORYSIZE] = (HBITMAP) CopyImage(hBms[currInd], IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG);
@@ -35,62 +31,64 @@ newReversible()
         undoSteps++;
     redoSteps = 0;
     SelectObject(hDrawingDC, hBms[currInd]);
-    imgXRes = GetDIBWidth(hBms[currInd]);
-    imgYRes = GetDIBHeight(hBms[currInd]);
     imageSaved = FALSE;
 }
 
-void
-undo()
+void ImageModel::Undo()
 {
     if (undoSteps > 0)
     {
+        int oldWidth = GetWidth();
+        int oldHeight = GetHeight();
         selectionWindow.ShowWindow(SW_HIDE);
         currInd = (currInd + HISTORYSIZE - 1) % HISTORYSIZE;
         SelectObject(hDrawingDC, hBms[currInd]);
         undoSteps--;
         if (redoSteps < HISTORYSIZE - 1)
             redoSteps++;
-        setImgXYRes(GetDIBWidth(hBms[currInd]), GetDIBHeight(hBms[currInd]));
+        if (GetWidth() != oldWidth || GetHeight() != oldHeight)
+            NotifyDimensionsChanged();
+        NotifyImageChanged();
     }
 }
 
-void
-redo()
+void ImageModel::Redo()
 {
     if (redoSteps > 0)
     {
+        int oldWidth = GetWidth();
+        int oldHeight = GetHeight();
         selectionWindow.ShowWindow(SW_HIDE);
         currInd = (currInd + 1) % HISTORYSIZE;
         SelectObject(hDrawingDC, hBms[currInd]);
         redoSteps--;
         if (undoSteps < HISTORYSIZE - 1)
             undoSteps++;
-        setImgXYRes(GetDIBWidth(hBms[currInd]), GetDIBHeight(hBms[currInd]));
+        if (GetWidth() != oldWidth || GetHeight() != oldHeight)
+            NotifyDimensionsChanged();
+        NotifyImageChanged();
     }
 }
 
-void
-resetToU1()
+void ImageModel::ResetToPrevious()
 {
     DeleteObject(hBms[currInd]);
     hBms[currInd] =
         (HBITMAP) CopyImage(hBms[(currInd + HISTORYSIZE - 1) % HISTORYSIZE], IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG);
     SelectObject(hDrawingDC, hBms[currInd]);
-    imgXRes = GetDIBWidth(hBms[currInd]);
-    imgYRes = GetDIBHeight(hBms[currInd]);
+    NotifyImageChanged();
 }
 
-void
-clearHistory()
+void ImageModel::ClearHistory()
 {
     undoSteps = 0;
     redoSteps = 0;
 }
 
-void
-insertReversible(HBITMAP hbm)
+void ImageModel::Insert(HBITMAP hbm)
 {
+    int oldWidth = GetWidth();
+    int oldHeight = GetHeight();
     DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]);
     hBms[(currInd + 1) % HISTORYSIZE] = hbm;
     currInd = (currInd + 1) % HISTORYSIZE;
@@ -98,19 +96,22 @@ insertReversible(HBITMAP hbm)
         undoSteps++;
     redoSteps = 0;
     SelectObject(hDrawingDC, hBms[currInd]);
-    setImgXYRes(GetDIBWidth(hBms[currInd]), GetDIBHeight(hBms[currInd]));
+    if (GetWidth() != oldWidth || GetHeight() != oldHeight)
+        NotifyDimensionsChanged();
+    NotifyImageChanged();
 }
 
-void
-cropReversible(int width, int height, int xOffset, int yOffset)
+void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY)
 {
     HDC hdc;
     HPEN oldPen;
     HBRUSH oldBrush;
+    int oldWidth = GetWidth();
+    int oldHeight = GetHeight();
 
     SelectObject(hDrawingDC, hBms[currInd]);
     DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]);
-    hBms[(currInd + 1) % HISTORYSIZE] = CreateDIBWithProperties(width, height);
+    hBms[(currInd + 1) % HISTORYSIZE] = CreateDIBWithProperties(nWidth, nHeight);
     currInd = (currInd + 1) % HISTORYSIZE;
     if (undoSteps < HISTORYSIZE - 1)
         undoSteps++;
@@ -121,12 +122,71 @@ cropReversible(int width, int height, int xOffset, int yOffset)
 
     oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, paletteModel.GetBgColor()));
     oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(paletteModel.GetBgColor()));
-    Rectangle(hdc, 0, 0, width, height);
-    BitBlt(hdc, -xOffset, -yOffset, imgXRes, imgYRes, hDrawingDC, 0, 0, SRCCOPY);
+    Rectangle(hdc, 0, 0, nWidth, nHeight);
+    BitBlt(hdc, -nOffsetX, -nOffsetY, GetWidth(), GetHeight(), hDrawingDC, 0, 0, SRCCOPY);
     DeleteObject(SelectObject(hdc, oldBrush));
     DeleteObject(SelectObject(hdc, oldPen));
     DeleteDC(hdc);
     SelectObject(hDrawingDC, hBms[currInd]);
 
-    setImgXYRes(width, height);
+    if (GetWidth() != oldWidth || GetHeight() != oldHeight)
+        NotifyDimensionsChanged();
+    NotifyImageChanged();
+}
+
+void ImageModel::SaveImage(LPTSTR lpFileName)
+{
+    SaveDIBToFile(hBms[currInd], lpFileName, hDrawingDC, &fileTime, &fileSize, fileHPPM, fileVPPM);
+    imageSaved = TRUE;
+}
+
+BOOL ImageModel::IsImageSaved()
+{
+    return imageSaved;
+}
+
+BOOL ImageModel::HasUndoSteps()
+{
+    return undoSteps > 0;
+}
+
+BOOL ImageModel::HasRedoSteps()
+{
+    return redoSteps > 0;
+}
+
+void ImageModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY)
+{
+    int oldWidth = GetWidth();
+    int oldHeight = GetHeight();
+    Insert((HBITMAP) CopyImage(hBms[currInd], IMAGE_BITMAP,
+           GetWidth() * nStretchPercentX / 100,
+           GetHeight() * nStretchPercentY / 100, 0));
+    if (GetWidth() != oldWidth || GetHeight() != oldHeight)
+        NotifyDimensionsChanged();
+    NotifyImageChanged();
+}
+
+int ImageModel::GetWidth()
+{
+    return GetDIBWidth(hBms[currInd]);
+}
+
+int ImageModel::GetHeight()
+{
+    return GetDIBHeight(hBms[currInd]);
+}
+
+void ImageModel::InvertColors()
+{
+    RECT rect = {0, 0, GetWidth(), GetHeight()};
+    CopyPrevious();
+    InvertRect(hDrawingDC, &rect);
+    NotifyImageChanged();
+}
+
+void ImageModel::Clear(COLORREF color)
+{
+    Rectangle(hDrawingDC, 0 - 1, 0 - 1, GetWidth() + 1, GetHeight() + 1);
+    NotifyImageChanged();
 }
index c3b526c..39dcc57 100644 (file)
@@ -6,16 +6,32 @@
  * PROGRAMMERS: Benedikt Freisen
  */
 
-void newReversible(void);
+class ImageModel
+{
+private:
+    void NotifyDimensionsChanged();
+    void NotifyImageChanged();
+public:
+    HBITMAP hBms[HISTORYSIZE];
+    int currInd;
+    int undoSteps;
+    int redoSteps;
+    BOOL imageSaved;
 
-void undo(void);
-
-void redo(void);
-
-void resetToU1(void);
-
-void clearHistory(void);
-
-void insertReversible(HBITMAP hbm);
-
-void cropReversible(int width, int height, int xOffset, int yOffset);
+    void CopyPrevious(void);
+    void Undo(void);
+    void Redo(void);
+    void ResetToPrevious(void);
+    void ClearHistory(void);
+    void Insert(HBITMAP hbm);
+    void Crop(int nWidth, int nHeight, int nOffsetX = 0, int nOffsetY = 0);
+    void SaveImage(LPTSTR lpFileName);
+    BOOL IsImageSaved();
+    BOOL HasUndoSteps();
+    BOOL HasRedoSteps();
+    void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX = 0, int nSkewDegY = 0);
+    int GetWidth();
+    int GetHeight();
+    void InvertColors();
+    void Clear(COLORREF color = 0x00ffffff);
+};
index 922c3e6..d00c905 100644 (file)
 extern void
 zoomTo(int newZoom, int mouseX, int mouseY);
 
+void
+updateCanvasAndScrollbars()
+{
+    selectionWindow.ShowWindow(SW_HIDE);
+    imageArea.MoveWindow(3, 3, imageModel.GetWidth() * toolsModel.GetZoom() / 1000, imageModel.GetHeight() * toolsModel.GetZoom() / 1000, FALSE);
+    scrollboxWindow.Invalidate(TRUE);
+    imageArea.Invalidate(FALSE);
+
+    scrollboxWindow.SetScrollPos(SB_HORZ, 0, TRUE);
+    scrollboxWindow.SetScrollPos(SB_VERT, 0, TRUE);
+}
+
 void CImgAreaWindow::drawZoomFrame(int mouseX, int mouseY)
 {
     HDC hdc;
@@ -51,6 +63,8 @@ void CImgAreaWindow::drawZoomFrame(int mouseX, int mouseY)
 
 LRESULT CImgAreaWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
+    int imgXRes = imageModel.GetWidth();
+    int imgYRes = imageModel.GetHeight();
     sizeboxLeftTop.MoveWindow(
                0,
                0, 3, 3, TRUE);
@@ -82,7 +96,9 @@ LRESULT CImgAreaWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
 LRESULT CImgAreaWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
     DefWindowProc(WM_PAINT, wParam, lParam);
-    HDC hdc = imageArea.GetDC();
+    HDC hdc = GetDC();
+    int imgXRes = imageModel.GetWidth();
+    int imgYRes = imageModel.GetHeight();
     StretchBlt(hdc, 0, 0, imgXRes * toolsModel.GetZoom() / 1000, imgYRes * toolsModel.GetZoom() / 1000, hDrawingDC, 0, 0, imgXRes,
                imgYRes, SRCCOPY);
     if (showGrid && (toolsModel.GetZoom() >= 4000))
@@ -101,7 +117,7 @@ LRESULT CImgAreaWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& b
         }
         DeleteObject(SelectObject(hdc, oldPen));
     }
-    imageArea.ReleaseDC(hdc);
+    ReleaseDC(hdc);
     selectionWindow.Invalidate(FALSE);
     miniature.Invalidate(FALSE);
     return 0;
@@ -144,7 +160,7 @@ LRESULT CImgAreaWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, B
     else
     {
         SendMessage(WM_LBUTTONUP, wParam, lParam);
-        undo();
+        imageModel.Undo();
     }
     Invalidate(FALSE);
     if ((toolsModel.GetActiveTool() == TOOL_ZOOM) && (toolsModel.GetZoom() < 8000))
@@ -164,7 +180,7 @@ LRESULT CImgAreaWindow::OnRButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, B
     else
     {
         SendMessage(WM_RBUTTONUP, wParam, lParam);
-        undo();
+        imageModel.Undo();
     }
     Invalidate(FALSE);
     if ((toolsModel.GetActiveTool() == TOOL_ZOOM) && (toolsModel.GetZoom() > 125))
@@ -231,7 +247,7 @@ LRESULT CImgAreaWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
 
         tme.cbSize = sizeof(TRACKMOUSEEVENT);
         tme.dwFlags = TME_LEAVE;
-        tme.hwndTrack = imageArea.m_hWnd;
+        tme.hwndTrack = m_hWnd;
         tme.dwHoverTime = 0;
         TrackMouseEvent(&tme);
 
@@ -252,12 +268,12 @@ LRESULT CImgAreaWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
         {
             if (xRel < 0)
                 xRel = (xNow < 0) ? -start.x : xRel;
-            else if (xNow > imgXRes)
-                xRel = imgXRes-start.x;
+            else if (xNow > imageModel.GetWidth())
+                xRel = imageModel.GetWidth() - start.x;
             if (yRel < 0)
                 yRel = (yNow < 0) ? -start.y : yRel;
-            else if (yNow > imgYRes)
-                 yRel = imgYRes-start.y;
+            else if (yNow > imageModel.GetHeight())
+                 yRel = imageModel.GetHeight() - start.y;
         }
         /* rectsel and shape tools always show non-negative numbers when drawing */
         if ((toolsModel.GetActiveTool() == TOOL_RECTSEL) || (toolsModel.GetActiveTool() == TOOL_SHAPE))
@@ -316,6 +332,18 @@ LRESULT CImgAreaWindow::OnMouseLeave(UINT nMsg, WPARAM wParam, LPARAM lParam, BO
 {
     SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) _T(""));
     if (toolsModel.GetActiveTool() == TOOL_ZOOM)
-        imageArea.Invalidate(FALSE);
+        Invalidate(FALSE);
+    return 0;
+}
+
+LRESULT CImgAreaWindow::OnImageModelDimensionsChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    updateCanvasAndScrollbars();
+    return 0;
+}
+
+LRESULT CImgAreaWindow::OnImageModelImageChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    Invalidate(FALSE);
     return 0;
 }
index 527b667..6c76f71 100644 (file)
@@ -22,6 +22,8 @@ public:
         MESSAGE_HANDLER(WM_RBUTTONUP, OnRButtonUp)
         MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
         MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
+        MESSAGE_HANDLER(WM_IMAGEMODELDIMENSIONSCHANGED, OnImageModelDimensionsChanged)
+        MESSAGE_HANDLER(WM_IMAGEMODELIMAGECHANGED, OnImageModelImageChanged)
     END_MSG_MAP()
 
     BOOL drawing;
@@ -36,6 +38,8 @@ private:
     LRESULT OnRButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnMouseLeave(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnImageModelDimensionsChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnImageModelImageChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
 
     void drawZoomFrame(int mouseX, int mouseY);
 };
index d0d3ed0..363c635 100644 (file)
@@ -24,11 +24,7 @@ int heightSetInDlg;
 
 STRETCHSKEW stretchSkew;
 
-HBITMAP hBms[HISTORYSIZE];
-int currInd = 0;
-int undoSteps = 0;
-int redoSteps = 0;
-BOOL imageSaved = TRUE;
+ImageModel imageModel;
 
 POINT start;
 POINT last;
@@ -214,8 +210,9 @@ _tWinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPTSTR lpszArgument
     SelectObject(hDrawingDC, CreatePen(PS_SOLID, 0, paletteModel.GetFgColor()));
     SelectObject(hDrawingDC, CreateSolidBrush(paletteModel.GetBgColor()));
 
-    hBms[0] = CreateDIBWithProperties(imgXRes, imgYRes);
-    SelectObject(hDrawingDC, hBms[0]);
+    //TODO: move to ImageModel
+    imageModel.hBms[0] = CreateDIBWithProperties(imgXRes, imgYRes);
+    SelectObject(hDrawingDC, imageModel.hBms[0]);
     Rectangle(hDrawingDC, 0 - 1, 0 - 1, imgXRes + 1, imgYRes + 1);
 
     if (lpszArgument[0] != 0)
@@ -227,13 +224,13 @@ _tWinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPTSTR lpszArgument
             TCHAR tempstr[1000];
             TCHAR resstr[100];
             TCHAR *temp;
-            insertReversible(bmNew);
+            imageModel.Insert(bmNew);
             GetFullPathName(lpszArgument, SIZEOF(filepathname), filepathname, &temp);
             _tcscpy(filename, temp);
             LoadString(hProgInstance, IDS_WINDOWTITLE, resstr, SIZEOF(resstr));
             _stprintf(tempstr, resstr, filename);
             mainWindow.SetWindowText(tempstr);
-            clearHistory();
+            imageModel.ClearHistory();
             isAFile = TRUE;
         }
         else
index 6fab193..702c725 100644 (file)
@@ -27,7 +27,7 @@ LRESULT CMiniatureWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
     HDC hdc;
     miniature.GetClientRect(&mclient);
     hdc = miniature.GetDC();
-    StretchBlt(hdc, 0, 0, mclient.right, mclient.bottom, hDrawingDC, 0, 0, imgXRes, imgYRes, SRCCOPY);
+    StretchBlt(hdc, 0, 0, mclient.right, mclient.bottom, hDrawingDC, 0, 0, imageModel.GetWidth(), imageModel.GetHeight(), SRCCOPY);
     miniature.ReleaseDC(hdc);
     return 0;
 }
index ffa0bc7..10f446e 100644 (file)
@@ -76,33 +76,33 @@ startPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_RECT:
         case TOOL_ELLIPSE:
         case TOOL_RRECT:
-            newReversible();
+            imageModel.CopyPrevious();
             break;
         case TOOL_RECTSEL:
         case TOOL_TEXT:
-            newReversible();
+            imageModel.CopyPrevious();
             selectionWindow.ShowWindow(SW_HIDE);
             rectSel_src.right = rectSel_src.left;
             rectSel_src.bottom = rectSel_src.top;
             break;
         case TOOL_RUBBER:
-            newReversible();
+            imageModel.CopyPrevious();
             Erase(hdc, x, y, x, y, bg, toolsModel.GetRubberRadius());
             break;
         case TOOL_FILL:
-            newReversible();
+            imageModel.CopyPrevious();
             Fill(hdc, x, y, fg);
             break;
         case TOOL_PEN:
-            newReversible();
+            imageModel.CopyPrevious();
             SetPixel(hdc, x, y, fg);
             break;
         case TOOL_BRUSH:
-            newReversible();
+            imageModel.CopyPrevious();
             Brush(hdc, x, y, x, y, fg, toolsModel.GetBrushStyle());
             break;
         case TOOL_AIRBRUSH:
-            newReversible();
+            imageModel.CopyPrevious();
             Airbrush(hdc, x, y, fg, toolsModel.GetAirBrushWidth());
             break;
         case TOOL_BEZIER:
@@ -110,7 +110,7 @@ startPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             pointStack[pointSP].y = y;
             if (pointSP == 0)
             {
-                newReversible();
+                imageModel.CopyPrevious();
                 pointSP++;
             }
             break;
@@ -121,7 +121,7 @@ startPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
                 Poly(hdc, pointStack, pointSP + 1, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
             if (pointSP == 0)
             {
-                newReversible();
+                imageModel.CopyPrevious();
                 pointSP++;
             }
             break;
@@ -135,22 +135,22 @@ whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
     {
         case TOOL_FREESEL:
             if (ptSP == 0)
-                newReversible();
+                imageModel.CopyPrevious();
             ptSP++;
             if (ptSP % 1024 == 0)
                 ptStack = (POINT*) HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, ptStack, sizeof(POINT) * (ptSP + 1024));
-            ptStack[ptSP].x = max(0, min(x, imgXRes));
-            ptStack[ptSP].y = max(0, min(y, imgYRes));
-            resetToU1();
+            ptStack[ptSP].x = max(0, min(x, imageModel.GetWidth()));
+            ptStack[ptSP].y = max(0, min(y, imageModel.GetHeight()));
+            imageModel.ResetToPrevious();
             Poly(hdc, ptStack, ptSP + 1, 0, 0, 2, 0, FALSE, TRUE); /* draw the freehand selection inverted/xored */
             break;
         case TOOL_RECTSEL:
         case TOOL_TEXT:
         {
             POINT temp;
-            resetToU1();
-            temp.x = max(0, min(x, imgXRes));
-            temp.y = max(0, min(y, imgYRes));
+            imageModel.ResetToPrevious();
+            temp.x = max(0, min(x, imageModel.GetWidth()));
+            temp.y = max(0, min(y, imageModel.GetHeight()));
             rectSel_dest.left = rectSel_src.left = min(start.x, temp.x);
             rectSel_dest.top = rectSel_src.top = min(start.y, temp.y);
             rectSel_dest.right = rectSel_src.right = max(start.x, temp.x);
@@ -171,13 +171,13 @@ whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             Airbrush(hdc, x, y, fg, toolsModel.GetAirBrushWidth());
             break;
         case TOOL_LINE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 roundTo8Directions(start.x, start.y, &x, &y);
             Line(hdc, start.x, start.y, x, y, fg, toolsModel.GetLineWidth());
             break;
         case TOOL_BEZIER:
-            resetToU1();
+            imageModel.ResetToPrevious();
             pointStack[pointSP].x = x;
             pointStack[pointSP].y = y;
             switch (pointSP)
@@ -195,13 +195,13 @@ whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             }
             break;
         case TOOL_RECT:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             Rect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_SHAPE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             pointStack[pointSP].x = x;
             pointStack[pointSP].y = y;
             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
@@ -211,13 +211,13 @@ whilePaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
                 Poly(hdc, pointStack, pointSP + 1, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
             break;
         case TOOL_ELLIPSE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             Ellp(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_RRECT:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             RRect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
@@ -270,11 +270,11 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
                 Poly(hSelDC, ptStackCopy, ptSP + 1, 0x00ffffff, 0x00ffffff, 1, 2, TRUE, FALSE);
                 HeapFree(GetProcessHeap(), 0, ptStackCopy);
                 SelectObject(hSelDC, hSelBm = CreateDIBWithProperties(RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src)));
-                resetToU1();
+                imageModel.ResetToPrevious();
                 MaskBlt(hSelDC, 0, 0, RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), hDrawingDC, rectSel_src.left,
                         rectSel_src.top, hSelMask, 0, 0, MAKEROP4(SRCCOPY, WHITENESS));
                 Poly(hdc, ptStack, ptSP + 1, bg, bg, 1, 2, TRUE, FALSE);
-                newReversible();
+                imageModel.CopyPrevious();
 
                 MaskBlt(hDrawingDC, rectSel_src.left, rectSel_src.top, RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), hSelDC, 0,
                         0, hSelMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND));
@@ -291,7 +291,7 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             break;
         }
         case TOOL_RECTSEL:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if ((RECT_WIDTH(rectSel_src) != 0) && (RECT_HEIGHT(rectSel_src) != 0))
             {
                 DeleteObject(hSelMask);
@@ -299,12 +299,12 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
                 DeleteObject(SelectObject(hSelDC, hSelMask));
                 Rect(hSelDC, 0, 0, RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), 0x00ffffff, 0x00ffffff, 1, 2);
                 SelectObject(hSelDC, hSelBm = CreateDIBWithProperties(RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src)));
-                resetToU1();
+                imageModel.ResetToPrevious();
                 BitBlt(hSelDC, 0, 0, RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), hDrawingDC, rectSel_src.left,
                        rectSel_src.top, SRCCOPY);
                 Rect(hdc, rectSel_src.left, rectSel_src.top, rectSel_src.right,
                      rectSel_src.bottom, bg, bg, 0, TRUE);
-                newReversible();
+                imageModel.CopyPrevious();
 
                 BitBlt(hDrawingDC, rectSel_src.left, rectSel_src.top, RECT_WIDTH(rectSel_src), RECT_HEIGHT(rectSel_src), hSelDC, 0,
                        0, SRCCOPY);
@@ -315,10 +315,10 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             }
             break;
         case TOOL_TEXT:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if ((RECT_WIDTH(rectSel_src) != 0) && (RECT_HEIGHT(rectSel_src) != 0))
             {
-                newReversible();
+                imageModel.CopyPrevious();
 
                 placeSelWin();
                 selectionWindow.ShowWindow(SW_SHOW);
@@ -333,7 +333,7 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             SetPixel(hdc, x, y, fg);
             break;
         case TOOL_LINE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 roundTo8Directions(start.x, start.y, &x, &y);
             Line(hdc, start.x, start.y, x, y, fg, toolsModel.GetLineWidth());
@@ -344,13 +344,13 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
                 pointSP = 0;
             break;
         case TOOL_RECT:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             Rect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_SHAPE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             pointStack[pointSP].x = x;
             pointStack[pointSP].y = y;
             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
@@ -374,13 +374,13 @@ endPaintingL(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
                 pointSP--;
             break;
         case TOOL_ELLIPSE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             Ellp(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_RRECT:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             RRect(hdc, start.x, start.y, x, y, fg, bg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
@@ -403,26 +403,26 @@ startPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
         case TOOL_RECT:
         case TOOL_ELLIPSE:
         case TOOL_RRECT:
-            newReversible();
+            imageModel.CopyPrevious();
             break;
         case TOOL_RUBBER:
-            newReversible();
+            imageModel.CopyPrevious();
             Replace(hdc, x, y, x, y, fg, bg, toolsModel.GetRubberRadius());
             break;
         case TOOL_FILL:
-            newReversible();
+            imageModel.CopyPrevious();
             Fill(hdc, x, y, bg);
             break;
         case TOOL_PEN:
-            newReversible();
+            imageModel.CopyPrevious();
             SetPixel(hdc, x, y, bg);
             break;
         case TOOL_BRUSH:
-            newReversible();
+            imageModel.CopyPrevious();
             Brush(hdc, x, y, x, y, bg, toolsModel.GetBrushStyle());
             break;
         case TOOL_AIRBRUSH:
-            newReversible();
+            imageModel.CopyPrevious();
             Airbrush(hdc, x, y, bg, toolsModel.GetAirBrushWidth());
             break;
         case TOOL_BEZIER:
@@ -430,7 +430,7 @@ startPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             pointStack[pointSP].y = y;
             if (pointSP == 0)
             {
-                newReversible();
+                imageModel.CopyPrevious();
                 pointSP++;
             }
             break;
@@ -441,7 +441,7 @@ startPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
                 Poly(hdc, pointStack, pointSP + 1, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
             if (pointSP == 0)
             {
-                newReversible();
+                imageModel.CopyPrevious();
                 pointSP++;
             }
             break;
@@ -466,13 +466,13 @@ whilePaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             Airbrush(hdc, x, y, bg, toolsModel.GetAirBrushWidth());
             break;
         case TOOL_LINE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 roundTo8Directions(start.x, start.y, &x, &y);
             Line(hdc, start.x, start.y, x, y, bg, toolsModel.GetLineWidth());
             break;
         case TOOL_BEZIER:
-            resetToU1();
+            imageModel.ResetToPrevious();
             pointStack[pointSP].x = x;
             pointStack[pointSP].y = y;
             switch (pointSP)
@@ -490,13 +490,13 @@ whilePaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             }
             break;
         case TOOL_RECT:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             Rect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_SHAPE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             pointStack[pointSP].x = x;
             pointStack[pointSP].y = y;
             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
@@ -506,13 +506,13 @@ whilePaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
                 Poly(hdc, pointStack, pointSP + 1, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle(), FALSE, FALSE);
             break;
         case TOOL_ELLIPSE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             Ellp(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_RRECT:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             RRect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
@@ -536,7 +536,7 @@ endPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
             SetPixel(hdc, x, y, bg);
             break;
         case TOOL_LINE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 roundTo8Directions(start.x, start.y, &x, &y);
             Line(hdc, start.x, start.y, x, y, bg, toolsModel.GetLineWidth());
@@ -547,13 +547,13 @@ endPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
                 pointSP = 0;
             break;
         case TOOL_RECT:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             Rect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_SHAPE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             pointStack[pointSP].x = x;
             pointStack[pointSP].y = y;
             if ((pointSP > 0) && (GetAsyncKeyState(VK_SHIFT) < 0))
@@ -577,13 +577,13 @@ endPaintingR(HDC hdc, LONG x, LONG y, COLORREF fg, COLORREF bg)
                 pointSP--;
             break;
         case TOOL_ELLIPSE:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             Ellp(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
             break;
         case TOOL_RRECT:
-            resetToU1();
+            imageModel.ResetToPrevious();
             if (GetAsyncKeyState(VK_SHIFT) < 0)
                 regularize(start.x, start.y, &x, &y);
             RRect(hdc, start.x, start.y, x, y, bg, fg, toolsModel.GetLineWidth(), toolsModel.GetShapeStyle());
index 8efc15b..3f46a9d 100644 (file)
@@ -74,8 +74,8 @@ LRESULT CScrollboxWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
         }
         scrollboxWindow.SetScrollInfo(SB_HORZ, &si);
         scrlClientWindow.MoveWindow(-scrollboxWindow.GetScrollPos(SB_HORZ),
-                   -scrollboxWindow.GetScrollPos(SB_VERT), imgXRes * toolsModel.GetZoom() / 1000 + 6,
-                   imgYRes * toolsModel.GetZoom() / 1000 + 6, TRUE);
+                   -scrollboxWindow.GetScrollPos(SB_VERT), imageModel.GetWidth() * toolsModel.GetZoom() / 1000 + 6,
+                   imageModel.GetHeight() * toolsModel.GetZoom() / 1000 + 6, TRUE);
     }
     return 0;
 }
@@ -109,8 +109,8 @@ LRESULT CScrollboxWindow::OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
         }
         scrollboxWindow.SetScrollInfo(SB_VERT, &si);
         scrlClientWindow.MoveWindow(-scrollboxWindow.GetScrollPos(SB_HORZ),
-                   -scrollboxWindow.GetScrollPos(SB_VERT), imgXRes * toolsModel.GetZoom() / 1000 + 6,
-                   imgYRes * toolsModel.GetZoom() / 1000 + 6, TRUE);
+                   -scrollboxWindow.GetScrollPos(SB_VERT), imageModel.GetWidth() * toolsModel.GetZoom() / 1000 + 6,
+                   imageModel.GetHeight() * toolsModel.GetZoom() / 1000 + 6, TRUE);
     }
     return 0;
 }
index 92f7f8c..3016dca 100644 (file)
@@ -175,7 +175,7 @@ LRESULT CSelectionWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, B
     {
         TCHAR sizeStr[100];
         POINT deltaUsed;
-        resetToU1();
+        imageModel.ResetToPrevious();
         frac.x += GET_X_LPARAM(lParam) - pos.x;
         frac.y += GET_Y_LPARAM(lParam) - pos.y;
         delta.x += frac.x * 1000 / toolsModel.GetZoom();
index d8bdb6d..0af047a 100644 (file)
@@ -45,6 +45,8 @@ LRESULT CSizeboxWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
         TCHAR sizeStr[100];
         short xRel;
         short yRel;
+        int imgXRes = imageModel.GetWidth();
+        int imgYRes = imageModel.GetHeight();
         xRel = (GET_X_LPARAM(lParam) - xOrig) * 1000 / toolsModel.GetZoom();
         yRel = (GET_Y_LPARAM(lParam) - yOrig) * 1000 / toolsModel.GetZoom();
         if (m_hWnd == sizeboxLeftTop.m_hWnd)
@@ -76,24 +78,26 @@ LRESULT CSizeboxWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
         short yRel;
         ReleaseCapture();
         resizing = FALSE;
+        int imgXRes = imageModel.GetWidth();
+        int imgYRes = imageModel.GetHeight();
         xRel = (GET_X_LPARAM(lParam) - xOrig) * 1000 / toolsModel.GetZoom();
         yRel = (GET_Y_LPARAM(lParam) - yOrig) * 1000 / toolsModel.GetZoom();
         if (m_hWnd == sizeboxLeftTop)
-            cropReversible(imgXRes - xRel, imgYRes - yRel, xRel, yRel);
+            imageModel.Crop(imgXRes - xRel, imgYRes - yRel, xRel, yRel);
         if (m_hWnd == sizeboxCenterTop.m_hWnd)
-            cropReversible(imgXRes, imgYRes - yRel, 0, yRel);
+            imageModel.Crop(imgXRes, imgYRes - yRel, 0, yRel);
         if (m_hWnd == sizeboxRightTop.m_hWnd)
-            cropReversible(imgXRes + xRel, imgYRes - yRel, 0, yRel);
+            imageModel.Crop(imgXRes + xRel, imgYRes - yRel, 0, yRel);
         if (m_hWnd == sizeboxLeftCenter.m_hWnd)
-            cropReversible(imgXRes - xRel, imgYRes, xRel, 0);
+            imageModel.Crop(imgXRes - xRel, imgYRes, xRel, 0);
         if (m_hWnd == sizeboxRightCenter.m_hWnd)
-            cropReversible(imgXRes + xRel, imgYRes, 0, 0);
+            imageModel.Crop(imgXRes + xRel, imgYRes, 0, 0);
         if (m_hWnd == sizeboxLeftBottom.m_hWnd)
-            cropReversible(imgXRes - xRel, imgYRes + yRel, xRel, 0);
+            imageModel.Crop(imgXRes - xRel, imgYRes + yRel, xRel, 0);
         if (m_hWnd == sizeboxCenterBottom.m_hWnd)
-            cropReversible(imgXRes, imgYRes + yRel, 0, 0);
+            imageModel.Crop(imgXRes, imgYRes + yRel, 0, 0);
         if (m_hWnd == sizeboxRightBottom.m_hWnd)
-            cropReversible(imgXRes + xRel, imgYRes + yRel, 0, 0);
+            imageModel.Crop(imgXRes + xRel, imgYRes + yRel, 0, 0);
         SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) _T(""));
     }
     return 0;
index 7c4cc82..109296d 100644 (file)
 
 /* FUNCTIONS ********************************************************/
 
-void
-updateCanvasAndScrollbars()
-{
-    selectionWindow.ShowWindow(SW_HIDE);
-    imageArea.MoveWindow(3, 3, imgXRes * toolsModel.GetZoom() / 1000, imgYRes * toolsModel.GetZoom() / 1000, FALSE);
-    scrollboxWindow.Invalidate(TRUE);
-    imageArea.Invalidate(FALSE);
-
-    scrollboxWindow.SetScrollPos(SB_HORZ, 0, TRUE);
-    scrollboxWindow.SetScrollPos(SB_VERT, 0, TRUE);
-}
-
 void
 zoomTo(int newZoom, int mouseX, int mouseY)
 {
@@ -44,7 +32,7 @@ zoomTo(int newZoom, int mouseX, int mouseY)
     toolsModel.SetZoom(newZoom);
 
     selectionWindow.ShowWindow(SW_HIDE);
-    imageArea.MoveWindow(3, 3, imgXRes * toolsModel.GetZoom() / 1000, imgYRes * toolsModel.GetZoom() / 1000, FALSE);
+    imageArea.MoveWindow(3, 3, imageModel.GetWidth() * toolsModel.GetZoom() / 1000, imageModel.GetHeight() * toolsModel.GetZoom() / 1000, FALSE);
     scrollboxWindow.Invalidate(TRUE);
     imageArea.Invalidate(FALSE);
 
@@ -87,23 +75,19 @@ void CMainWindow::saveImage(BOOL overwrite)
 {
     if (isAFile && overwrite)
     {
-        SaveDIBToFile(hBms[currInd], filepathname, hDrawingDC, &fileTime, &fileSize, fileHPPM,
-                      fileVPPM);
-        imageSaved = TRUE;
+        imageModel.SaveImage(filepathname);
     }
     else if (GetSaveFileName(&sfn) != 0)
     {
         TCHAR tempstr[1000];
         TCHAR resstr[100];
-        SaveDIBToFile(hBms[currInd], sfn.lpstrFile, hDrawingDC, &fileTime, &fileSize,
-                      fileHPPM, fileVPPM);
+        imageModel.SaveImage(sfn.lpstrFile);
         CopyMemory(filename, sfn.lpstrFileTitle, sizeof(filename));
         CopyMemory(filepathname, sfn.lpstrFile, sizeof(filepathname));
         LoadString(hProgInstance, IDS_WINDOWTITLE, resstr, SIZEOF(resstr));
         _stprintf(tempstr, resstr, filename);
         SetWindowText(tempstr);
         isAFile = TRUE;
-        imageSaved = TRUE;
     }
 }
 
@@ -111,14 +95,13 @@ void CMainWindow::UpdateApplicationProperties(HBITMAP bitmap, LPTSTR newfilename
 {
     TCHAR tempstr[1000];
     TCHAR resstr[100];
-    insertReversible(bitmap);
-    updateCanvasAndScrollbars();
+    imageModel.Insert(bitmap);
     CopyMemory(filename, newfilename, sizeof(filename));
     CopyMemory(filepathname, newfilepathname, sizeof(filepathname));
     LoadString(hProgInstance, IDS_WINDOWTITLE, resstr, SIZEOF(resstr));
     _stprintf(tempstr, resstr, filename);
     SetWindowText(tempstr);
-    clearHistory();
+    imageModel.ClearHistory();
     isAFile = TRUE;
 }
 
@@ -134,7 +117,7 @@ void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP bitmap, HWND window)
     DeleteObject(SelectObject(hSelDC, hSelBm = (HBITMAP) CopyImage(bitmap,
                                                                    IMAGE_BITMAP, 0, 0,
                                                                    LR_COPYRETURNORG)));
-    newReversible();
+    imageModel.CopyPrevious();
     SetRectEmpty(&rectSel_src);
     rectSel_dest.left = rectSel_dest.top = 0;
     rectSel_dest.right = rectSel_dest.left + GetDIBWidth(hSelBm);
@@ -189,7 +172,7 @@ LRESULT CMainWindow::OnDestroy(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
 
 LRESULT CMainWindow::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    if (!imageSaved)
+    if (!imageModel.IsImageSaved())
     {
         TCHAR programname[20];
         TCHAR saveprompttext[100];
@@ -204,7 +187,7 @@ LRESULT CMainWindow::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHan
                 break;
             case IDYES:
                 saveImage(FALSE);
-                if (imageSaved)
+                if (imageModel.IsImageSaved())
                     DestroyWindow();
                 break;
         }
@@ -228,8 +211,8 @@ LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM wParam, LPARAM lParam, BO
             EnableMenuItem(menu, IDM_FILEASWALLPAPERSTRETCHED, ENABLED_IF(isAFile));
             break;
         case 1: /* Edit menu */
-            EnableMenuItem(menu, IDM_EDITUNDO, ENABLED_IF(undoSteps > 0));
-            EnableMenuItem(menu, IDM_EDITREDO, ENABLED_IF(redoSteps > 0));
+            EnableMenuItem(menu, IDM_EDITUNDO, ENABLED_IF(imageModel.HasUndoSteps()));
+            EnableMenuItem(menu, IDM_EDITREDO, ENABLED_IF(imageModel.HasRedoSteps()));
             EnableMenuItem(menu, IDM_EDITCUT,  ENABLED_IF(trueSelection));
             EnableMenuItem(menu, IDM_EDITCOPY, ENABLED_IF(trueSelection));
             EnableMenuItem(menu, IDM_EDITDELETESELECTION, ENABLED_IF(trueSelection));
@@ -344,7 +327,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
         case IDM_FILENEW:
         {
             BOOL reset = TRUE;
-            if (!imageSaved)
+            if (!imageModel.IsImageSaved())
             {
                 TCHAR programname[20];
                 TCHAR saveprompttext[100];
@@ -355,7 +338,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
                 switch (MessageBox(temptext, programname, MB_YESNOCANCEL | MB_ICONQUESTION))
                 {
                     case IDNO:
-                        imageSaved = TRUE;
+                        imageModel.imageSaved = TRUE; //TODO: move to ImageModel
                         break;
                     case IDYES:
                         saveImage(FALSE);
@@ -365,12 +348,10 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
                         break;
                 }
             }
-            if (reset && imageSaved)
+            if (reset && imageModel.IsImageSaved()) //TODO: move to ImageModel
             {
-                Rectangle(hDrawingDC, 0 - 1, 0 - 1, imgXRes + 1, imgYRes + 1);
-                imageArea.Invalidate(FALSE);
-                updateCanvasAndScrollbars();
-                clearHistory();
+                imageModel.Clear();
+                imageModel.ClearHistory();
             }
             break;
         }
@@ -401,11 +382,11 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
             SetWallpaper(filepathname, 2, 0);
             break;
         case IDM_EDITUNDO:
-            undo();
+            imageModel.Undo();
             imageArea.Invalidate(FALSE);
             break;
         case IDM_EDITREDO:
-            redo();
+            imageModel.Redo();
             imageArea.Invalidate(FALSE);
             break;
         case IDM_EDITCOPY:
@@ -432,16 +413,16 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
         {
             /* remove selection window and already painted content using undo(),
             paint Rect for rectangular selections and Poly for freeform selections */
-            undo();
+            imageModel.Undo();
             if (toolsModel.GetActiveTool() == TOOL_RECTSEL)
             {
-                newReversible();
+                imageModel.CopyPrevious();
                 Rect(hDrawingDC, rectSel_dest.left, rectSel_dest.top, rectSel_dest.right,
                      rectSel_dest.bottom, paletteModel.GetBgColor(), paletteModel.GetBgColor(), 0, TRUE);
             }
             if (toolsModel.GetActiveTool() == TOOL_FREESEL)
             {
-                newReversible();
+                imageModel.CopyPrevious();
                 Poly(hDrawingDC, ptStack, ptSP + 1, 0, 0, 2, 0, FALSE, TRUE);
             }
             break;
@@ -451,9 +432,10 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
             HWND hToolbar = FindWindowEx(toolBoxContainer.m_hWnd, NULL, TOOLBARCLASSNAME, NULL);
             SendMessage(hToolbar, TB_CHECKBUTTON, ID_RECTSEL, MAKELPARAM(TRUE, 0));
             toolBoxContainer.SendMessage(WM_COMMAND, ID_RECTSEL);
+            //TODO: do this properly
             startPaintingL(hDrawingDC, 0, 0, paletteModel.GetFgColor(), paletteModel.GetBgColor());
-            whilePaintingL(hDrawingDC, imgXRes, imgYRes, paletteModel.GetFgColor(), paletteModel.GetBgColor());
-            endPaintingL(hDrawingDC, imgXRes, imgYRes, paletteModel.GetFgColor(), paletteModel.GetBgColor());
+            whilePaintingL(hDrawingDC, imageModel.GetWidth(), imageModel.GetHeight(), paletteModel.GetFgColor(), paletteModel.GetBgColor());
+            endPaintingL(hDrawingDC, imageModel.GetWidth(), imageModel.GetHeight(), paletteModel.GetFgColor(), paletteModel.GetBgColor());
             break;
         }
         case IDM_EDITCOPYTO:
@@ -474,31 +456,22 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
             break;
         case IDM_COLORSEDITPALETTE:
             if (ChooseColor(&choosecolor))
-            {
                 paletteModel.SetFgColor(choosecolor.rgbResult);
-                paletteWindow.Invalidate(FALSE);
-            }
             break;
         case IDM_COLORSMODERNPALETTE:
             paletteModel.SelectPalette(1);
-            paletteWindow.Invalidate(FALSE);
             break;
         case IDM_COLORSOLDPALETTE:
             paletteModel.SelectPalette(2);
-            paletteWindow.Invalidate(FALSE);
             break;
         case IDM_IMAGEINVERTCOLORS:
         {
-            RECT tempRect;
-            newReversible();
-            SetRect(&tempRect, 0, 0, imgXRes, imgYRes);
-            InvertRect(hDrawingDC, &tempRect);
-            imageArea.Invalidate(FALSE);
+            imageModel.InvertColors();
             break;
         }
         case IDM_IMAGEDELETEIMAGE:
-            newReversible();
-            Rect(hDrawingDC, 0, 0, imgXRes, imgYRes, paletteModel.GetBgColor(), paletteModel.GetBgColor(), 0, TRUE);
+            imageModel.CopyPrevious();
+            Rect(hDrawingDC, 0, 0, imageModel.GetWidth(), imageModel.GetHeight(), paletteModel.GetBgColor(), paletteModel.GetBgColor(), 0, TRUE);
             imageArea.Invalidate(FALSE);
             break;
         case IDM_IMAGEROTATEMIRROR:
@@ -517,9 +490,9 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
                     }
                     else
                     {
-                        newReversible();
-                        StretchBlt(hDrawingDC, imgXRes - 1, 0, -imgXRes, imgYRes, hDrawingDC, 0, 0,
-                                   imgXRes, imgYRes, SRCCOPY);
+                        imageModel.CopyPrevious();
+                        StretchBlt(hDrawingDC, imageModel.GetWidth() - 1, 0, -imageModel.GetWidth(), imageModel.GetHeight(), hDrawingDC, 0, 0,
+                                   imageModel.GetWidth(), imageModel.GetHeight(), SRCCOPY);
                         imageArea.Invalidate(FALSE);
                     }
                     break;
@@ -536,9 +509,9 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
                     }
                     else
                     {
-                        newReversible();
-                        StretchBlt(hDrawingDC, 0, imgYRes - 1, imgXRes, -imgYRes, hDrawingDC, 0, 0,
-                                   imgXRes, imgYRes, SRCCOPY);
+                        imageModel.CopyPrevious();
+                        StretchBlt(hDrawingDC, 0, imageModel.GetHeight() - 1, imageModel.GetWidth(), -imageModel.GetHeight(), hDrawingDC, 0, 0,
+                                   imageModel.GetWidth(), imageModel.GetHeight(), SRCCOPY);
                         imageArea.Invalidate(FALSE);
                     }
                     break;
@@ -557,9 +530,9 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
                     }
                     else
                     {
-                        newReversible();
-                        StretchBlt(hDrawingDC, imgXRes - 1, imgYRes - 1, -imgXRes, -imgYRes, hDrawingDC,
-                                   0, 0, imgXRes, imgYRes, SRCCOPY);
+                        imageModel.CopyPrevious();
+                        StretchBlt(hDrawingDC, imageModel.GetWidth() - 1, imageModel.GetHeight() - 1, -imageModel.GetWidth(), -imageModel.GetHeight(), hDrawingDC,
+                                   0, 0, imageModel.GetWidth(), imageModel.GetHeight(), SRCCOPY);
                         imageArea.Invalidate(FALSE);
                     }
                     break;
@@ -571,8 +544,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
         {
             if (attributesDlg())
             {
-                cropReversible(widthSetInDlg, heightSetInDlg, 0, 0);
-                updateCanvasAndScrollbars();
+                imageModel.Crop(widthSetInDlg, heightSetInDlg, 0, 0);
             }
             break;
         }
@@ -580,10 +552,8 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
         {
             if (changeSizeDlg())
             {
-                insertReversible((HBITMAP) CopyImage(hBms[currInd], IMAGE_BITMAP,
-                                                     imgXRes * stretchSkew.percentage.x / 100,
-                                                     imgYRes * stretchSkew.percentage.y / 100, 0));
-                updateCanvasAndScrollbars();
+                imageModel.StretchSkew(stretchSkew.percentage.x, stretchSkew.percentage.y,
+                                       stretchSkew.angle.x, stretchSkew.angle.y);
             }
             break;
         }
@@ -591,8 +561,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
             toolsModel.SetBackgroundTransparent(!toolsModel.IsBackgroundTransparent());
             break;
         case IDM_IMAGECROP:
-            insertReversible((HBITMAP) CopyImage(hSelBm, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG));
-            updateCanvasAndScrollbars();
+            imageModel.Insert((HBITMAP) CopyImage(hSelBm, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG));
             break;
 
         case IDM_VIEWTOOLBOX: