1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/os2/icon.cpp
3// Purpose:     wxIcon class
4// Author:      David Webster
5// Modified by:
6// Created:     10/09/99
7// RCS-ID:      $Id: icon.cpp 39261 2006-05-21 21:45:44Z ABX $
8// Copyright:   (c) David Webster
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16    #pragma hdrstop
17#endif
18
19#include "wx/icon.h"
20
21#ifndef WX_PRECOMP
22    #include "wx/list.h"
23    #include "wx/utils.h"
24    #include "wx/app.h"
25    #include "wx/log.h"
26#endif
27
28#include "wx/os2/private.h"
29#include "assert.h"
30
31IMPLEMENT_DYNAMIC_CLASS(wxIcon, wxGDIObject)
32
33// ============================================================================
34// implementation
35// ============================================================================
36
37// ----------------------------------------------------------------------------
38// wxIconRefData
39// ----------------------------------------------------------------------------
40
41void wxIconRefData::Free()
42{
43    if (m_hIcon)
44        ::WinFreeFileIcon((HPOINTER)m_hIcon);
45}
46
47// ----------------------------------------------------------------------------
48// wxIcon
49// ----------------------------------------------------------------------------
50
51wxIcon::wxIcon()
52       :m_bIsXpm(false)
53{
54}
55
56wxIcon::wxIcon( const char WXUNUSED(bits)[],
57                int        WXUNUSED(nWidth),
58                int        WXUNUSED(nHeight) )
59       :m_bIsXpm(false)
60{
61}
62
63wxIcon::wxIcon( const wxString& rIconFile,
64                long            lFlags,
65                int             nDesiredWidth,
66                int             nDesiredHeight )
67       :m_bIsXpm(false)
68{
69    //
70    // A very poor hack, but we have to have separate icon files from windows
71    // So we have a modified name where replace the last three characters
72    // with os2.  Also need the extension.
73    //
74    wxString sOs2Name = rIconFile.Mid(0, rIconFile.length() - 3);
75
76    sOs2Name += wxT("Os2.ico");
77    LoadFile( sOs2Name
78             ,lFlags
79             ,nDesiredWidth
80             ,nDesiredHeight
81            );
82}
83
84wxIcon::~wxIcon()
85{
86}
87
88void wxIcon::CreateIconFromXpm(
89  const char**                      ppData
90)
91{
92    wxBitmap                        vBmp(ppData);
93
94    CopyFromBitmap(vBmp);
95    if (GetHICON())
96    {
97        m_bIsXpm = true;
98        m_vXpmSrc = vBmp;
99    }
100} // end of wxIcon::CreateIconFromXpm
101
102void wxIcon::CopyFromBitmap( const wxBitmap& rBmp )
103{
104    wxMask*                         pMask = rBmp.GetMask();
105    HBITMAP                         hBmp = NULLHANDLE;
106    HBITMAP                         hBmpMask = NULLHANDLE;
107    HBITMAP                         hOldBitmap = NULLHANDLE;
108    ERRORID                         vError;
109    wxString                        sError;
110    LONG                            lHits;
111
112    if (!pMask)
113    {
114        //
115        // We must have a mask for an icon, so even if it's probably incorrect,
116        // do create it (grey is the "standard" transparent colour)
117        //
118        pMask = new wxMask( rBmp
119                           ,*wxLIGHT_GREY
120                          );
121    }
122
123    BITMAPINFOHEADER2 vHeader;
124    SIZEL             vSize = {0, 0};
125    DEVOPENSTRUC      vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
126    HDC               hDCSrc = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
127    HDC               hDCDst = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
128    HPS               hPSSrc = ::GpiCreatePS(vHabmain, hDCSrc, &vSize, PU_PELS | GPIA_ASSOC);
129    HPS               hPSDst = ::GpiCreatePS(vHabmain, hDCDst, &vSize, PU_PELS | GPIA_ASSOC);
130    POINTL            vPoint[4] = { {0, 0}, {rBmp.GetWidth(), rBmp.GetHeight()},
131                                    {0, 0}, {rBmp.GetWidth(), rBmp.GetHeight()}
132                                  };
133    POINTL            vPointMask[4] = { {0, 0}, {rBmp.GetWidth(), rBmp.GetHeight() * 2},
134                                        {0, 0}, {rBmp.GetWidth(), rBmp.GetHeight()}
135                                    };
136    POINTERINFO       vIconInfo;
137
138    memset(&vIconInfo, '\0', sizeof(POINTERINFO));
139    vIconInfo.fPointer = FALSE;  // we want an icon, not a pointer
140
141    memset(&vHeader, '\0', 16);
142    vHeader.cbFix           = 16;
143    vHeader.cx              = (ULONG)rBmp.GetWidth();
144    vHeader.cy              = (ULONG)rBmp.GetHeight();
145    vHeader.cPlanes         = 1L;
146    vHeader.cBitCount       = 24;
147
148    hBmp = ::GpiCreateBitmap( hPSDst
149                             ,&vHeader
150                             ,0L
151                             ,NULL
152                             ,NULL
153                            );
154
155    if ((hOldBitmap = ::GpiSetBitmap(hPSDst, hBmp)) == HBM_ERROR)
156    {
157        vError = ::WinGetLastError(vHabmain);
158        sError = wxPMErrorToStr(vError);
159    }
160    if ((hOldBitmap = ::GpiSetBitmap(hPSSrc, (HBITMAP)rBmp.GetHBITMAP())) == HBM_ERROR)
161    {
162        vError = ::WinGetLastError(vHabmain);
163        sError = wxPMErrorToStr(vError);
164    }
165    if ((lHits = ::GpiBitBlt( hPSDst
166                             ,hPSSrc
167                             ,4L
168                             ,vPoint
169                             ,ROP_SRCCOPY
170                             ,BBO_IGNORE
171                            )) == GPI_ERROR)
172    {
173        vError = ::WinGetLastError(vHabmain);
174        sError = wxPMErrorToStr(vError);
175    }
176    if ((hOldBitmap = ::GpiSetBitmap(hPSDst, NULLHANDLE)) == HBM_ERROR)
177    {
178        vError = ::WinGetLastError(vHabmain);
179        sError = wxPMErrorToStr(vError);
180    }
181    if ((hOldBitmap = ::GpiSetBitmap(hPSSrc, NULLHANDLE)) == HBM_ERROR)
182    {
183        vError = ::WinGetLastError(vHabmain);
184        sError = wxPMErrorToStr(vError);
185    }
186    vIconInfo.hbmColor = hBmp;
187
188    vHeader.cy              = (ULONG)rBmp.GetHeight() * 2;
189    hBmpMask = ::GpiCreateBitmap( hPSDst
190                                 ,&vHeader
191                                 ,0L
192                                 ,NULL
193                                 ,NULL
194                                );
195
196    if ((hOldBitmap = ::GpiSetBitmap(hPSDst, hBmpMask)) == HBM_ERROR)
197    {
198        vError = ::WinGetLastError(vHabmain);
199        sError = wxPMErrorToStr(vError);
200    }
201    if ((hOldBitmap = ::GpiSetBitmap(hPSSrc, (HBITMAP)pMask->GetMaskBitmap())) == HBM_ERROR)
202    {
203        vError = ::WinGetLastError(vHabmain);
204        sError = wxPMErrorToStr(vError);
205    }
206    if ((lHits = ::GpiBitBlt( hPSDst
207                             ,hPSSrc
208                             ,4L
209                             ,vPointMask
210                             ,ROP_SRCCOPY
211                             ,BBO_IGNORE
212                            )) == GPI_ERROR)
213    {
214        vError = ::WinGetLastError(vHabmain);
215        sError = wxPMErrorToStr(vError);
216    }
217    if ((hOldBitmap = ::GpiSetBitmap(hPSSrc, NULLHANDLE)) == HBM_ERROR)
218    {
219        vError = ::WinGetLastError(vHabmain);
220        sError = wxPMErrorToStr(vError);
221    }
222    if ((hOldBitmap = ::GpiSetBitmap(hPSDst, NULLHANDLE)) == HBM_ERROR)
223    {
224        vError = ::WinGetLastError(vHabmain);
225        sError = wxPMErrorToStr(vError);
226    }
227
228    vIconInfo.hbmPointer = hBmpMask;
229
230    HICON hIcon = ::WinCreatePointerIndirect( HWND_DESKTOP, &vIconInfo);
231
232    if (!hIcon)
233    {
234        wxLogLastError(wxT("WinCreatePointerIndirect"));
235        vError = ::WinGetLastError(vHabmain);
236        sError = wxPMErrorToStr(vError);
237    }
238    else
239    {
240        SetHICON((WXHICON)hIcon);
241        SetSize( rBmp.GetWidth()
242                ,rBmp.GetHeight()
243               );
244    }
245
246    if (!rBmp.GetMask())
247    {
248        //
249        // We created the mask, now delete it
250        //
251        delete pMask;
252    }
253    ::GpiSetBitmap(hPSSrc, NULL);
254    ::GpiSetBitmap(hPSDst, NULL);
255    ::GpiDestroyPS(hPSSrc);
256    ::GpiDestroyPS(hPSDst);
257    ::DevCloseDC(hDCSrc);
258    ::DevCloseDC(hDCDst);
259} // end of wxIcon::CopyFromBitmap
260
261bool wxIcon::LoadFile( const wxString& rFilename,
262                       long lType,
263                       int nDesiredWidth,
264                       int nDesiredHeight )
265{
266    HPS                             hPs = NULLHANDLE;
267
268    UnRef();
269
270    wxGDIImageHandler*              pHandler = FindHandler(lType);
271
272    if (pHandler)
273        return(pHandler->Load( this
274                              ,rFilename
275                              ,hPs
276                              ,lType
277                              ,nDesiredWidth
278                              ,nDesiredHeight
279                             ));
280    else
281        return false;
282}
283