Added FIXME comment for entry point parameter.
[wine] / controls / desktop.c
1 /*
2  * Desktop window class.
3  *
4  * Copyright 1994 Alexandre Julliard
5  */
6
7 #include <stdio.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 #include "desktop.h"
12 #include "windef.h"
13 #include "wingdi.h"
14 #include "heap.h"
15 #include "monitor.h"
16 #include "win.h"
17 #include "wine/winuser16.h"
18
19 /**********************************************************************/
20
21 DESKTOP_DRIVER *DESKTOP_Driver = NULL;
22
23 /***********************************************************************
24  *              DESKTOP_IsSingleWindow
25  */
26 BOOL DESKTOP_IsSingleWindow(void)
27 {
28   BOOL retvalue;
29   DESKTOP *pDesktop = (DESKTOP *) WIN_GetDesktop()->wExtra;
30   retvalue = MONITOR_IsSingleWindow(pDesktop->pPrimaryMonitor);
31   WIN_ReleaseDesktop();
32   return retvalue;
33 }
34
35 /***********************************************************************
36  *              DESKTOP_GetScreenWidth
37  *
38  * Return the width of the screen associated to the current desktop.
39  */
40 int DESKTOP_GetScreenWidth()
41 {
42     int retvalue;
43   DESKTOP *pDesktop = (DESKTOP *) WIN_GetDesktop()->wExtra;
44     retvalue = MONITOR_GetWidth(pDesktop->pPrimaryMonitor);
45     WIN_ReleaseDesktop();
46     return retvalue;
47     
48 }
49
50 /***********************************************************************
51  *              DESKTOP_GetScreenHeight
52  *
53  * Return the height of the screen associated to the current desktop.
54  */
55 int DESKTOP_GetScreenHeight()
56 {
57     int retvalue;
58   DESKTOP *pDesktop = (DESKTOP *) WIN_GetDesktop()->wExtra;
59     retvalue = MONITOR_GetHeight(pDesktop->pPrimaryMonitor);
60     WIN_ReleaseDesktop();
61     return retvalue;
62     
63 }
64
65 /***********************************************************************
66  *              DESKTOP_GetScreenDepth
67  *
68  * Return the depth of the screen associated to the current desktop.
69  */
70 int DESKTOP_GetScreenDepth()
71 {
72     int retvalue;
73   DESKTOP *pDesktop = (DESKTOP *) WIN_GetDesktop()->wExtra;
74     retvalue = MONITOR_GetDepth(pDesktop->pPrimaryMonitor);
75     WIN_ReleaseDesktop();
76     return retvalue;
77
78 }
79
80 /***********************************************************************
81  *           DESKTOP_LoadBitmap
82  *
83  * Load a bitmap from a file. Used by SetDeskWallPaper().
84  */
85 static HBITMAP DESKTOP_LoadBitmap( HDC hdc, const char *filename )
86 {
87     BITMAPFILEHEADER *fileHeader;
88     BITMAPINFO *bitmapInfo;
89     HBITMAP hbitmap;
90     HFILE file;
91     LPSTR buffer;
92     LONG size;
93
94     /* Read all the file into memory */
95
96     if ((file = _lopen( filename, OF_READ )) == HFILE_ERROR)
97     {
98         UINT len = GetWindowsDirectoryA( NULL, 0 );
99         if (!(buffer = HeapAlloc( GetProcessHeap(), 0,
100                                   len + strlen(filename) + 2 )))
101             return 0;
102         GetWindowsDirectoryA( buffer, len + 1 );
103         strcat( buffer, "\\" );
104         strcat( buffer, filename );
105         file = _lopen( buffer, OF_READ );
106         HeapFree( GetProcessHeap(), 0, buffer );
107     }
108     if (file == HFILE_ERROR) return 0;
109     size = _llseek( file, 0, 2 );
110     if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
111     {
112         _lclose( file );
113         return 0;
114     }
115     _llseek( file, 0, 0 );
116     size = _lread( file, buffer, size );
117     _lclose( file );
118     fileHeader = (BITMAPFILEHEADER *)buffer;
119     bitmapInfo = (BITMAPINFO *)(buffer + sizeof(BITMAPFILEHEADER));
120     
121       /* Check header content */
122     if ((fileHeader->bfType != 0x4d42) || (size < fileHeader->bfSize))
123     {
124         HeapFree( GetProcessHeap(), 0, buffer );
125         return 0;
126     }
127     hbitmap = CreateDIBitmap( hdc, &bitmapInfo->bmiHeader, CBM_INIT,
128                                 buffer + fileHeader->bfOffBits,
129                                 bitmapInfo, DIB_RGB_COLORS );
130     HeapFree( GetProcessHeap(), 0, buffer );
131     return hbitmap;
132 }
133
134
135 /***********************************************************************
136  *           DESKTOP_DoEraseBkgnd
137  *
138  * Handle the WM_ERASEBKGND message.
139  */
140 static LRESULT DESKTOP_DoEraseBkgnd( HWND hwnd, HDC hdc,
141                                      DESKTOP *desktopPtr )
142 {
143     RECT rect;
144     WND*   Wnd = WIN_FindWndPtr( hwnd );
145
146     if (Wnd->hrgnUpdate > 1) DeleteObject( Wnd->hrgnUpdate );
147     Wnd->hrgnUpdate = 0;
148
149     WIN_ReleaseWndPtr(Wnd);
150     
151     GetClientRect( hwnd, &rect );    
152
153     /* Paint desktop pattern (only if wall paper does not cover everything) */
154
155     if (!desktopPtr->hbitmapWallPaper || 
156         (!desktopPtr->fTileWallPaper && ((desktopPtr->bitmapSize.cx < rect.right) ||
157          (desktopPtr->bitmapSize.cy < rect.bottom))))
158     {
159           /* Set colors in case pattern is a monochrome bitmap */
160         SetBkColor( hdc, RGB(0,0,0) );
161         SetTextColor( hdc, GetSysColor(COLOR_BACKGROUND) );
162         FillRect( hdc, &rect, desktopPtr->hbrushPattern );
163     }
164
165       /* Paint wall paper */
166
167     if (desktopPtr->hbitmapWallPaper)
168     {
169         INT x, y;
170         HDC hMemDC = CreateCompatibleDC( hdc );
171         
172         SelectObject( hMemDC, desktopPtr->hbitmapWallPaper );
173
174         if (desktopPtr->fTileWallPaper)
175         {
176             for (y = 0; y < rect.bottom; y += desktopPtr->bitmapSize.cy)
177                 for (x = 0; x < rect.right; x += desktopPtr->bitmapSize.cx)
178                     BitBlt( hdc, x, y, desktopPtr->bitmapSize.cx,
179                               desktopPtr->bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
180         }
181         else
182         {
183             x = (rect.left + rect.right - desktopPtr->bitmapSize.cx) / 2;
184             y = (rect.top + rect.bottom - desktopPtr->bitmapSize.cy) / 2;
185             if (x < 0) x = 0;
186             if (y < 0) y = 0;
187             BitBlt( hdc, x, y, desktopPtr->bitmapSize.cx,
188                       desktopPtr->bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
189         }
190         DeleteDC( hMemDC );
191     }
192
193     return 1;
194 }
195
196
197 /***********************************************************************
198  *           DesktopWndProc_locked
199  *
200  * Window procedure for the desktop window.
201  */
202 static inline LRESULT WINAPI DesktopWndProc_locked( WND *wndPtr, UINT message,
203                                WPARAM wParam, LPARAM lParam )
204 {
205     DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
206     HWND hwnd = wndPtr->hwndSelf;
207
208       /* Most messages are ignored (we DON'T call DefWindowProc) */
209
210     switch(message)
211     {
212         /* Warning: this message is sent directly by                     */
213         /* WIN_CreateDesktopWindow() and does not contain a valid lParam */
214     case WM_NCCREATE:
215         desktopPtr->hbrushPattern = 0;
216         desktopPtr->hbitmapWallPaper = 0;
217         SetDeskPattern();
218         SetDeskWallPaper( (LPSTR)-1 );
219         return  1;
220         
221     case WM_ERASEBKGND:
222         if(!DESKTOP_IsSingleWindow())
223             return  1;
224         return  DESKTOP_DoEraseBkgnd( hwnd, (HDC)wParam, desktopPtr );
225
226     case WM_SYSCOMMAND:
227         if ((wParam & 0xfff0) != SC_CLOSE)
228             return  0;
229         ExitWindows16( 0, 0 ); 
230
231     case WM_SETCURSOR:
232         return  (LRESULT)SetCursor16( LoadCursor16( 0, IDC_ARROW16 ) );
233     }
234     
235     return 0;
236 }
237
238 /***********************************************************************
239  *           DesktopWndProc
240  *
241  * This is just a wrapper for the DesktopWndProc which does windows
242  * locking and unlocking.
243  */
244 LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message,
245                                WPARAM wParam, LPARAM lParam )
246 {
247     WND *wndPtr = WIN_FindWndPtr( hwnd );
248     LRESULT retvalue = DesktopWndProc_locked(wndPtr,message,wParam,lParam);
249
250     WIN_ReleaseWndPtr(wndPtr);
251     return retvalue;
252 }
253
254 /***********************************************************************
255  *           PaintDesktop   (USER32.415)
256  *
257  */
258 BOOL WINAPI PaintDesktop(HDC hdc)
259 {
260     BOOL retvalue;
261     HWND hwnd = GetDesktopWindow();
262     WND *wndPtr = WIN_FindWndPtr( hwnd );
263     DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
264     retvalue = DESKTOP_DoEraseBkgnd( hwnd, hdc, desktopPtr );
265     WIN_ReleaseWndPtr(wndPtr);
266     return retvalue;
267
268 }
269
270 /***********************************************************************
271  *           SetDeskPattern   (USER.279)
272  */
273 BOOL16 WINAPI SetDeskPattern(void)
274 {
275     char buffer[100];
276     GetProfileStringA( "desktop", "Pattern", "(None)", buffer, 100 );
277     return DESKTOP_SetPattern( buffer );
278 }
279
280
281 /***********************************************************************
282  *           SetDeskWallPaper16   (USER.285)
283  */
284 BOOL16 WINAPI SetDeskWallPaper16( LPCSTR filename )
285 {
286     return SetDeskWallPaper( filename );
287 }
288
289
290 /***********************************************************************
291  *           SetDeskWallPaper32   (USER32.475)
292  *
293  * FIXME: is there a unicode version?
294  */
295 BOOL WINAPI SetDeskWallPaper( LPCSTR filename )
296 {
297     HBITMAP hbitmap;
298     HDC hdc;
299     char buffer[256];
300     WND *wndPtr = WIN_GetDesktop();
301     DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
302
303     if (filename == (LPSTR)-1)
304     {
305         GetProfileStringA( "desktop", "WallPaper", "(None)", buffer, 256 );
306         filename = buffer;
307     }
308     hdc = GetDC( 0 );
309     hbitmap = DESKTOP_LoadBitmap( hdc, filename );
310     ReleaseDC( 0, hdc );
311     if (desktopPtr->hbitmapWallPaper) DeleteObject( desktopPtr->hbitmapWallPaper );
312     desktopPtr->hbitmapWallPaper = hbitmap;
313     desktopPtr->fTileWallPaper = GetProfileIntA( "desktop", "TileWallPaper", 0 );
314     if (hbitmap)
315     {
316         BITMAP bmp;
317         GetObjectA( hbitmap, sizeof(bmp), &bmp );
318         desktopPtr->bitmapSize.cx = (bmp.bmWidth != 0) ? bmp.bmWidth : 1;
319         desktopPtr->bitmapSize.cy = (bmp.bmHeight != 0) ? bmp.bmHeight : 1;
320     }
321     WIN_ReleaseDesktop();
322     return TRUE;
323 }
324
325
326 /***********************************************************************
327  *           DESKTOP_SetPattern
328  *
329  * Set the desktop pattern.
330  */
331 BOOL DESKTOP_SetPattern( LPCSTR pattern )
332 {
333     WND *wndPtr = WIN_GetDesktop();
334     DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
335     int pat[8];
336
337     if (desktopPtr->hbrushPattern) DeleteObject( desktopPtr->hbrushPattern );
338     memset( pat, 0, sizeof(pat) );
339     if (pattern && sscanf( pattern, " %d %d %d %d %d %d %d %d",
340                            &pat[0], &pat[1], &pat[2], &pat[3],
341                            &pat[4], &pat[5], &pat[6], &pat[7] ))
342     {
343         WORD pattern[8];
344         HBITMAP hbitmap;
345         int i;
346
347         for (i = 0; i < 8; i++) pattern[i] = pat[i] & 0xffff;
348         hbitmap = CreateBitmap( 8, 8, 1, 1, (LPSTR)pattern );
349         desktopPtr->hbrushPattern = CreatePatternBrush( hbitmap );
350         DeleteObject( hbitmap );
351     }
352     else desktopPtr->hbrushPattern = CreateSolidBrush( GetSysColor(COLOR_BACKGROUND) );
353     WIN_ReleaseDesktop();
354     return TRUE;
355 }
356