Do not free the not owned error string.
[wine.git] / controls / desktop.c
blobca91c8b6b7573f2bd6b2b6f97e379a369350b00e
1 /*
2 * Desktop window class.
4 * Copyright 1994 Alexandre Julliard
5 */
7 #include <stdio.h>
8 #include <string.h>
9 #include <unistd.h>
11 #include "windef.h"
12 #include "wingdi.h"
13 #include "heap.h"
14 #include "user.h"
15 #include "win.h"
16 #include "controls.h"
17 #include "wine/winuser16.h"
19 typedef struct
21 HBRUSH hbrushPattern;
22 HBITMAP hbitmapWallPaper;
23 SIZE bitmapSize;
24 BOOL fTileWallPaper;
25 } DESKTOP;
27 static LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
30 /*********************************************************************
31 * desktop class descriptor
33 const struct builtin_class_descr DESKTOP_builtin_class =
35 DESKTOP_CLASS_ATOM, /* name */
36 CS_GLOBALCLASS, /* style */
37 NULL, /* procA (winproc is Unicode only) */
38 DesktopWndProc, /* procW */
39 sizeof(DESKTOP), /* extra */
40 IDC_ARROWA, /* cursor */
41 COLOR_BACKGROUND+1 /* brush */
45 /***********************************************************************
46 * DESKTOP_LoadBitmap
48 * Load a bitmap from a file. Used by SetDeskWallPaper().
50 static HBITMAP DESKTOP_LoadBitmap( HDC hdc, const char *filename )
52 BITMAPFILEHEADER *fileHeader;
53 BITMAPINFO *bitmapInfo;
54 HBITMAP hbitmap;
55 HFILE file;
56 LPSTR buffer;
57 LONG size;
59 /* Read all the file into memory */
61 if ((file = _lopen( filename, OF_READ )) == HFILE_ERROR)
63 UINT len = GetWindowsDirectoryA( NULL, 0 );
64 if (!(buffer = HeapAlloc( GetProcessHeap(), 0,
65 len + strlen(filename) + 2 )))
66 return 0;
67 GetWindowsDirectoryA( buffer, len + 1 );
68 strcat( buffer, "\\" );
69 strcat( buffer, filename );
70 file = _lopen( buffer, OF_READ );
71 HeapFree( GetProcessHeap(), 0, buffer );
73 if (file == HFILE_ERROR) return 0;
74 size = _llseek( file, 0, 2 );
75 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
77 _lclose( file );
78 return 0;
80 _llseek( file, 0, 0 );
81 size = _lread( file, buffer, size );
82 _lclose( file );
83 fileHeader = (BITMAPFILEHEADER *)buffer;
84 bitmapInfo = (BITMAPINFO *)(buffer + sizeof(BITMAPFILEHEADER));
86 /* Check header content */
87 if ((fileHeader->bfType != 0x4d42) || (size < fileHeader->bfSize))
89 HeapFree( GetProcessHeap(), 0, buffer );
90 return 0;
92 hbitmap = CreateDIBitmap( hdc, &bitmapInfo->bmiHeader, CBM_INIT,
93 buffer + fileHeader->bfOffBits,
94 bitmapInfo, DIB_RGB_COLORS );
95 HeapFree( GetProcessHeap(), 0, buffer );
96 return hbitmap;
100 /***********************************************************************
101 * DESKTOP_DoEraseBkgnd
103 * Handle the WM_ERASEBKGND message.
105 static LRESULT DESKTOP_DoEraseBkgnd( HWND hwnd, HDC hdc,
106 DESKTOP *desktopPtr )
108 RECT rect;
109 WND* Wnd = WIN_FindWndPtr( hwnd );
111 if (Wnd->hrgnUpdate > 1) DeleteObject( Wnd->hrgnUpdate );
112 Wnd->hrgnUpdate = 0;
114 WIN_ReleaseWndPtr(Wnd);
116 GetClientRect( hwnd, &rect );
118 /* Paint desktop pattern (only if wall paper does not cover everything) */
120 if (!desktopPtr->hbitmapWallPaper ||
121 (!desktopPtr->fTileWallPaper && ((desktopPtr->bitmapSize.cx < rect.right) ||
122 (desktopPtr->bitmapSize.cy < rect.bottom))))
124 HBRUSH brush = desktopPtr->hbrushPattern;
125 if (!brush) brush = GetClassLongA( hwnd, GCL_HBRBACKGROUND );
126 /* Set colors in case pattern is a monochrome bitmap */
127 SetBkColor( hdc, RGB(0,0,0) );
128 SetTextColor( hdc, GetSysColor(COLOR_BACKGROUND) );
129 FillRect( hdc, &rect, brush );
132 /* Paint wall paper */
134 if (desktopPtr->hbitmapWallPaper)
136 INT x, y;
137 HDC hMemDC = CreateCompatibleDC( hdc );
139 SelectObject( hMemDC, desktopPtr->hbitmapWallPaper );
141 if (desktopPtr->fTileWallPaper)
143 for (y = 0; y < rect.bottom; y += desktopPtr->bitmapSize.cy)
144 for (x = 0; x < rect.right; x += desktopPtr->bitmapSize.cx)
145 BitBlt( hdc, x, y, desktopPtr->bitmapSize.cx,
146 desktopPtr->bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
148 else
150 x = (rect.left + rect.right - desktopPtr->bitmapSize.cx) / 2;
151 y = (rect.top + rect.bottom - desktopPtr->bitmapSize.cy) / 2;
152 if (x < 0) x = 0;
153 if (y < 0) y = 0;
154 BitBlt( hdc, x, y, desktopPtr->bitmapSize.cx,
155 desktopPtr->bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
157 DeleteDC( hMemDC );
160 return 1;
164 /***********************************************************************
165 * DesktopWndProc_locked
167 * Window procedure for the desktop window.
169 static inline LRESULT WINAPI DesktopWndProc_locked( WND *wndPtr, UINT message,
170 WPARAM wParam, LPARAM lParam )
172 DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
173 HWND hwnd = wndPtr->hwndSelf;
175 /* Most messages are ignored (we DON'T call DefWindowProc) */
177 switch(message)
179 /* Warning: this message is sent directly by */
180 /* WIN_CreateDesktopWindow() and does not contain a valid lParam */
181 case WM_NCCREATE:
182 desktopPtr->hbrushPattern = 0;
183 desktopPtr->hbitmapWallPaper = 0;
184 SetDeskPattern();
185 SetDeskWallPaper( (LPSTR)-1 );
186 return 1;
188 case WM_ERASEBKGND:
189 if(!USER_Driver.pIsSingleWindow())
190 return 1;
191 return DESKTOP_DoEraseBkgnd( hwnd, (HDC)wParam, desktopPtr );
193 case WM_SYSCOMMAND:
194 if ((wParam & 0xfff0) != SC_CLOSE)
195 return 0;
196 ExitWindows16( 0, 0 );
198 case WM_SETCURSOR:
199 return (LRESULT)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
202 return 0;
205 /***********************************************************************
206 * DesktopWndProc
208 * This is just a wrapper for the DesktopWndProc which does windows
209 * locking and unlocking.
211 static LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
213 WND *wndPtr = WIN_FindWndPtr( hwnd );
214 LRESULT retvalue = DesktopWndProc_locked(wndPtr,message,wParam,lParam);
216 WIN_ReleaseWndPtr(wndPtr);
217 return retvalue;
220 /***********************************************************************
221 * PaintDesktop (USER32.415)
224 BOOL WINAPI PaintDesktop(HDC hdc)
226 BOOL retvalue;
227 HWND hwnd = GetDesktopWindow();
228 WND *wndPtr = WIN_FindWndPtr( hwnd );
229 DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
230 retvalue = DESKTOP_DoEraseBkgnd( hwnd, hdc, desktopPtr );
231 WIN_ReleaseWndPtr(wndPtr);
232 return retvalue;
236 /***********************************************************************
237 * SetDeskPattern (USER.279)
239 BOOL16 WINAPI SetDeskPattern(void)
241 char buffer[100];
242 GetProfileStringA( "desktop", "Pattern", "(None)", buffer, 100 );
243 return DESKTOP_SetPattern( buffer );
247 /***********************************************************************
248 * SetDeskWallPaper16 (USER.285)
250 BOOL16 WINAPI SetDeskWallPaper16( LPCSTR filename )
252 return SetDeskWallPaper( filename );
256 /***********************************************************************
257 * SetDeskWallPaper (USER32.475)
259 * FIXME: is there a unicode version?
261 BOOL WINAPI SetDeskWallPaper( LPCSTR filename )
263 HBITMAP hbitmap;
264 HDC hdc;
265 char buffer[256];
266 WND *wndPtr = WIN_GetDesktop();
267 DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
269 if (filename == (LPSTR)-1)
271 GetProfileStringA( "desktop", "WallPaper", "(None)", buffer, 256 );
272 filename = buffer;
274 hdc = GetDC( 0 );
275 hbitmap = DESKTOP_LoadBitmap( hdc, filename );
276 ReleaseDC( 0, hdc );
277 if (desktopPtr->hbitmapWallPaper) DeleteObject( desktopPtr->hbitmapWallPaper );
278 desktopPtr->hbitmapWallPaper = hbitmap;
279 desktopPtr->fTileWallPaper = GetProfileIntA( "desktop", "TileWallPaper", 0 );
280 if (hbitmap)
282 BITMAP bmp;
283 GetObjectA( hbitmap, sizeof(bmp), &bmp );
284 desktopPtr->bitmapSize.cx = (bmp.bmWidth != 0) ? bmp.bmWidth : 1;
285 desktopPtr->bitmapSize.cy = (bmp.bmHeight != 0) ? bmp.bmHeight : 1;
287 WIN_ReleaseDesktop();
288 return TRUE;
292 /***********************************************************************
293 * DESKTOP_SetPattern
295 * Set the desktop pattern.
297 BOOL DESKTOP_SetPattern( LPCSTR pattern )
299 WND *wndPtr = WIN_GetDesktop();
300 DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
301 int pat[8];
303 if (desktopPtr->hbrushPattern) DeleteObject( desktopPtr->hbrushPattern );
304 memset( pat, 0, sizeof(pat) );
305 if (pattern && sscanf( pattern, " %d %d %d %d %d %d %d %d",
306 &pat[0], &pat[1], &pat[2], &pat[3],
307 &pat[4], &pat[5], &pat[6], &pat[7] ))
309 WORD pattern[8];
310 HBITMAP hbitmap;
311 int i;
313 for (i = 0; i < 8; i++) pattern[i] = pat[i] & 0xffff;
314 hbitmap = CreateBitmap( 8, 8, 1, 1, (LPSTR)pattern );
315 desktopPtr->hbrushPattern = CreatePatternBrush( hbitmap );
316 DeleteObject( hbitmap );
318 else desktopPtr->hbrushPattern = 0;
319 WIN_ReleaseDesktop();
320 return TRUE;