Fixed WM_SETFONT handling (no redraw made in some cases).
[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 "user.h"
14 #include "controls.h"
15 #include "wine/winuser16.h"
16
17 static HBRUSH hbrushPattern;
18 static HBITMAP hbitmapWallPaper;
19 static SIZE bitmapSize;
20 static BOOL fTileWallPaper;
21
22 static LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
23
24
25 /*********************************************************************
26  * desktop class descriptor
27  */
28 const struct builtin_class_descr DESKTOP_builtin_class =
29 {
30     DESKTOP_CLASS_ATOM,   /* name */
31     CS_GLOBALCLASS,       /* style */
32     NULL,                 /* procA (winproc is Unicode only) */
33     DesktopWndProc,       /* procW */
34     0,                    /* extra */
35     IDC_ARROWA,           /* cursor */
36     COLOR_BACKGROUND+1    /* brush */
37 };
38
39
40 /***********************************************************************
41  *           DESKTOP_LoadBitmap
42  *
43  * Load a bitmap from a file. Used by SetDeskWallPaper().
44  */
45 static HBITMAP DESKTOP_LoadBitmap( HDC hdc, const char *filename )
46 {
47     BITMAPFILEHEADER *fileHeader;
48     BITMAPINFO *bitmapInfo;
49     HBITMAP hbitmap;
50     HFILE file;
51     LPSTR buffer;
52     LONG size;
53
54     /* Read all the file into memory */
55
56     if ((file = _lopen( filename, OF_READ )) == HFILE_ERROR)
57     {
58         UINT len = GetWindowsDirectoryA( NULL, 0 );
59         if (!(buffer = HeapAlloc( GetProcessHeap(), 0,
60                                   len + strlen(filename) + 2 )))
61             return 0;
62         GetWindowsDirectoryA( buffer, len + 1 );
63         strcat( buffer, "\\" );
64         strcat( buffer, filename );
65         file = _lopen( buffer, OF_READ );
66         HeapFree( GetProcessHeap(), 0, buffer );
67     }
68     if (file == HFILE_ERROR) return 0;
69     size = _llseek( file, 0, 2 );
70     if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
71     {
72         _lclose( file );
73         return 0;
74     }
75     _llseek( file, 0, 0 );
76     size = _lread( file, buffer, size );
77     _lclose( file );
78     fileHeader = (BITMAPFILEHEADER *)buffer;
79     bitmapInfo = (BITMAPINFO *)(buffer + sizeof(BITMAPFILEHEADER));
80     
81       /* Check header content */
82     if ((fileHeader->bfType != 0x4d42) || (size < fileHeader->bfSize))
83     {
84         HeapFree( GetProcessHeap(), 0, buffer );
85         return 0;
86     }
87     hbitmap = CreateDIBitmap( hdc, &bitmapInfo->bmiHeader, CBM_INIT,
88                                 buffer + fileHeader->bfOffBits,
89                                 bitmapInfo, DIB_RGB_COLORS );
90     HeapFree( GetProcessHeap(), 0, buffer );
91     return hbitmap;
92 }
93
94
95
96 /***********************************************************************
97  *           DesktopWndProc
98  */
99 static LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
100 {
101     LRESULT retvalue = 0;
102
103     if (message == WM_NCCREATE)
104     {
105         hbrushPattern = 0;
106         hbitmapWallPaper = 0;
107         SetDeskPattern();
108         SetDeskWallPaper( (LPSTR)-1 );
109         retvalue = 1;
110     }
111     /* all other messages are ignored */
112     return retvalue;
113 }
114
115 /***********************************************************************
116  *           PaintDesktop   (USER32.@)
117  *
118  */
119 BOOL WINAPI PaintDesktop(HDC hdc)
120 {
121     HWND hwnd = GetDesktopWindow();
122
123     /* check for an owning thread; otherwise don't paint anything (non-desktop mode) */
124     if (GetWindowThreadProcessId( hwnd, NULL ))
125     {
126         RECT rect;
127
128         GetClientRect( hwnd, &rect );
129
130         /* Paint desktop pattern (only if wall paper does not cover everything) */
131
132         if (!hbitmapWallPaper ||
133             (!fTileWallPaper && ((bitmapSize.cx < rect.right) || (bitmapSize.cy < rect.bottom))))
134         {
135             HBRUSH brush = hbrushPattern;
136             if (!brush) brush = GetClassLongA( hwnd, GCL_HBRBACKGROUND );
137             /* Set colors in case pattern is a monochrome bitmap */
138             SetBkColor( hdc, RGB(0,0,0) );
139             SetTextColor( hdc, GetSysColor(COLOR_BACKGROUND) );
140             FillRect( hdc, &rect, brush );
141         }
142
143         /* Paint wall paper */
144
145         if (hbitmapWallPaper)
146         {
147             INT x, y;
148             HDC hMemDC = CreateCompatibleDC( hdc );
149
150             SelectObject( hMemDC, hbitmapWallPaper );
151
152             if (fTileWallPaper)
153             {
154                 for (y = 0; y < rect.bottom; y += bitmapSize.cy)
155                     for (x = 0; x < rect.right; x += bitmapSize.cx)
156                         BitBlt( hdc, x, y, bitmapSize.cx, bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
157             }
158             else
159             {
160                 x = (rect.left + rect.right - bitmapSize.cx) / 2;
161                 y = (rect.top + rect.bottom - bitmapSize.cy) / 2;
162                 if (x < 0) x = 0;
163                 if (y < 0) y = 0;
164                 BitBlt( hdc, x, y, bitmapSize.cx, bitmapSize.cy, hMemDC, 0, 0, SRCCOPY );
165             }
166             DeleteDC( hMemDC );
167         }
168     }
169     return TRUE;
170 }
171
172 /***********************************************************************
173  *           OldSetDeskPattern   (USER.279)
174  */
175 BOOL16 WINAPI SetDeskPattern(void)
176 {
177     char buffer[100];
178     GetProfileStringA( "desktop", "Pattern", "(None)", buffer, 100 );
179     return DESKTOP_SetPattern( buffer );
180 }
181
182
183 /***********************************************************************
184  *           SetDeskWallPaper   (USER.285)
185  */
186 BOOL16 WINAPI SetDeskWallPaper16( LPCSTR filename )
187 {
188     return SetDeskWallPaper( filename );
189 }
190
191
192 /***********************************************************************
193  *           SetDeskWallPaper   (USER32.@)
194  *
195  * FIXME: is there a unicode version?
196  */
197 BOOL WINAPI SetDeskWallPaper( LPCSTR filename )
198 {
199     HBITMAP hbitmap;
200     HDC hdc;
201     char buffer[256];
202
203     if (filename == (LPSTR)-1)
204     {
205         GetProfileStringA( "desktop", "WallPaper", "(None)", buffer, 256 );
206         filename = buffer;
207     }
208     hdc = GetDC( 0 );
209     hbitmap = DESKTOP_LoadBitmap( hdc, filename );
210     ReleaseDC( 0, hdc );
211     if (hbitmapWallPaper) DeleteObject( hbitmapWallPaper );
212     hbitmapWallPaper = hbitmap;
213     fTileWallPaper = GetProfileIntA( "desktop", "TileWallPaper", 0 );
214     if (hbitmap)
215     {
216         BITMAP bmp;
217         GetObjectA( hbitmap, sizeof(bmp), &bmp );
218         bitmapSize.cx = (bmp.bmWidth != 0) ? bmp.bmWidth : 1;
219         bitmapSize.cy = (bmp.bmHeight != 0) ? bmp.bmHeight : 1;
220     }
221     return TRUE;
222 }
223
224
225 /***********************************************************************
226  *           DESKTOP_SetPattern
227  *
228  * Set the desktop pattern.
229  */
230 BOOL DESKTOP_SetPattern( LPCSTR pattern )
231 {
232     int pat[8];
233
234     if (hbrushPattern) DeleteObject( hbrushPattern );
235     memset( pat, 0, sizeof(pat) );
236     if (pattern && sscanf( pattern, " %d %d %d %d %d %d %d %d",
237                            &pat[0], &pat[1], &pat[2], &pat[3],
238                            &pat[4], &pat[5], &pat[6], &pat[7] ))
239     {
240         WORD pattern[8];
241         HBITMAP hbitmap;
242         int i;
243
244         for (i = 0; i < 8; i++) pattern[i] = pat[i] & 0xffff;
245         hbitmap = CreateBitmap( 8, 8, 1, 1, (LPSTR)pattern );
246         hbrushPattern = CreatePatternBrush( hbitmap );
247         DeleteObject( hbitmap );
248     }
249     else hbrushPattern = 0;
250     return TRUE;
251 }
252