Added unicode window proc for the listbox control.
[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 "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"
18
19 typedef struct
20 {
21     HBRUSH        hbrushPattern;
22     HBITMAP       hbitmapWallPaper;
23     SIZE          bitmapSize;
24     BOOL          fTileWallPaper;
25 } DESKTOP;
26
27 static LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
28
29
30 /*********************************************************************
31  * desktop class descriptor
32  */
33 const struct builtin_class_descr DESKTOP_builtin_class =
34 {
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 */
42 };
43
44
45 /***********************************************************************
46  *           DESKTOP_LoadBitmap
47  *
48  * Load a bitmap from a file. Used by SetDeskWallPaper().
49  */
50 static HBITMAP DESKTOP_LoadBitmap( HDC hdc, const char *filename )
51 {
52     BITMAPFILEHEADER *fileHeader;
53     BITMAPINFO *bitmapInfo;
54     HBITMAP hbitmap;
55     HFILE file;
56     LPSTR buffer;
57     LONG size;
58
59     /* Read all the file into memory */
60
61     if ((file = _lopen( filename, OF_READ )) == HFILE_ERROR)
62     {
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 );
72     }
73     if (file == HFILE_ERROR) return 0;
74     size = _llseek( file, 0, 2 );
75     if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
76     {
77         _lclose( file );
78         return 0;
79     }
80     _llseek( file, 0, 0 );
81     size = _lread( file, buffer, size );
82     _lclose( file );
83     fileHeader = (BITMAPFILEHEADER *)buffer;
84     bitmapInfo = (BITMAPINFO *)(buffer + sizeof(BITMAPFILEHEADER));
85     
86       /* Check header content */
87     if ((fileHeader->bfType != 0x4d42) || (size < fileHeader->bfSize))
88     {
89         HeapFree( GetProcessHeap(), 0, buffer );
90         return 0;
91     }
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;
97 }
98
99
100 /***********************************************************************
101  *           DESKTOP_DoEraseBkgnd
102  *
103  * Handle the WM_ERASEBKGND message.
104  */
105 static LRESULT DESKTOP_DoEraseBkgnd( HWND hwnd, HDC hdc,
106                                      DESKTOP *desktopPtr )
107 {
108     RECT rect;
109     WND*   Wnd = WIN_FindWndPtr( hwnd );
110
111     if (Wnd->hrgnUpdate > 1) DeleteObject( Wnd->hrgnUpdate );
112     Wnd->hrgnUpdate = 0;
113
114     WIN_ReleaseWndPtr(Wnd);
115     
116     GetClientRect( hwnd, &rect );    
117
118     /* Paint desktop pattern (only if wall paper does not cover everything) */
119
120     if (!desktopPtr->hbitmapWallPaper || 
121         (!desktopPtr->fTileWallPaper && ((desktopPtr->bitmapSize.cx < rect.right) ||
122          (desktopPtr->bitmapSize.cy < rect.bottom))))
123     {
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 );
130     }
131
132       /* Paint wall paper */
133
134     if (desktopPtr->hbitmapWallPaper)
135     {
136         INT x, y;
137         HDC hMemDC = CreateCompatibleDC( hdc );
138         
139         SelectObject( hMemDC, desktopPtr->hbitmapWallPaper );
140
141         if (desktopPtr->fTileWallPaper)
142         {
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 );
147         }
148         else
149         {
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 );
156         }
157         DeleteDC( hMemDC );
158     }
159
160     return 1;
161 }
162
163
164 /***********************************************************************
165  *           DesktopWndProc_locked
166  *
167  * Window procedure for the desktop window.
168  */
169 static inline LRESULT WINAPI DesktopWndProc_locked( WND *wndPtr, UINT message,
170                                WPARAM wParam, LPARAM lParam )
171 {
172     DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
173     HWND hwnd = wndPtr->hwndSelf;
174
175       /* Most messages are ignored (we DON'T call DefWindowProc) */
176
177     switch(message)
178     {
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;
187         
188     case WM_ERASEBKGND:
189         if(!USER_Driver.pIsSingleWindow())
190             return  1;
191         return  DESKTOP_DoEraseBkgnd( hwnd, (HDC)wParam, desktopPtr );
192
193     case WM_SYSCOMMAND:
194         if ((wParam & 0xfff0) != SC_CLOSE)
195             return  0;
196         ExitWindows16( 0, 0 ); 
197
198     case WM_SETCURSOR:
199         return  (LRESULT)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
200     }
201     
202     return 0;
203 }
204
205 /***********************************************************************
206  *           DesktopWndProc
207  *
208  * This is just a wrapper for the DesktopWndProc which does windows
209  * locking and unlocking.
210  */
211 static LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
212 {
213     WND *wndPtr = WIN_FindWndPtr( hwnd );
214     LRESULT retvalue = DesktopWndProc_locked(wndPtr,message,wParam,lParam);
215
216     WIN_ReleaseWndPtr(wndPtr);
217     return retvalue;
218 }
219
220 /***********************************************************************
221  *           PaintDesktop   (USER32.415)
222  *
223  */
224 BOOL WINAPI PaintDesktop(HDC hdc)
225 {
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;
233
234 }
235
236 /***********************************************************************
237  *           SetDeskPattern   (USER.279)
238  */
239 BOOL16 WINAPI SetDeskPattern(void)
240 {
241     char buffer[100];
242     GetProfileStringA( "desktop", "Pattern", "(None)", buffer, 100 );
243     return DESKTOP_SetPattern( buffer );
244 }
245
246
247 /***********************************************************************
248  *           SetDeskWallPaper16   (USER.285)
249  */
250 BOOL16 WINAPI SetDeskWallPaper16( LPCSTR filename )
251 {
252     return SetDeskWallPaper( filename );
253 }
254
255
256 /***********************************************************************
257  *           SetDeskWallPaper   (USER32.475)
258  *
259  * FIXME: is there a unicode version?
260  */
261 BOOL WINAPI SetDeskWallPaper( LPCSTR filename )
262 {
263     HBITMAP hbitmap;
264     HDC hdc;
265     char buffer[256];
266     WND *wndPtr = WIN_GetDesktop();
267     DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
268
269     if (filename == (LPSTR)-1)
270     {
271         GetProfileStringA( "desktop", "WallPaper", "(None)", buffer, 256 );
272         filename = buffer;
273     }
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)
281     {
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;
286     }
287     WIN_ReleaseDesktop();
288     return TRUE;
289 }
290
291
292 /***********************************************************************
293  *           DESKTOP_SetPattern
294  *
295  * Set the desktop pattern.
296  */
297 BOOL DESKTOP_SetPattern( LPCSTR pattern )
298 {
299     WND *wndPtr = WIN_GetDesktop();
300     DESKTOP *desktopPtr = (DESKTOP *)wndPtr->wExtra;
301     int pat[8];
302
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] ))
308     {
309         WORD pattern[8];
310         HBITMAP hbitmap;
311         int i;
312
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 );
317     }
318     else desktopPtr->hbrushPattern = 0;
319     WIN_ReleaseDesktop();
320     return TRUE;
321 }
322