https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9f56e67bc2f25b21ce7870f922855945acb8895a

commit 9f56e67bc2f25b21ce7870f922855945acb8895a
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sun Jun 18 19:48:20 2023 +0900
Commit:     GitHub <[email protected]>
CommitDate: Sun Jun 18 19:48:20 2023 +0900

    [MSPAINT] Use CF_DIB instead of CF_BITMAP (#5349)
    
    CF_BITMAP is not recommended format for copying. In fact, Win10 won't 
accept it.
    - Use CF_DIB clipboard format instead of CF_BITMAP in copying.
    - Use CF_ENHMETAFILE, CF_DIB, or CF_BITMAP in pasting.
    - Add BitmapToClipboardDIB, BitmapFromClipboardDIB, and BitmapFromHEMF 
helper functions to dib.cpp.
    - Re-enable paste by fixing the bug that is embugged in the previous commit.
    - Enable Cut, Copy, Paste, and Delete on text editing box by modifying 
OnInitMenuPopup.
    - Add IDS_CANTPASTE resource string to show message on paste failure.
    CORE-18867
---
 base/applications/mspaint/dib.cpp            | 132 +++++++++++++++++++++++++
 base/applications/mspaint/dib.h              |   4 +
 base/applications/mspaint/lang/bg-BG.rc      |   1 +
 base/applications/mspaint/lang/cs-CZ.rc      |   1 +
 base/applications/mspaint/lang/de-DE.rc      |   1 +
 base/applications/mspaint/lang/en-GB.rc      |   1 +
 base/applications/mspaint/lang/en-US.rc      |   1 +
 base/applications/mspaint/lang/es-ES.rc      |   1 +
 base/applications/mspaint/lang/et-EE.rc      |   1 +
 base/applications/mspaint/lang/eu-ES.rc      |   1 +
 base/applications/mspaint/lang/fr-FR.rc      |   1 +
 base/applications/mspaint/lang/he-IL.rc      |   1 +
 base/applications/mspaint/lang/hu-HU.rc      |   1 +
 base/applications/mspaint/lang/id-ID.rc      |   1 +
 base/applications/mspaint/lang/it-IT.rc      |   1 +
 base/applications/mspaint/lang/ja-JP.rc      |   1 +
 base/applications/mspaint/lang/nl-NL.rc      |   1 +
 base/applications/mspaint/lang/no-NO.rc      |   1 +
 base/applications/mspaint/lang/pl-PL.rc      |   1 +
 base/applications/mspaint/lang/pt-BR.rc      |   1 +
 base/applications/mspaint/lang/pt-PT.rc      |   1 +
 base/applications/mspaint/lang/ro-RO.rc      |   1 +
 base/applications/mspaint/lang/ru-RU.rc      |   1 +
 base/applications/mspaint/lang/sk-SK.rc      |   1 +
 base/applications/mspaint/lang/sq-AL.rc      |   1 +
 base/applications/mspaint/lang/sv-SE.rc      |   1 +
 base/applications/mspaint/lang/tr-TR.rc      |   1 +
 base/applications/mspaint/lang/uk-UA.rc      |   1 +
 base/applications/mspaint/lang/vi-VN.rc      |   1 +
 base/applications/mspaint/lang/zh-CN.rc      |   1 +
 base/applications/mspaint/lang/zh-HK.rc      |   1 +
 base/applications/mspaint/lang/zh-TW.rc      |   1 +
 base/applications/mspaint/mouse.cpp          |   9 +-
 base/applications/mspaint/resource.h         |   1 +
 base/applications/mspaint/selectionmodel.cpp |   8 +-
 base/applications/mspaint/textedit.cpp       |  29 ++++--
 base/applications/mspaint/textedit.h         |   6 ++
 base/applications/mspaint/winproc.cpp        | 142 +++++++++++++++++++++------
 38 files changed, 318 insertions(+), 43 deletions(-)

diff --git a/base/applications/mspaint/dib.cpp 
b/base/applications/mspaint/dib.cpp
index 85472994639..cb34859bd56 100644
--- a/base/applications/mspaint/dib.cpp
+++ b/base/applications/mspaint/dib.cpp
@@ -333,3 +333,135 @@ HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL 
bVertical)
     DeleteDC(hDC2);
     return hbmNew;
 }
+
+struct BITMAPINFODX : BITMAPINFO
+{
+    RGBQUAD bmiColorsAdditional[256 - 1];
+};
+
+HGLOBAL BitmapToClipboardDIB(HBITMAP hBitmap)
+{
+    BITMAP bm;
+    if (!GetObject(hBitmap, sizeof(BITMAP), &bm))
+        return NULL;
+
+    BITMAPINFODX bmi;
+    ZeroMemory(&bmi, sizeof(bmi));
+    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bmi.bmiHeader.biWidth = bm.bmWidth;
+    bmi.bmiHeader.biHeight = bm.bmHeight;
+    bmi.bmiHeader.biPlanes = 1;
+    bmi.bmiHeader.biBitCount = bm.bmBitsPixel;
+    bmi.bmiHeader.biCompression = BI_RGB;
+    bmi.bmiHeader.biSizeImage = bm.bmWidthBytes * bm.bmHeight;
+
+    INT cColors;
+    if (bm.bmBitsPixel < 16)
+        cColors = 1 << bm.bmBitsPixel;
+    else
+        cColors = 0;
+
+    HDC hDC = CreateCompatibleDC(NULL);
+
+    if (cColors)
+    {
+        HGDIOBJ hbmOld = SelectObject(hDC, hBitmap);
+        cColors = GetDIBColorTable(hDC, 0, cColors, bmi.bmiColors);
+        SelectObject(hDC, hbmOld);
+    }
+
+    DWORD cbColors = cColors * sizeof(RGBQUAD);
+    DWORD dwSize = sizeof(BITMAPINFOHEADER) + cbColors + 
bmi.bmiHeader.biSizeImage;
+    HGLOBAL hGlobal = GlobalAlloc(GHND | GMEM_SHARE, dwSize);
+    if (hGlobal)
+    {
+        LPBYTE pb = (LPBYTE)GlobalLock(hGlobal);
+        if (pb)
+        {
+            CopyMemory(pb, &bmi, sizeof(BITMAPINFOHEADER));
+            pb += sizeof(BITMAPINFOHEADER);
+
+            CopyMemory(pb, bmi.bmiColors, cbColors);
+            pb += cbColors;
+
+            GetDIBits(hDC, hBitmap, 0, bm.bmHeight, pb, &bmi, DIB_RGB_COLORS);
+
+            GlobalUnlock(hGlobal);
+        }
+        else
+        {
+            GlobalFree(hGlobal);
+            hGlobal = NULL;
+        }
+    }
+
+    DeleteDC(hDC);
+
+    return hGlobal;
+}
+
+HBITMAP BitmapFromClipboardDIB(HGLOBAL hGlobal)
+{
+    LPBYTE pb = (LPBYTE)GlobalLock(hGlobal);
+    if (!pb)
+        return NULL;
+
+    LPBITMAPINFO pbmi = (LPBITMAPINFO)pb;
+    pb += pbmi->bmiHeader.biSize;
+
+    INT cColors = 0, cbColors = 0;
+    if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+    {
+        LPBITMAPCOREINFO pbmci = (LPBITMAPCOREINFO)pbmi;
+        WORD BitCount = pbmci->bmciHeader.bcBitCount;
+        if (BitCount < 16)
+        {
+            cColors = (1 << BitCount);
+            cbColors = cColors * sizeof(RGBTRIPLE);
+            pb += cbColors;
+        }
+    }
+    else if (pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
+    {
+        WORD BitCount = pbmi->bmiHeader.biBitCount;
+        if (BitCount < 16)
+        {
+            cColors = (1 << BitCount);
+            cbColors = cColors * sizeof(RGBQUAD);
+            pb += cbColors;
+        }
+    }
+
+    HDC hDC = CreateCompatibleDC(NULL);
+    HBITMAP hBitmap = CreateDIBSection(hDC, pbmi, DIB_RGB_COLORS, NULL, NULL, 
0);
+    if (hBitmap)
+    {
+        SetDIBits(hDC, hBitmap, 0, labs(pbmi->bmiHeader.biHeight), pb, pbmi, 
DIB_RGB_COLORS);
+    }
+    DeleteDC(hDC);
+
+    GlobalUnlock(hGlobal);
+
+    return hBitmap;
+}
+
+HBITMAP BitmapFromHEMF(HENHMETAFILE hEMF)
+{
+    ENHMETAHEADER header;
+    if (!GetEnhMetaFileHeader(hEMF, sizeof(header), &header))
+        return NULL;
+
+    CRect rc = *(LPRECT)&header.rclBounds;
+    INT cx = rc.Width(), cy = rc.Height();
+    HBITMAP hbm = CreateColorDIB(cx, cy, RGB(255, 255, 255));
+    if (!hbm)
+        return NULL;
+
+    HDC hDC = CreateCompatibleDC(NULL);
+    HGDIOBJ hbmOld = SelectObject(hDC, hbm);
+    PlayEnhMetaFile(hDC, hEMF, &rc);
+    SelectObject(hDC, hbmOld);
+    DeleteDC(hDC);
+
+    return hbm;
+}
diff --git a/base/applications/mspaint/dib.h b/base/applications/mspaint/dib.h
index f4043d83ca3..4958f612673 100644
--- a/base/applications/mspaint/dib.h
+++ b/base/applications/mspaint/dib.h
@@ -36,3 +36,7 @@ HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL 
bVertical);
 float PpcmFromDpi(float dpi);
 
 #define ROUND(x) (INT)((x) + 0.5)
+
+HGLOBAL BitmapToClipboardDIB(HBITMAP hBitmap);
+HBITMAP BitmapFromClipboardDIB(HGLOBAL hGlobal);
+HBITMAP BitmapFromHEMF(HENHMETAFILE hEMF);
diff --git a/base/applications/mspaint/lang/bg-BG.rc 
b/base/applications/mspaint/lang/bg-BG.rc
index 5c0e13f0f1c..49fdda7a16b 100644
--- a/base/applications/mspaint/lang/bg-BG.rc
+++ b/base/applications/mspaint/lang/bg-BG.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Подчертан"
     IDS_VERTICAL "Вертикален"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/cs-CZ.rc 
b/base/applications/mspaint/lang/cs-CZ.rc
index 134b16d83e5..40d16e29cf5 100644
--- a/base/applications/mspaint/lang/cs-CZ.rc
+++ b/base/applications/mspaint/lang/cs-CZ.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/de-DE.rc 
b/base/applications/mspaint/lang/de-DE.rc
index b4479752bd2..6901a9ce68e 100644
--- a/base/applications/mspaint/lang/de-DE.rc
+++ b/base/applications/mspaint/lang/de-DE.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/en-GB.rc 
b/base/applications/mspaint/lang/en-GB.rc
index afe0dac8147..c2590081acb 100644
--- a/base/applications/mspaint/lang/en-GB.rc
+++ b/base/applications/mspaint/lang/en-GB.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d dots per inch"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/en-US.rc 
b/base/applications/mspaint/lang/en-US.rc
index 2f28cbe4bec..408a60bc505 100644
--- a/base/applications/mspaint/lang/en-US.rc
+++ b/base/applications/mspaint/lang/en-US.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d dots per inch"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/es-ES.rc 
b/base/applications/mspaint/lang/es-ES.rc
index 29eca278eca..782968cbd1b 100644
--- a/base/applications/mspaint/lang/es-ES.rc
+++ b/base/applications/mspaint/lang/es-ES.rc
@@ -244,4 +244,5 @@ BEGIN
     IDS_UNDERLINE "Subrayado"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/et-EE.rc 
b/base/applications/mspaint/lang/et-EE.rc
index 0320598596f..16a381596b8 100644
--- a/base/applications/mspaint/lang/et-EE.rc
+++ b/base/applications/mspaint/lang/et-EE.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/eu-ES.rc 
b/base/applications/mspaint/lang/eu-ES.rc
index 3078614dac8..066460512df 100644
--- a/base/applications/mspaint/lang/eu-ES.rc
+++ b/base/applications/mspaint/lang/eu-ES.rc
@@ -234,4 +234,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/fr-FR.rc 
b/base/applications/mspaint/lang/fr-FR.rc
index 92e2af66317..147b939fb58 100644
--- a/base/applications/mspaint/lang/fr-FR.rc
+++ b/base/applications/mspaint/lang/fr-FR.rc
@@ -234,4 +234,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/he-IL.rc 
b/base/applications/mspaint/lang/he-IL.rc
index 352f668177e..9a381bc4ff4 100644
--- a/base/applications/mspaint/lang/he-IL.rc
+++ b/base/applications/mspaint/lang/he-IL.rc
@@ -237,4 +237,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/hu-HU.rc 
b/base/applications/mspaint/lang/hu-HU.rc
index 8f193665862..ac16396730f 100644
--- a/base/applications/mspaint/lang/hu-HU.rc
+++ b/base/applications/mspaint/lang/hu-HU.rc
@@ -234,4 +234,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/id-ID.rc 
b/base/applications/mspaint/lang/id-ID.rc
index 0113573158a..6e082265cbf 100644
--- a/base/applications/mspaint/lang/id-ID.rc
+++ b/base/applications/mspaint/lang/id-ID.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/it-IT.rc 
b/base/applications/mspaint/lang/it-IT.rc
index 1e880516ac1..0ee7d4f8457 100644
--- a/base/applications/mspaint/lang/it-IT.rc
+++ b/base/applications/mspaint/lang/it-IT.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/ja-JP.rc 
b/base/applications/mspaint/lang/ja-JP.rc
index d771a81e70b..8e6bac2e22e 100644
--- a/base/applications/mspaint/lang/ja-JP.rc
+++ b/base/applications/mspaint/lang/ja-JP.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "下線"
     IDS_VERTICAL "縦書き"
     IDS_PRINTRES "%d x %d ピクセル/cm"
+    IDS_CANTPASTE "申し訳ありませんが、このデータを貼り付けできません。データ形式が間違っているか、対応していません。"
 END
diff --git a/base/applications/mspaint/lang/nl-NL.rc 
b/base/applications/mspaint/lang/nl-NL.rc
index 3de457f22b6..5cb77b29837 100644
--- a/base/applications/mspaint/lang/nl-NL.rc
+++ b/base/applications/mspaint/lang/nl-NL.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/no-NO.rc 
b/base/applications/mspaint/lang/no-NO.rc
index 549d3ae938c..83434aa1a35 100644
--- a/base/applications/mspaint/lang/no-NO.rc
+++ b/base/applications/mspaint/lang/no-NO.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/pl-PL.rc 
b/base/applications/mspaint/lang/pl-PL.rc
index bd61c31ef89..86f1c53bef8 100644
--- a/base/applications/mspaint/lang/pl-PL.rc
+++ b/base/applications/mspaint/lang/pl-PL.rc
@@ -243,4 +243,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/pt-BR.rc 
b/base/applications/mspaint/lang/pt-BR.rc
index 075558c43d9..db0e4a0b2a0 100644
--- a/base/applications/mspaint/lang/pt-BR.rc
+++ b/base/applications/mspaint/lang/pt-BR.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/pt-PT.rc 
b/base/applications/mspaint/lang/pt-PT.rc
index ef8a793a3c1..638eabfe402 100644
--- a/base/applications/mspaint/lang/pt-PT.rc
+++ b/base/applications/mspaint/lang/pt-PT.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Sublinhado"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/ro-RO.rc 
b/base/applications/mspaint/lang/ro-RO.rc
index a92ec1d6913..e6349714f3d 100644
--- a/base/applications/mspaint/lang/ro-RO.rc
+++ b/base/applications/mspaint/lang/ro-RO.rc
@@ -243,4 +243,5 @@ BEGIN
     IDS_UNDERLINE "Subliniat"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/ru-RU.rc 
b/base/applications/mspaint/lang/ru-RU.rc
index b241a712aa2..f65543435cb 100644
--- a/base/applications/mspaint/lang/ru-RU.rc
+++ b/base/applications/mspaint/lang/ru-RU.rc
@@ -234,4 +234,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/sk-SK.rc 
b/base/applications/mspaint/lang/sk-SK.rc
index e2acdc15642..1abab0cd683 100644
--- a/base/applications/mspaint/lang/sk-SK.rc
+++ b/base/applications/mspaint/lang/sk-SK.rc
@@ -243,4 +243,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/sq-AL.rc 
b/base/applications/mspaint/lang/sq-AL.rc
index 368a59c9369..d77521cae5e 100644
--- a/base/applications/mspaint/lang/sq-AL.rc
+++ b/base/applications/mspaint/lang/sq-AL.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/sv-SE.rc 
b/base/applications/mspaint/lang/sv-SE.rc
index 55ad9f1953c..8301fe01424 100644
--- a/base/applications/mspaint/lang/sv-SE.rc
+++ b/base/applications/mspaint/lang/sv-SE.rc
@@ -234,4 +234,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/tr-TR.rc 
b/base/applications/mspaint/lang/tr-TR.rc
index 532af08a2e5..227c35fe17b 100644
--- a/base/applications/mspaint/lang/tr-TR.rc
+++ b/base/applications/mspaint/lang/tr-TR.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Altı Çizgili"
     IDS_VERTICAL "Düşey"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/uk-UA.rc 
b/base/applications/mspaint/lang/uk-UA.rc
index 160830d6e6d..00a9e8ea90c 100644
--- a/base/applications/mspaint/lang/uk-UA.rc
+++ b/base/applications/mspaint/lang/uk-UA.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/vi-VN.rc 
b/base/applications/mspaint/lang/vi-VN.rc
index b5741ae9c96..b826a9270bd 100644
--- a/base/applications/mspaint/lang/vi-VN.rc
+++ b/base/applications/mspaint/lang/vi-VN.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "Underline"
     IDS_VERTICAL "Vertical"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/zh-CN.rc 
b/base/applications/mspaint/lang/zh-CN.rc
index 2bc72542710..8aea3b4c409 100644
--- a/base/applications/mspaint/lang/zh-CN.rc
+++ b/base/applications/mspaint/lang/zh-CN.rc
@@ -244,4 +244,5 @@ BEGIN
     IDS_UNDERLINE "下划线"
     IDS_VERTICAL "垂直"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/zh-HK.rc 
b/base/applications/mspaint/lang/zh-HK.rc
index 3f4cf0d1073..ca0db48b6d0 100644
--- a/base/applications/mspaint/lang/zh-HK.rc
+++ b/base/applications/mspaint/lang/zh-HK.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "底線"
     IDS_VERTICAL "垂直"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/lang/zh-TW.rc 
b/base/applications/mspaint/lang/zh-TW.rc
index b404dec54c9..1ed27e4ec36 100644
--- a/base/applications/mspaint/lang/zh-TW.rc
+++ b/base/applications/mspaint/lang/zh-TW.rc
@@ -242,4 +242,5 @@ BEGIN
     IDS_UNDERLINE "底線"
     IDS_VERTICAL "垂直"
     IDS_PRINTRES "%d x %d pixel/cm"
+    IDS_CANTPASTE "Sorry, this application cannot paste this data. The data 
format is either incorrect or not supported."
 END
diff --git a/base/applications/mspaint/mouse.cpp 
b/base/applications/mspaint/mouse.cpp
index 97359f0ce68..b16ae6190b8 100644
--- a/base/applications/mspaint/mouse.cpp
+++ b/base/applications/mspaint/mouse.cpp
@@ -547,7 +547,6 @@ struct TextTool : ToolBase
 
         // Draw the text
         INT style = (toolsModel.IsBackgroundTransparent() ? 0 : 1);
-        imageModel.PushImageForUndo();
         Text(hdc, rc.left, rc.top, rc.right, rc.bottom, m_fg, m_bg, szText,
              textEditWindow.GetFont(), style);
     }
@@ -568,12 +567,11 @@ struct TextTool : ToolBase
         BOOL bTextBoxShown = ::IsWindowVisible(textEditWindow);
         if (bTextBoxShown && textEditWindow.GetWindowTextLength() > 0)
         {
+            imageModel.PushImageForUndo();
             draw(m_hdc);
-
-            if (selectionModel.m_rc.IsRectEmpty())
+            if (::IsRectEmpty(&selectionModel.m_rc))
             {
-                textEditWindow.ShowWindow(SW_HIDE);
-                textEditWindow.SetWindowText(NULL);
+                quit();
                 return;
             }
         }
@@ -613,6 +611,7 @@ struct TextTool : ToolBase
 
     void OnFinishDraw() override
     {
+        imageModel.PushImageForUndo();
         draw(m_hdc);
         quit();
         ToolBase::OnFinishDraw();
diff --git a/base/applications/mspaint/resource.h 
b/base/applications/mspaint/resource.h
index 3be802ced8c..53f17d4c715 100644
--- a/base/applications/mspaint/resource.h
+++ b/base/applications/mspaint/resource.h
@@ -219,3 +219,4 @@
 #define IDS_UNDERLINE   937
 #define IDS_VERTICAL    938
 #define IDS_PRINTRES    939
+#define IDS_CANTPASTE   940
diff --git a/base/applications/mspaint/selectionmodel.cpp 
b/base/applications/mspaint/selectionmodel.cpp
index 9497cef153f..bfa4501d5fc 100644
--- a/base/applications/mspaint/selectionmodel.cpp
+++ b/base/applications/mspaint/selectionmodel.cpp
@@ -205,8 +205,12 @@ void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, 
INT y)
 
     m_rc.left = x;
     m_rc.top = y;
-    m_rc.right = m_rc.left + GetDIBWidth(hBm);
-    m_rc.bottom = m_rc.top + GetDIBHeight(hBm);
+    m_rc.right = x + GetDIBWidth(hBm);
+    m_rc.bottom = y + GetDIBHeight(hBm);
+
+    // If m_rc and m_rcOld were same, the image cannot be pasted to the canvas.
+    // See also SelectionModel::Landing
+    ::SetRect(&m_rcOld, -2, -2, -1, -1); // Outside of image
 
     ClearMask();
 }
diff --git a/base/applications/mspaint/textedit.cpp 
b/base/applications/mspaint/textedit.cpp
index bf0ab2ce4fb..6d84a12c285 100644
--- a/base/applications/mspaint/textedit.cpp
+++ b/base/applications/mspaint/textedit.cpp
@@ -410,15 +410,9 @@ void CTextEditWindow::Reposition()
     CRect rcImage;
     canvasWindow.GetImageRect(rcImage);
 
-    if (rc.bottom > rcImage.bottom)
-        ::OffsetRect(&rc, 0, rcImage.Height());
-
-    if (rc.right > rcImage.right)
-        ::OffsetRect(&rc, rcImage.Width(), 0);
-
+    // FIXME: Smartly restrict the position and size by using 
WM_WINDOWPOSCHANGING
     if (rc.left < 0)
         ::OffsetRect(&rc, -rc.left, 0);
-
     if (rc.top < 0)
         ::OffsetRect(&rc, 0, -rc.top);
 
@@ -433,3 +427,24 @@ LRESULT CTextEditWindow::OnMouseWheel(UINT nMsg, WPARAM 
wParam, LPARAM lParam, B
 {
     return ::SendMessage(GetParent(), nMsg, wParam, lParam);
 }
+
+LRESULT CTextEditWindow::OnCut(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
+{
+    LRESULT ret = DefWindowProc(nMsg, wParam, lParam);
+    Invalidate(TRUE); // Redraw
+    return ret;
+}
+
+LRESULT CTextEditWindow::OnPaste(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
+{
+    LRESULT ret = DefWindowProc(nMsg, wParam, lParam);
+    FixEditPos(NULL);
+    return ret;
+}
+
+LRESULT CTextEditWindow::OnClear(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
+{
+    LRESULT ret = DefWindowProc(nMsg, wParam, lParam);
+    Invalidate(TRUE); // Redraw
+    return ret;
+}
diff --git a/base/applications/mspaint/textedit.h 
b/base/applications/mspaint/textedit.h
index a227ce25714..95fb3e6ca45 100644
--- a/base/applications/mspaint/textedit.h
+++ b/base/applications/mspaint/textedit.h
@@ -45,6 +45,9 @@ public:
         MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown);
         MESSAGE_HANDLER(EM_SETSEL, OnSetSel);
         MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel);
+        MESSAGE_HANDLER(WM_CUT, OnCut);
+        MESSAGE_HANDLER(WM_PASTE, OnPaste);
+        MESSAGE_HANDLER(WM_CLEAR, OnClear);
     END_MSG_MAP()
 
     LRESULT OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
@@ -66,6 +69,9 @@ public:
     LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnSetSel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
+    LRESULT OnCut(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnPaste(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnClear(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
 
 protected:
     HWND m_hwndParent;
diff --git a/base/applications/mspaint/winproc.cpp 
b/base/applications/mspaint/winproc.cpp
index 29bc32b9327..ec714193b7c 100644
--- a/base/applications/mspaint/winproc.cpp
+++ b/base/applications/mspaint/winproc.cpp
@@ -200,9 +200,7 @@ void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP 
bitmap, HWND window)
         }
     }
 
-    HWND hToolbar = FindWindowEx(toolBoxContainer.m_hWnd, NULL, 
TOOLBARCLASSNAME, NULL);
-    SendMessage(hToolbar, TB_CHECKBUTTON, ID_RECTSEL, MAKELPARAM(TRUE, 0));
-    toolBoxContainer.SendMessage(WM_COMMAND, ID_RECTSEL);
+    toolsModel.SetActiveTool(TOOL_RECTSEL);
 
     imageModel.PushImageForUndo();
     selectionModel.InsertFromHBITMAP(bitmap, 0, 0);
@@ -424,6 +422,10 @@ LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM 
wParam, LPARAM lParam, BO
     BOOL trueSelection =
         (selectionModel.m_bShow &&
          ((toolsModel.GetActiveTool() == TOOL_FREESEL) || 
(toolsModel.GetActiveTool() == TOOL_RECTSEL)));
+    BOOL textShown = (toolsModel.GetActiveTool() == TOOL_TEXT && 
::IsWindowVisible(textEditWindow));
+    DWORD dwStart, dwEnd;
+    textEditWindow.SendMessage(EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
+    BOOL hasTextSel = (dwStart < dwEnd);
 
     switch (lParam)
     {
@@ -431,16 +433,20 @@ LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM 
wParam, LPARAM lParam, BO
             ProcessFileMenu((HMENU)wParam);
             break;
         case 1: /* Edit menu */
-            EnableMenuItem(menu, IDM_EDITUNDO, 
ENABLED_IF(imageModel.CanUndo()));
-            EnableMenuItem(menu, IDM_EDITREDO, 
ENABLED_IF(imageModel.CanRedo()));
-            EnableMenuItem(menu, IDM_EDITCUT,  ENABLED_IF(trueSelection));
-            EnableMenuItem(menu, IDM_EDITCOPY, ENABLED_IF(trueSelection));
-            EnableMenuItem(menu, IDM_EDITDELETESELECTION, 
ENABLED_IF(trueSelection));
+            EnableMenuItem(menu, IDM_EDITUNDO,
+                ENABLED_IF(textShown ? textEditWindow.SendMessage(EM_CANUNDO) 
: imageModel.CanUndo()));
+            EnableMenuItem(menu, IDM_EDITREDO, ENABLED_IF(textShown ? FALSE : 
imageModel.CanRedo()));
+            EnableMenuItem(menu, IDM_EDITCUT, ENABLED_IF(textShown ? 
hasTextSel : trueSelection));
+            EnableMenuItem(menu, IDM_EDITCOPY, ENABLED_IF(textShown ? 
hasTextSel : trueSelection));
+            EnableMenuItem(menu, IDM_EDITDELETESELECTION,
+                           ENABLED_IF(textShown ? hasTextSel : trueSelection));
             EnableMenuItem(menu, IDM_EDITINVERTSELECTION, 
ENABLED_IF(trueSelection));
             EnableMenuItem(menu, IDM_EDITCOPYTO, ENABLED_IF(trueSelection));
-            OpenClipboard();
-            EnableMenuItem(menu, IDM_EDITPASTE, 
ENABLED_IF(IsClipboardFormatAvailable(CF_BITMAP)));
-            CloseClipboard();
+            EnableMenuItem(menu, IDM_EDITPASTE,
+                           ENABLED_IF(textShown ? 
::IsClipboardFormatAvailable(CF_UNICODETEXT) :
+                                      
::IsClipboardFormatAvailable(CF_ENHMETAFILE) ||
+                                      ::IsClipboardFormatAvailable(CF_DIB) ||
+                                      
::IsClipboardFormatAvailable(CF_BITMAP)));
             break;
         case 2: /* View menu */
             CheckMenuItem(menu, IDM_VIEWTOOLBOX, 
CHECKED_IF(::IsWindowVisible(toolBoxContainer)));
@@ -503,7 +509,7 @@ LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
                 if (canvasWindow.m_hWnd == hwndCapture ||
                     fullscreenWindow.m_hWnd == hwndCapture)
                 {
-                    SendMessage(hwndCapture, nMsg, wParam, lParam);
+                    ::SendMessage(hwndCapture, nMsg, wParam, lParam);
                 }
             }
             else if (selectionModel.m_bShow)
@@ -528,6 +534,8 @@ LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
         case VK_DOWN:
             canvasWindow.MoveSelection(0, +1);
             break;
+        default:
+            break;
     }
     return 0;
 }
@@ -549,6 +557,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
         return 0;
     }
 
+    BOOL textShown = (toolsModel.GetActiveTool() == TOOL_TEXT && 
::IsWindowVisible(textEditWindow));
     switch (LOWORD(wParam))
     {
         case IDM_HELPINFO:
@@ -641,7 +650,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
             break;
         }
         case IDM_EDITUNDO:
-            if (toolsModel.GetActiveTool() == TOOL_TEXT && 
::IsWindowVisible(textEditWindow))
+            if (textShown)
             {
                 textEditWindow.PostMessage(WM_UNDO, 0, 0);
                 break;
@@ -663,8 +672,11 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
             imageModel.Undo();
             break;
         case IDM_EDITREDO:
-            if (toolsModel.GetActiveTool() == TOOL_TEXT && 
::IsWindowVisible(textEditWindow))
+            if (textShown)
+            {
+                // There is no "WM_REDO". Do nothing
                 break;
+            }
             if (ToolBase::pointSP != 0) // drawing something?
             {
                 canvasWindow.finishDrawing();
@@ -673,38 +685,110 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
             imageModel.Redo();
             break;
         case IDM_EDITCOPY:
-            // FIXME: We should use CF_DIB in the future
-            if (OpenClipboard())
+            if (textShown)
             {
-                EmptyClipboard();
-                if (selectionModel.m_bShow)
-                {
-                    selectionModel.TakeOff();
-                    SetClipboardData(CF_BITMAP, selectionModel.CopyBitmap());
-                }
-                else
+                textEditWindow.SendMessage(WM_COPY);
+                break;
+            }
+            if (!selectionModel.m_bShow || !OpenClipboard())
+                break;
+
+            EmptyClipboard();
+
+            selectionModel.TakeOff();
+
+            {
+                HBITMAP hbm = selectionModel.CopyBitmap();
+                if (hbm)
                 {
-                    SetClipboardData(CF_BITMAP, imageModel.CopyBitmap());
+                    HGLOBAL hGlobal = BitmapToClipboardDIB(hbm);
+                    if (hGlobal)
+                        ::SetClipboardData(CF_DIB, hGlobal);
+                    ::DeleteObject(hbm);
                 }
-                CloseClipboard();
             }
+
+            CloseClipboard();
             break;
         case IDM_EDITCUT:
+            if (textShown)
+            {
+                textEditWindow.SendMessage(WM_CUT);
+                break;
+            }
             /* Copy */
             SendMessage(WM_COMMAND, IDM_EDITCOPY, 0);
             /* Delete selection */
             SendMessage(WM_COMMAND, IDM_EDITDELETESELECTION, 0);
             break;
         case IDM_EDITPASTE:
-            OpenClipboard();
-            if (IsClipboardFormatAvailable(CF_BITMAP))
+            if (textShown)
             {
-                InsertSelectionFromHBITMAP((HBITMAP) 
GetClipboardData(CF_BITMAP), m_hWnd);
+                textEditWindow.SendMessage(WM_PASTE);
+                break;
             }
+
+            if (!OpenClipboard())
+                break;
+
+            // In many cases, CF_ENHMETAFILE provides a better image than 
CF_DIB
+            if (::IsClipboardFormatAvailable(CF_ENHMETAFILE))
+            {
+                HENHMETAFILE hEMF = 
(HENHMETAFILE)::GetClipboardData(CF_ENHMETAFILE);
+                if (hEMF)
+                {
+                    HBITMAP hbm = BitmapFromHEMF(hEMF);
+                    ::DeleteEnhMetaFile(hEMF);
+                    if (hbm)
+                    {
+                        InsertSelectionFromHBITMAP(hbm, m_hWnd);
+                        CloseClipboard();
+                        break;
+                    }
+                }
+            }
+
+            // In many cases, CF_DIB provides a better image than CF_BITMAP
+            if (::IsClipboardFormatAvailable(CF_DIB))
+            {
+                HBITMAP hbm = 
BitmapFromClipboardDIB(::GetClipboardData(CF_DIB));
+                if (hbm)
+                {
+                    InsertSelectionFromHBITMAP(hbm, m_hWnd);
+                    CloseClipboard();
+                    break;
+                }
+            }
+
+            // The last resort
+            if (::IsClipboardFormatAvailable(CF_BITMAP))
+            {
+                HBITMAP hbm = (HBITMAP)::GetClipboardData(CF_BITMAP);
+                if (hbm)
+                {
+                    InsertSelectionFromHBITMAP(hbm, m_hWnd);
+                    CloseClipboard();
+                    break;
+                }
+            }
+
+            // Failed to paste
+            {
+                CString strText, strTitle;
+                strText.LoadString(IDS_CANTPASTE);
+                strTitle.LoadString(IDS_PROGRAMNAME);
+                MessageBox(strText, strTitle, MB_ICONINFORMATION);
+            }
+
             CloseClipboard();
             break;
         case IDM_EDITDELETESELECTION:
         {
+            if (textShown)
+            {
+                textEditWindow.SendMessage(WM_CLEAR);
+                break;
+            }
             switch (toolsModel.GetActiveTool())
             {
                 case TOOL_FREESEL:
@@ -722,7 +806,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
         }
         case IDM_EDITSELECTALL:
         {
-            if (toolsModel.GetActiveTool() == TOOL_TEXT && 
::IsWindowVisible(textEditWindow))
+            if (textShown)
             {
                 textEditWindow.SendMessage(EM_SETSEL, 0, -1);
                 break;

Reply via email to