Use default GUI font instead of hard-coded 'MS Sans Serif'.
[wine] / windows / sysparams.c
1 /*
2  * System parameters functions
3  *
4  * Copyright 1994 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnls.h"
29 #include "wingdi.h"
30 #include "winreg.h"
31 #include "wine/winuser16.h"
32 #include "winerror.h"
33
34 #include "controls.h"
35 #include "user.h"
36 #include "wine/debug.h"
37 #include "sysmetrics.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(system);
40
41 /* System parameter indexes */
42 #define SPI_SETBEEP_IDX                         0
43 #define SPI_SETMOUSE_IDX                        1
44 #define SPI_SETBORDER_IDX                       2
45 #define SPI_SETKEYBOARDSPEED_IDX                3
46 #define SPI_ICONHORIZONTALSPACING_IDX           4
47 #define SPI_SETSCREENSAVETIMEOUT_IDX            5
48 #define SPI_SETGRIDGRANULARITY_IDX              6
49 #define SPI_SETKEYBOARDDELAY_IDX                7
50 #define SPI_ICONVERTICALSPACING_IDX             8
51 #define SPI_SETICONTITLEWRAP_IDX                9
52 #define SPI_SETMENUDROPALIGNMENT_IDX            10
53 #define SPI_SETDOUBLECLKWIDTH_IDX               11
54 #define SPI_SETDOUBLECLKHEIGHT_IDX              12
55 #define SPI_SETDOUBLECLICKTIME_IDX              13
56 #define SPI_SETMOUSEBUTTONSWAP_IDX              14
57 #define SPI_SETDRAGFULLWINDOWS_IDX              15
58 #define SPI_SETWORKAREA_IDX                     16
59 #define SPI_SETSHOWSOUNDS_IDX                   17
60 #define SPI_SETKEYBOARDPREF_IDX                 18
61 #define SPI_SETSCREENREADER_IDX                 19
62 #define SPI_SETSCREENSAVERRUNNING_IDX           20
63 #define SPI_WINE_IDX                            SPI_SETSCREENSAVERRUNNING_IDX
64
65 /**
66  * Names of the registry subkeys of HKEY_CURRENT_USER key and value names
67  * for the system parameters.
68  * Names of the keys are created by adding string "_REGKEY" to
69  * "SET" action names, value names are created by adding "_REG_NAME"
70  * to the "SET" action name.
71  */
72 #define SPI_SETBEEP_REGKEY              "Control Panel\\Sound"
73 #define SPI_SETBEEP_VALNAME             "Beep"
74 #define SPI_SETMOUSE_REGKEY             "Control Panel\\Mouse"
75 #define SPI_SETMOUSE_VALNAME1           "MouseThreshold1"
76 #define SPI_SETMOUSE_VALNAME2           "MouseThreshold2"
77 #define SPI_SETMOUSE_VALNAME3           "MouseSpeed"
78 #define SPI_SETBORDER_REGKEY            "Control Panel\\Desktop"
79 #define SPI_SETBORDER_VALNAME           "BorderWidth"
80 #define SPI_SETKEYBOARDSPEED_REGKEY             "Control Panel\\Keyboard"
81 #define SPI_SETKEYBOARDSPEED_VALNAME            "KeyboardSpeed"
82 #define SPI_ICONHORIZONTALSPACING_REGKEY        "Control Panel\\Desktop"
83 #define SPI_ICONHORIZONTALSPACING_VALNAME       "IconSpacing"
84 #define SPI_SETSCREENSAVETIMEOUT_REGKEY         "Control Panel\\Desktop"
85 #define SPI_SETSCREENSAVETIMEOUT_VALNAME        "ScreenSaveTimeOut"
86 #define SPI_SETSCREENSAVEACTIVE_REGKEY          "Control Panel\\Desktop"
87 #define SPI_SETSCREENSAVEACTIVE_VALNAME         "ScreenSaveActive"
88 #define SPI_SETGRIDGRANULARITY_REGKEY           "Control Panel\\Desktop"
89 #define SPI_SETGRIDGRANULARITY_VALNAME          "GridGranularity"
90 #define SPI_SETKEYBOARDDELAY_REGKEY             "Control Panel\\Keyboard"
91 #define SPI_SETKEYBOARDDELAY_VALNAME            "KeyboardDelay"
92 #define SPI_ICONVERTICALSPACING_REGKEY          "Control Panel\\Desktop"
93 #define SPI_ICONVERTICALSPACING_VALNAME         "IconVerticalSpacing"
94 #define SPI_SETICONTITLEWRAP_REGKEY             "Control Panel\\Desktop"
95 #define SPI_SETICONTITLEWRAP_VALNAME            "IconTitleWrap"
96 #define SPI_SETMENUDROPALIGNMENT_REGKEY         "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"
97 #define SPI_SETMENUDROPALIGNMENT_VALNAME        "MenuDropAlignment"
98 #define SPI_SETDOUBLECLKWIDTH_REGKEY            "Control Panel\\Mouse"
99 #define SPI_SETDOUBLECLKWIDTH_VALNAME           "DoubleClickWidth"
100 #define SPI_SETDOUBLECLKHEIGHT_REGKEY           "Control Panel\\Mouse"
101 #define SPI_SETDOUBLECLKHEIGHT_VALNAME          "DoubleClickHeight"
102 #define SPI_SETDOUBLECLICKTIME_REGKEY           "Control Panel\\Mouse"
103 #define SPI_SETDOUBLECLICKTIME_VALNAME          "DoubleClickSpeed"
104 #define SPI_SETMOUSEBUTTONSWAP_REGKEY           "Control Panel\\Mouse"
105 #define SPI_SETMOUSEBUTTONSWAP_VALNAME          "SwapMouseButtons"
106 #define SPI_SETDRAGFULLWINDOWS_REGKEY           "Control Panel\\Desktop"
107 #define SPI_SETDRAGFULLWINDOWS_VALNAME          "DragFullWindows"
108 #define SPI_SETWORKAREA_REGKEY                  "Control Panel\\Desktop"
109 #define SPI_SETWORKAREA_VALNAME                 "WINE_WorkArea"
110 #define SPI_SETSHOWSOUNDS_REGKEY        "Control Panel\\Accessibility\\ShowSounds"
111 #define SPI_SETSHOWSOUNDS_VALNAME       "On"
112 /* FIXME - real values */
113 #define SPI_SETKEYBOARDPREF_REGKEY      "Control Panel\\Desktop"
114 #define SPI_SETKEYBOARDPREF_VALNAME     "WINE_KeyboardPref"
115 #define SPI_SETSCREENREADER_REGKEY      "Control Panel\\Desktop"
116 #define SPI_SETSCREENREADER_VALNAME     "WINE_ScreenReader"
117 #define SPI_SETSCREENSAVERRUNNING_REGKEY        "Control Panel\\Desktop"
118 #define SPI_SETSCREENSAVERRUNNING_VALNAME       "WINE_ScreenSaverRunning"
119
120 /* volatile registry branch under CURRENT_USER_REGKEY for temporary values storage */
121 #define WINE_CURRENT_USER_REGKEY     "Wine"
122
123 /* Indicators whether system parameter value is loaded */
124 static char spi_loaded[SPI_WINE_IDX + 1];
125
126 static BOOL notify_change = TRUE;
127
128 /* System parameters storage */
129 static BOOL beep_active = TRUE;
130 static int mouse_threshold1 = 6;
131 static int mouse_threshold2 = 10;
132 static int mouse_speed = 1;
133 static int border = 1;
134 static int keyboard_speed = 31;
135 static int screensave_timeout = 300;
136 static int grid_granularity = 0;
137 static int keyboard_delay = 1;
138 static BOOL icon_title_wrap = TRUE;
139 static int double_click_time = 500;
140 static BOOL drag_full_windows = FALSE;
141 static RECT work_area;
142 static BOOL keyboard_pref = TRUE;
143 static BOOL screen_reader = FALSE;
144 static BOOL screensaver_running = FALSE;
145
146 /***********************************************************************
147  *              GetTimerResolution (USER.14)
148  */
149 LONG WINAPI GetTimerResolution16(void)
150 {
151         return (1000);
152 }
153
154 /***********************************************************************
155  *              ControlPanelInfo (USER.273)
156  */
157 void WINAPI ControlPanelInfo16( INT16 nInfoType, WORD wData, LPSTR lpBuffer )
158 {
159         FIXME("(%d, %04x, %p): stub.\n", nInfoType, wData, lpBuffer);
160 }
161
162 /* This function is a copy of the one in objects/font.c */
163 static void SYSPARAMS_LogFont32ATo16( const LOGFONTA* font32, LPLOGFONT16 font16 )
164 {
165     font16->lfHeight = font32->lfHeight;
166     font16->lfWidth = font32->lfWidth;
167     font16->lfEscapement = font32->lfEscapement;
168     font16->lfOrientation = font32->lfOrientation;
169     font16->lfWeight = font32->lfWeight;
170     font16->lfItalic = font32->lfItalic;
171     font16->lfUnderline = font32->lfUnderline;
172     font16->lfStrikeOut = font32->lfStrikeOut;
173     font16->lfCharSet = font32->lfCharSet;
174     font16->lfOutPrecision = font32->lfOutPrecision;
175     font16->lfClipPrecision = font32->lfClipPrecision;
176     font16->lfQuality = font32->lfQuality;
177     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
178     lstrcpynA( font16->lfFaceName, font32->lfFaceName, LF_FACESIZE );
179 }
180
181 static void SYSPARAMS_LogFont32ATo32W( const LOGFONTA* font32A, LPLOGFONTW font32W )
182 {
183     font32W->lfHeight = font32A->lfHeight;
184     font32W->lfWidth = font32A->lfWidth;
185     font32W->lfEscapement = font32A->lfEscapement;
186     font32W->lfOrientation = font32A->lfOrientation;
187     font32W->lfWeight = font32A->lfWeight;
188     font32W->lfItalic = font32A->lfItalic;
189     font32W->lfUnderline = font32A->lfUnderline;
190     font32W->lfStrikeOut = font32A->lfStrikeOut;
191     font32W->lfCharSet = font32A->lfCharSet;
192     font32W->lfOutPrecision = font32A->lfOutPrecision;
193     font32W->lfClipPrecision = font32A->lfClipPrecision;
194     font32W->lfQuality = font32A->lfQuality;
195     font32W->lfPitchAndFamily = font32A->lfPitchAndFamily;
196     MultiByteToWideChar( CP_ACP, 0, font32A->lfFaceName, -1, font32W->lfFaceName, LF_FACESIZE );
197     font32W->lfFaceName[LF_FACESIZE-1] = 0;
198 }
199
200 static void SYSPARAMS_NonClientMetrics32ATo16( const NONCLIENTMETRICSA* lpnm32, LPNONCLIENTMETRICS16 lpnm16 )
201 {
202     lpnm16->iBorderWidth        = lpnm32->iBorderWidth;
203     lpnm16->iScrollWidth        = lpnm32->iScrollWidth;
204     lpnm16->iScrollHeight       = lpnm32->iScrollHeight;
205     lpnm16->iCaptionWidth       = lpnm32->iCaptionWidth;
206     lpnm16->iCaptionHeight      = lpnm32->iCaptionHeight;
207     SYSPARAMS_LogFont32ATo16( &lpnm32->lfCaptionFont,   &lpnm16->lfCaptionFont );
208     lpnm16->iSmCaptionWidth     = lpnm32->iSmCaptionWidth;
209     lpnm16->iSmCaptionHeight    = lpnm32->iSmCaptionHeight;
210     SYSPARAMS_LogFont32ATo16( &lpnm32->lfSmCaptionFont, &lpnm16->lfSmCaptionFont );
211     lpnm16->iMenuWidth          = lpnm32->iMenuWidth;
212     lpnm16->iMenuHeight         = lpnm32->iMenuHeight;
213     SYSPARAMS_LogFont32ATo16( &lpnm32->lfMenuFont,      &lpnm16->lfMenuFont );
214     SYSPARAMS_LogFont32ATo16( &lpnm32->lfStatusFont,    &lpnm16->lfStatusFont );
215     SYSPARAMS_LogFont32ATo16( &lpnm32->lfMessageFont,   &lpnm16->lfMessageFont );
216 }
217
218 static void SYSPARAMS_NonClientMetrics32ATo32W( const NONCLIENTMETRICSA* lpnm32A, LPNONCLIENTMETRICSW lpnm32W )
219 {
220     lpnm32W->iBorderWidth       = lpnm32A->iBorderWidth;
221     lpnm32W->iScrollWidth       = lpnm32A->iScrollWidth;
222     lpnm32W->iScrollHeight      = lpnm32A->iScrollHeight;
223     lpnm32W->iCaptionWidth      = lpnm32A->iCaptionWidth;
224     lpnm32W->iCaptionHeight     = lpnm32A->iCaptionHeight;
225     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfCaptionFont,         &lpnm32W->lfCaptionFont );
226     lpnm32W->iSmCaptionWidth    = lpnm32A->iSmCaptionWidth;
227     lpnm32W->iSmCaptionHeight   = lpnm32A->iSmCaptionHeight;
228     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfSmCaptionFont,       &lpnm32W->lfSmCaptionFont );
229     lpnm32W->iMenuWidth         = lpnm32A->iMenuWidth;
230     lpnm32W->iMenuHeight        = lpnm32A->iMenuHeight;
231     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfMenuFont,            &lpnm32W->lfMenuFont );
232     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfStatusFont,          &lpnm32W->lfStatusFont );
233     SYSPARAMS_LogFont32ATo32W( &lpnm32A->lfMessageFont,         &lpnm32W->lfMessageFont );
234 }
235
236 /***********************************************************************
237  *           SYSPARAMS_Reset
238  *
239  * Sets the system parameter which should be always loaded to
240  * current value stored in registry.
241  * Invalidates lazy loaded parameter, so it will be loaded the next time
242  * it is requested.
243  *
244  * Parameters:
245  * uiAction - system parameter to reload value for.
246  *      Note, only "SET" values can be used for this parameter.
247  *      If uiAction is 0 all system parameters are reset.
248  */
249 void SYSPARAMS_Reset( UINT uiAction )
250 {
251 #define WINE_RELOAD_SPI(x) \
252     case x: \
253         spi_loaded[x##_IDX] = FALSE; \
254         SystemParametersInfoA( x, 0, dummy_buf, 0 );\
255         if (uiAction) \
256             break
257
258 #define WINE_IGNORE_SPI(x) \
259     case x: \
260         if (uiAction) \
261             break
262
263 #define WINE_INVALIDATE_SPI(x) \
264     case x: \
265         spi_loaded[x##_IDX] = FALSE; \
266         break
267
268     BOOL not_all_processed = TRUE;
269     char dummy_buf[10];
270
271     /* Execution falls through all the branches for uiAction == 0 */
272     switch (uiAction)
273     {
274     case 0:
275         memset( spi_loaded, 0, sizeof(spi_loaded) );
276
277     WINE_RELOAD_SPI(SPI_SETBORDER);
278     WINE_RELOAD_SPI(SPI_ICONHORIZONTALSPACING);
279     WINE_RELOAD_SPI(SPI_ICONVERTICALSPACING);
280     WINE_IGNORE_SPI(SPI_SETSCREENSAVEACTIVE);
281     WINE_RELOAD_SPI(SPI_SETDOUBLECLKWIDTH);
282     WINE_RELOAD_SPI(SPI_SETDOUBLECLKHEIGHT);
283     WINE_RELOAD_SPI(SPI_SETMOUSEBUTTONSWAP);
284     WINE_RELOAD_SPI(SPI_SETSHOWSOUNDS);
285     WINE_RELOAD_SPI(SPI_SETMENUDROPALIGNMENT);
286
287     default:
288         if (uiAction)
289         {
290             /* lazy loaded parameters */
291             switch (uiAction)
292             {
293             WINE_INVALIDATE_SPI(SPI_SETBEEP);
294             WINE_INVALIDATE_SPI(SPI_SETMOUSE);
295             WINE_INVALIDATE_SPI(SPI_SETKEYBOARDSPEED);
296             WINE_INVALIDATE_SPI(SPI_SETSCREENSAVETIMEOUT);
297             WINE_INVALIDATE_SPI(SPI_SETGRIDGRANULARITY);
298             WINE_INVALIDATE_SPI(SPI_SETKEYBOARDDELAY);
299             WINE_INVALIDATE_SPI(SPI_SETICONTITLEWRAP);
300             WINE_INVALIDATE_SPI(SPI_SETDOUBLECLICKTIME);
301             WINE_INVALIDATE_SPI(SPI_SETDRAGFULLWINDOWS);
302             WINE_INVALIDATE_SPI(SPI_SETWORKAREA);
303             WINE_INVALIDATE_SPI(SPI_SETKEYBOARDPREF);
304             WINE_INVALIDATE_SPI(SPI_SETSCREENREADER);
305             WINE_INVALIDATE_SPI(SPI_SETSCREENSAVERRUNNING);
306             default:
307                 FIXME( "Unknown action reset: %u\n", uiAction );
308                 break;
309             }
310         }
311         else
312             not_all_processed = FALSE;
313         break;
314     }
315
316     if (!uiAction && not_all_processed)
317         ERR( "Incorrect implementation of SYSPARAMS_Reset. "
318              "Not all params are reloaded.\n" );
319 #undef WINE_INVALIDATE_SPI
320 #undef WINE_IGNORE_SPI
321 #undef WINE_RELOAD_SPI
322 }
323
324 /***********************************************************************
325  *           get_volatile_regkey
326  *
327  * Return a handle to the volatile registry key used to store
328  * non-permanently modified parameters.
329  */
330 static HKEY get_volatile_regkey(void)
331 {
332     static HKEY volatile_key;
333
334     if (!volatile_key)
335     {
336         if (RegCreateKeyExA( HKEY_CURRENT_USER, WINE_CURRENT_USER_REGKEY,
337                              0, 0, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, 0,
338                              &volatile_key, 0 ) != ERROR_SUCCESS)
339             ERR("Can't create wine configuration registry branch");
340     }
341     return volatile_key;
342 }
343
344 /***********************************************************************
345  *           SYSPARAMS_NotifyChange
346  *
347  * Sends notification about system parameter update.
348  */
349 void SYSPARAMS_NotifyChange( UINT uiAction, UINT fWinIni )
350 {
351     if (notify_change)
352     {
353         if (fWinIni & SPIF_UPDATEINIFILE)
354         {
355             if (fWinIni & (SPIF_SENDWININICHANGE | SPIF_SENDCHANGE))
356                 SendMessageA(HWND_BROADCAST, WM_SETTINGCHANGE,
357                              uiAction, (LPARAM) "");
358         }
359         else 
360         {
361             /* FIXME notify other wine processes with internal message */
362         }
363     }
364 }
365
366
367 /***********************************************************************
368  * Loads system parameter from user profile.
369  */
370 BOOL SYSPARAMS_Load( LPSTR lpRegKey, LPSTR lpValName, LPSTR lpBuf )
371 {
372     BOOL ret = FALSE;
373     DWORD type;
374     HKEY hKey;
375     DWORD count;
376
377     if ((RegOpenKeyA( get_volatile_regkey(), lpRegKey,
378                      &hKey ) == ERROR_SUCCESS) ||
379         (RegOpenKeyA( HKEY_CURRENT_USER, lpRegKey,
380                       &hKey ) == ERROR_SUCCESS))
381     {
382         ret = !RegQueryValueExA( hKey, lpValName, NULL, &type, lpBuf, &count );
383         RegCloseKey( hKey );
384     }
385     return ret;
386 }
387
388 /***********************************************************************
389  * Saves system parameter to user profile.
390  */
391 BOOL SYSPARAMS_Save( LPSTR lpRegKey, LPSTR lpValName, LPSTR lpValue,
392                      UINT fWinIni )
393 {
394     HKEY hKey;
395     HKEY hBaseKey;
396     DWORD dwOptions;
397     BOOL ret = FALSE;
398
399     if (fWinIni & SPIF_UPDATEINIFILE)
400     {
401         hBaseKey = HKEY_CURRENT_USER;
402         dwOptions = 0;
403     }
404     else
405     {
406         hBaseKey = get_volatile_regkey();
407         dwOptions = REG_OPTION_VOLATILE;
408     }
409
410     if (RegCreateKeyExA( hBaseKey, lpRegKey,
411                          0, 0, dwOptions, KEY_ALL_ACCESS,
412                          0, &hKey, 0 ) == ERROR_SUCCESS)
413     {
414         if (RegSetValueExA( hKey, lpValName, 0, REG_SZ,
415                             lpValue, strlen(lpValue) + 1 ) == ERROR_SUCCESS)
416         {
417             ret = TRUE;
418             if (hBaseKey == HKEY_CURRENT_USER)
419                 RegDeleteKeyA( get_volatile_regkey(), lpRegKey );
420         }
421         RegCloseKey( hKey );
422     }
423     return ret;
424 }
425
426
427 /***********************************************************************
428  *           SYSPARAMS_GetDoubleClickSize
429  *
430  * There is no SPI_GETDOUBLECLK* so we export this function instead.
431  */
432 void SYSPARAMS_GetDoubleClickSize( INT *width, INT *height )
433 {
434     char buf[10];
435
436     if (!spi_loaded[SPI_SETDOUBLECLKWIDTH_IDX])
437     {
438         char buf[10];
439
440         if (SYSPARAMS_Load( SPI_SETDOUBLECLKWIDTH_REGKEY,
441                             SPI_SETDOUBLECLKWIDTH_VALNAME, buf ))
442         {
443             SYSMETRICS_Set( SM_CXDOUBLECLK, atoi( buf ) );
444         }
445         spi_loaded[SPI_SETDOUBLECLKWIDTH_IDX] = TRUE;
446     }
447     if (!spi_loaded[SPI_SETDOUBLECLKHEIGHT_IDX])
448     {
449         if (SYSPARAMS_Load( SPI_SETDOUBLECLKHEIGHT_REGKEY,
450                             SPI_SETDOUBLECLKHEIGHT_VALNAME, buf ))
451         {
452             SYSMETRICS_Set( SM_CYDOUBLECLK, atoi( buf ) );
453         }
454         spi_loaded[SPI_SETDOUBLECLKHEIGHT_IDX] = TRUE;
455     }
456     *width  = GetSystemMetrics( SM_CXDOUBLECLK );
457     *height = GetSystemMetrics( SM_CYDOUBLECLK );
458 }
459
460
461 /***********************************************************************
462  *           SYSPARAMS_GetMouseButtonSwap
463  *
464  * There is no SPI_GETMOUSEBUTTONSWAP so we export this function instead.
465  */
466 INT SYSPARAMS_GetMouseButtonSwap( void )
467 {
468         int spi_idx = SPI_SETMOUSEBUTTONSWAP_IDX;
469
470         if (!spi_loaded[spi_idx])
471         {
472             char buf[5];
473
474             if (SYSPARAMS_Load( SPI_SETMOUSEBUTTONSWAP_REGKEY,
475                                 SPI_SETMOUSEBUTTONSWAP_VALNAME, buf ))
476             {
477                 SYSMETRICS_Set( SM_SWAPBUTTON, atoi( buf ) );
478             }
479             spi_loaded[spi_idx] = TRUE;
480         }
481
482         return GetSystemMetrics( SM_SWAPBUTTON );
483 }
484
485 /***********************************************************************
486  *
487  *      SYSPARAMS_GetGUIFont
488  *
489  *  fills LOGFONT with 'default GUI font'.
490  */
491
492 static void SYSPARAMS_GetGUIFont( LOGFONTA* plf )
493 {
494         HFONT   hf;
495
496         memset( plf, 0, sizeof(LOGFONTA) );
497         hf = (HFONT)GetStockObject( DEFAULT_GUI_FONT );
498         if ( GetObjectA( hf, sizeof(LOGFONTA), plf ) != sizeof(LOGFONTA) )
499         {
500                 /*
501                  * GetObjectA() would be succeeded always
502                  * since this is a stock object
503                  */
504                 ERR("GetObjectA() failed\n");
505         }
506 }
507
508 /***********************************************************************
509  *              SystemParametersInfoA (USER32.@)
510  *
511  *     Each system parameter has flag which shows whether the parameter
512  * is loaded or not. Parameters, stored directly in SysParametersInfo are
513  * loaded from registry only when they are requested and the flag is
514  * "false", after the loading the flag is set to "true". On interprocess
515  * notification of the parameter change the corresponding parameter flag is
516  * set to "false". The parameter value will be reloaded when it is requested
517  * the next time.
518  *     Parameters, backed by or depend on GetSystemMetrics are processed
519  * differently. These parameters are always loaded. They are reloaded right
520  * away on interprocess change notification. We can't do lazy loading because
521  * we don't want to complicate GetSystemMetrics.
522  *     Parameters, backed by X settings are read from corresponding setting.
523  * On the parameter change request the setting is changed. Interprocess change
524  * notifications are ignored.
525  *     When parameter value is updated the changed value is stored in permanent
526  * registry branch if saving is requested. Otherwise it is stored
527  * in temporary branch
528  *
529  */
530 BOOL WINAPI SystemParametersInfoA( UINT uiAction, UINT uiParam,
531                                    PVOID pvParam, UINT fWinIni )
532 {
533 #define WINE_SPI_FIXME(x) \
534     case x: \
535         FIXME( "Unimplemented action: %u (%s)\n", x, #x ); \
536         SetLastError( ERROR_INVALID_SPI_VALUE ); \
537         ret = FALSE; \
538         break
539 #define WINE_SPI_WARN(x) \
540     case x: \
541         WARN( "Ignored action: %u (%s)\n", x, #x ); \
542         break
543
544     BOOL ret = TRUE;
545     unsigned spi_idx = 0;
546     
547     TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fWinIni);
548     
549     switch (uiAction)
550     {
551     case SPI_GETBEEP:                           /*      1 */
552         spi_idx = SPI_SETBEEP_IDX;
553         if (!spi_loaded[spi_idx])
554         {
555             char buf[5];
556             
557             if (SYSPARAMS_Load( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME, buf ))
558                 beep_active  = !strcasecmp( "Yes", buf );
559             spi_loaded[spi_idx] = TRUE;
560         }
561         
562         *(BOOL *)pvParam = beep_active;
563         break;
564
565     case SPI_SETBEEP:                           /*      2 */
566         spi_idx = SPI_SETBEEP_IDX;
567         if (SYSPARAMS_Save( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME,
568                             (uiParam ? "Yes" : "No"), fWinIni ))
569         {
570             beep_active = uiParam;
571             spi_loaded[spi_idx] = TRUE;
572         }
573         else
574             ret = FALSE;
575         break;
576
577     case SPI_GETMOUSE:                          /*      3 */
578         spi_idx = SPI_SETMOUSE_IDX;
579         if (!spi_loaded[spi_idx])
580         {
581             char buf[10];
582
583             if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME1,
584                                 buf ))
585                 mouse_threshold1 = atoi( buf );
586             if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME2,
587                                 buf ))
588                 mouse_threshold2 = atoi( buf );
589             if (SYSPARAMS_Load( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME3,
590                                 buf ))
591                 mouse_speed = atoi( buf );
592             spi_loaded[spi_idx] = TRUE;
593         }
594         ((INT *)pvParam)[0] = mouse_threshold1;
595         ((INT *)pvParam)[1] = mouse_threshold2;
596         ((INT *)pvParam)[2] = mouse_speed;
597         break;
598         
599     case SPI_SETMOUSE:                          /*      4 */
600     {
601         char buf[10];
602
603         spi_idx = SPI_SETMOUSE_IDX;
604         sprintf(buf, "%d", ((INT *)pvParam)[0]);
605
606         if (SYSPARAMS_Save( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME1,
607                             buf, fWinIni ))
608         {
609             mouse_threshold1 = ((INT *)pvParam)[0];
610             spi_loaded[spi_idx] = TRUE;
611
612             sprintf(buf, "%d", ((INT *)pvParam)[1]);
613             SYSPARAMS_Save( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME2,
614                             buf, fWinIni );
615             mouse_threshold2 = ((INT *)pvParam)[1];
616
617             sprintf(buf, "%d", ((INT *)pvParam)[2]);
618             SYSPARAMS_Save( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME3,
619                             buf, fWinIni );
620             mouse_speed = ((INT *)pvParam)[2];
621         }
622         else
623             ret = FALSE;
624         break;
625     }
626
627     case SPI_GETBORDER:                         /*      5 */
628         spi_idx = SPI_SETBORDER_IDX;
629         if (!spi_loaded[spi_idx])
630         {
631             char buf[10];
632
633             if (SYSPARAMS_Load( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME,
634                                 buf ))
635             {
636                 int i = atoi( buf );
637                 if (i > 0) border = i;
638             }
639             spi_loaded[spi_idx] = TRUE;
640             if (TWEAK_WineLook > WIN31_LOOK)
641             {
642                 SYSMETRICS_Set( SM_CXFRAME, border + GetSystemMetrics( SM_CXDLGFRAME ) );
643                 SYSMETRICS_Set( SM_CYFRAME, border + GetSystemMetrics( SM_CXDLGFRAME ) );
644             }
645         }
646         *(INT *)pvParam = border;
647         break;
648
649     case SPI_SETBORDER:                         /*      6 */
650     {
651         char buf[10];
652
653         spi_idx = SPI_SETBORDER_IDX;
654         sprintf(buf, "%u", uiParam);
655
656         if (SYSPARAMS_Save( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME,
657                             buf, fWinIni ))
658         {
659             if (uiParam > 0) 
660             {
661                 border = uiParam;
662                 spi_loaded[spi_idx] = TRUE;
663                 if (TWEAK_WineLook > WIN31_LOOK)
664                 {
665                     SYSMETRICS_Set( SM_CXFRAME, uiParam + GetSystemMetrics( SM_CXDLGFRAME ) );
666                     SYSMETRICS_Set( SM_CYFRAME, uiParam + GetSystemMetrics( SM_CXDLGFRAME ) );
667                 }
668             }
669         }
670         else
671             ret = FALSE;
672         break;
673     }
674
675     case SPI_GETKEYBOARDSPEED:                  /*     10 */
676         spi_idx = SPI_SETKEYBOARDSPEED_IDX;
677         if (!spi_loaded[spi_idx])
678         {
679             char buf[10];
680
681             if (SYSPARAMS_Load( SPI_SETKEYBOARDSPEED_REGKEY,
682                                 SPI_SETKEYBOARDSPEED_VALNAME,
683                                 buf ))
684                 keyboard_speed = atoi( buf );
685             spi_loaded[spi_idx] = TRUE;
686         }
687         *(INT *)pvParam = keyboard_speed;
688         break;
689
690     case SPI_SETKEYBOARDSPEED:                  /*     11 */
691     {
692         char buf[10];
693
694         spi_idx = SPI_SETKEYBOARDSPEED_IDX;
695         if (uiParam > 31)
696             uiParam = 31;
697         sprintf(buf, "%u", uiParam);
698
699         if (SYSPARAMS_Save( SPI_SETKEYBOARDSPEED_REGKEY,
700                             SPI_SETKEYBOARDSPEED_VALNAME,
701                             buf, fWinIni ))
702         {
703             keyboard_speed = uiParam;
704             spi_loaded[spi_idx] = TRUE;
705         }
706         else
707             ret = FALSE;
708         break;
709     }
710
711     /* not implemented in Windows */
712     WINE_SPI_WARN(SPI_LANGDRIVER);              /*     12 */
713
714     case SPI_ICONHORIZONTALSPACING:             /*     13 */
715         spi_idx = SPI_ICONHORIZONTALSPACING_IDX;
716         if (pvParam != NULL)
717         {
718             if (!spi_loaded[spi_idx])
719             {
720                 char buf[10];
721             
722                 if (SYSPARAMS_Load( SPI_ICONHORIZONTALSPACING_REGKEY,
723                                     SPI_ICONHORIZONTALSPACING_VALNAME, buf ))
724                 {
725                     SYSMETRICS_Set( SM_CXICONSPACING, atoi( buf ) );
726                 }
727                 spi_loaded[spi_idx] = TRUE;
728             }
729
730             *(INT *)pvParam = GetSystemMetrics( SM_CXICONSPACING );
731         }
732         else
733         {
734             char buf[10];
735
736             if (uiParam < 32) uiParam = 32;
737
738             sprintf(buf, "%u", uiParam);
739             if (SYSPARAMS_Save( SPI_ICONHORIZONTALSPACING_REGKEY,
740                                 SPI_ICONHORIZONTALSPACING_VALNAME,
741                                 buf, fWinIni ))
742             {
743                 SYSMETRICS_Set( SM_CXICONSPACING, uiParam );
744                 spi_loaded[spi_idx] = TRUE;
745             }
746             else
747                 ret = FALSE;
748         }
749         break;
750
751     case SPI_GETSCREENSAVETIMEOUT:              /*     14 */
752         spi_idx = SPI_SETSCREENSAVETIMEOUT_IDX;
753         if (!spi_loaded[spi_idx])
754         {
755             char buf[10];
756
757             if (SYSPARAMS_Load( SPI_SETSCREENSAVETIMEOUT_REGKEY,
758                                 SPI_SETSCREENSAVETIMEOUT_VALNAME,
759                                 buf ))
760                 screensave_timeout = atoi( buf );
761
762             spi_loaded[spi_idx] = TRUE;
763         }
764         *(INT *)pvParam = screensave_timeout;
765         break;
766
767     case SPI_SETSCREENSAVETIMEOUT:              /*     15 */
768     {
769         char buf[10];
770
771         spi_idx = SPI_SETSCREENSAVETIMEOUT_IDX;
772         sprintf(buf, "%u", uiParam);
773
774         if (SYSPARAMS_Save( SPI_SETSCREENSAVETIMEOUT_REGKEY,
775                             SPI_SETSCREENSAVETIMEOUT_VALNAME,
776                             buf, fWinIni ))
777         {
778             screensave_timeout = uiParam;
779             spi_loaded[spi_idx] = TRUE;
780         }
781         else
782             ret = FALSE;
783         break;
784     }
785         
786     case SPI_GETSCREENSAVEACTIVE:               /*     16 */
787         *(BOOL *)pvParam = USER_Driver.pGetScreenSaveActive();
788         break;
789
790     case SPI_SETSCREENSAVEACTIVE:               /*     17 */
791     {
792         char buf[5];
793
794         sprintf(buf, "%u", uiParam);
795         USER_Driver.pSetScreenSaveActive( uiParam );
796         /* saved value does not affect Wine */
797         SYSPARAMS_Save( SPI_SETSCREENSAVEACTIVE_REGKEY,
798                         SPI_SETSCREENSAVEACTIVE_VALNAME,
799                         buf, fWinIni );
800         break;
801     }
802         
803     case SPI_GETGRIDGRANULARITY:                /*     18 */
804         spi_idx = SPI_SETGRIDGRANULARITY_IDX;
805         if (!spi_loaded[spi_idx])
806         {
807             char buf[10];
808
809             if (SYSPARAMS_Load( SPI_SETGRIDGRANULARITY_REGKEY,
810                                 SPI_SETGRIDGRANULARITY_VALNAME,
811                                 buf ))
812                 grid_granularity = atoi( buf );
813             
814             spi_loaded[spi_idx] = TRUE;
815         }
816         *(INT *)pvParam = grid_granularity;
817         break;
818
819     case SPI_SETGRIDGRANULARITY:                /*     19 */
820     {
821         char buf[10];
822
823         spi_idx = SPI_SETGRIDGRANULARITY_IDX;
824         sprintf(buf, "%u", uiParam);
825
826         if (SYSPARAMS_Save( SPI_SETGRIDGRANULARITY_REGKEY,
827                             SPI_SETGRIDGRANULARITY_VALNAME,
828                             buf, fWinIni ))
829         {
830             grid_granularity = uiParam;
831             spi_loaded[spi_idx] = TRUE;
832         }
833         else
834             ret = FALSE;
835         break;
836     }
837
838     case SPI_SETDESKWALLPAPER:                  /*     20 */
839         ret = SetDeskWallPaper( (LPSTR)pvParam );
840         break;
841     case SPI_SETDESKPATTERN:                    /*     21 */
842         /* FIXME: the ability to specify a pattern in pvParam
843            doesn't seem to be documented for Win32 */
844         if ((INT16)uiParam == -1)
845         {
846             char buffer[256];
847             GetProfileStringA( "Desktop", "Pattern", 
848                                "170 85 170 85 170 85 170 85", 
849                                buffer, sizeof(buffer) );
850             ret = DESKTOP_SetPattern( (LPSTR)buffer );
851         } else
852             ret = DESKTOP_SetPattern( (LPSTR)pvParam );
853         break;
854
855     case SPI_GETKEYBOARDDELAY:                  /*     22 */
856         spi_idx = SPI_SETKEYBOARDDELAY_IDX;
857         if (!spi_loaded[spi_idx])
858         {
859             char buf[10];
860
861             if (SYSPARAMS_Load( SPI_SETKEYBOARDDELAY_REGKEY,
862                                 SPI_SETKEYBOARDDELAY_VALNAME,
863                                 buf ))
864             {
865                 int i = atoi( buf );
866                 if ( (i >= 0) && (i <= 3)) keyboard_delay = i;
867             }
868             
869             spi_loaded[spi_idx] = TRUE;
870         }
871         *(INT *)pvParam = keyboard_delay;
872         break;
873
874     case SPI_SETKEYBOARDDELAY:                  /*     23 */
875     {
876         char buf[10];
877
878         spi_idx = SPI_SETKEYBOARDDELAY_IDX;
879         sprintf(buf, "%u", uiParam);
880
881         if (SYSPARAMS_Save( SPI_SETKEYBOARDDELAY_REGKEY,
882                             SPI_SETKEYBOARDDELAY_VALNAME,
883                             buf, fWinIni ))
884         {
885             if (uiParam <= 3)
886                 keyboard_delay = uiParam;
887             spi_loaded[spi_idx] = TRUE;
888         }
889         else
890             ret = FALSE;
891         break;
892     }
893
894     case SPI_ICONVERTICALSPACING:               /*     24 */
895         spi_idx = SPI_ICONVERTICALSPACING_IDX;
896         if (pvParam != NULL)
897         {
898             if (!spi_loaded[spi_idx])
899             {
900                 char buf[10];
901             
902                 if (SYSPARAMS_Load( SPI_ICONVERTICALSPACING_REGKEY,
903                                     SPI_ICONVERTICALSPACING_VALNAME, buf ))
904                 {
905                     SYSMETRICS_Set( SM_CYICONSPACING, atoi( buf ) );
906                 }
907                 spi_loaded[spi_idx] = TRUE;
908             }
909
910             *(INT *)pvParam = GetSystemMetrics( SM_CYICONSPACING );
911         }
912         else
913         {
914             char buf[10];
915
916             if (uiParam < 32) uiParam = 32;
917
918             sprintf(buf, "%u", uiParam);
919             if (SYSPARAMS_Save( SPI_ICONVERTICALSPACING_REGKEY,
920                                 SPI_ICONVERTICALSPACING_VALNAME,
921                                 buf, fWinIni ))
922             {
923                 SYSMETRICS_Set( SM_CYICONSPACING, uiParam );
924                 spi_loaded[spi_idx] = TRUE;
925             }
926             else
927                 ret = FALSE;
928         }
929         
930         break;
931
932     case SPI_GETICONTITLEWRAP:                  /*     25 */
933         spi_idx = SPI_SETICONTITLEWRAP_IDX;
934         if (!spi_loaded[spi_idx])
935         {
936             char buf[5];
937
938             if (SYSPARAMS_Load( SPI_SETICONTITLEWRAP_REGKEY,
939                                 SPI_SETICONTITLEWRAP_VALNAME, buf ))
940                 icon_title_wrap  = atoi(buf);
941             spi_loaded[spi_idx] = TRUE;
942         }
943         
944         *(BOOL *)pvParam = icon_title_wrap;
945         break;
946
947     case SPI_SETICONTITLEWRAP:                  /*     26 */
948     {
949         char buf[5];
950
951         spi_idx = SPI_SETICONTITLEWRAP_IDX;
952         sprintf(buf, "%u", uiParam);
953         if (SYSPARAMS_Save( SPI_SETICONTITLEWRAP_REGKEY,
954                             SPI_SETICONTITLEWRAP_VALNAME,
955                             buf, fWinIni ))
956         {
957             icon_title_wrap = uiParam;
958             spi_loaded[spi_idx] = TRUE;
959         }
960         else
961             ret = FALSE;
962         break;
963     }
964     
965     case SPI_GETMENUDROPALIGNMENT:              /*     27 */
966         spi_idx = SPI_SETMENUDROPALIGNMENT_IDX;
967
968         if (!spi_loaded[spi_idx])
969         {
970             char buf[5];
971             
972             if (SYSPARAMS_Load( SPI_SETMENUDROPALIGNMENT_REGKEY,
973                                 SPI_SETMENUDROPALIGNMENT_VALNAME, buf ))
974             {
975                 SYSMETRICS_Set( SM_MENUDROPALIGNMENT, atoi( buf ) );
976             }
977             spi_loaded[spi_idx] = TRUE;
978         }
979         
980
981         *(BOOL *)pvParam = GetSystemMetrics( SM_MENUDROPALIGNMENT );
982         break;
983
984     case SPI_SETMENUDROPALIGNMENT:              /*     28 */
985     {
986         char buf[5];
987         spi_idx = SPI_SETMENUDROPALIGNMENT_IDX;
988
989         sprintf(buf, "%u", uiParam);
990         if (SYSPARAMS_Save( SPI_SETMENUDROPALIGNMENT_REGKEY,
991                             SPI_SETMENUDROPALIGNMENT_VALNAME,
992                             buf, fWinIni ))
993         {
994             SYSMETRICS_Set( SM_MENUDROPALIGNMENT, uiParam );
995             spi_loaded[spi_idx] = TRUE;
996         }
997         else
998             ret = FALSE;
999         break;
1000     }
1001
1002     case SPI_SETDOUBLECLKWIDTH:                 /*     29 */
1003     {
1004         char buf[10];
1005         spi_idx = SPI_SETDOUBLECLKWIDTH_IDX;
1006
1007         sprintf(buf, "%u", uiParam);
1008         if (SYSPARAMS_Save( SPI_SETDOUBLECLKWIDTH_REGKEY,
1009                             SPI_SETDOUBLECLKWIDTH_VALNAME,
1010                             buf, fWinIni ))
1011         {
1012             SYSMETRICS_Set( SM_CXDOUBLECLK, uiParam );
1013             spi_loaded[spi_idx] = TRUE;
1014         }
1015         else
1016             ret = FALSE;
1017         break;
1018     }
1019
1020     case SPI_SETDOUBLECLKHEIGHT:                /*     30 */
1021     {
1022         char buf[10];
1023         spi_idx = SPI_SETDOUBLECLKHEIGHT_IDX;
1024
1025         sprintf(buf, "%u", uiParam);
1026         if (SYSPARAMS_Save( SPI_SETDOUBLECLKHEIGHT_REGKEY,
1027                             SPI_SETDOUBLECLKHEIGHT_VALNAME,
1028                             buf, fWinIni ))
1029         {
1030             SYSMETRICS_Set( SM_CYDOUBLECLK, uiParam );
1031             spi_loaded[spi_idx] = TRUE;
1032         }
1033         else
1034             ret = FALSE;
1035         break;
1036     }
1037
1038     case SPI_GETICONTITLELOGFONT:               /*     31 */
1039     {
1040         LPLOGFONTA lpLogFont = (LPLOGFONTA)pvParam;
1041         LOGFONTA        lfDefault;
1042
1043         /*
1044          * The 'default GDI fonts' seems to be returned.
1045          * If a returned font is not a correct font in your environment,
1046          * please try to fix objects/gdiobj.c at first.
1047          */
1048         SYSPARAMS_GetGUIFont( &lfDefault );
1049
1050         GetProfileStringA( "Desktop", "IconTitleFaceName",
1051                            lfDefault.lfFaceName, 
1052                            lpLogFont->lfFaceName, LF_FACESIZE );
1053         lpLogFont->lfHeight = -GetProfileIntA( "Desktop", "IconTitleSize", 13 );
1054         lpLogFont->lfWidth = 0;
1055         lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
1056         lpLogFont->lfWeight = FW_NORMAL;
1057         lpLogFont->lfItalic = FALSE;
1058         lpLogFont->lfStrikeOut = FALSE;
1059         lpLogFont->lfUnderline = FALSE;
1060         lpLogFont->lfCharSet = lfDefault.lfCharSet; /* at least 'charset' should not be hard-coded */
1061         lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1062         lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1063         lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
1064         break;
1065     }
1066
1067     case SPI_SETDOUBLECLICKTIME:                /*     32 */
1068     {
1069         char buf[10];
1070
1071         spi_idx = SPI_SETDOUBLECLICKTIME_IDX;
1072         sprintf(buf, "%u", uiParam);
1073
1074         if (SYSPARAMS_Save( SPI_SETDOUBLECLICKTIME_REGKEY,
1075                             SPI_SETDOUBLECLICKTIME_VALNAME,
1076                             buf, fWinIni ))
1077         {
1078             if (!uiParam)
1079                 uiParam = 500;
1080             double_click_time = uiParam;
1081             spi_loaded[spi_idx] = TRUE;
1082         }
1083         else
1084             ret = FALSE;
1085         break;
1086     }
1087
1088     case SPI_SETMOUSEBUTTONSWAP:                /*     33 */
1089     {
1090         char buf[5];
1091         spi_idx = SPI_SETMOUSEBUTTONSWAP_IDX;
1092
1093         sprintf(buf, "%u", uiParam);
1094         if (SYSPARAMS_Save( SPI_SETMOUSEBUTTONSWAP_REGKEY,
1095                             SPI_SETMOUSEBUTTONSWAP_VALNAME,
1096                             buf, fWinIni ))
1097         {
1098             SYSMETRICS_Set( SM_SWAPBUTTON, uiParam );
1099             spi_loaded[spi_idx] = TRUE;
1100         }
1101         else
1102             ret = FALSE;
1103         break;
1104     }
1105
1106     WINE_SPI_FIXME(SPI_SETICONTITLELOGFONT);    /*     34 */
1107
1108     case SPI_GETFASTTASKSWITCH:                 /*     35 */
1109         *(BOOL *)pvParam = 1;
1110         break;
1111
1112     case SPI_SETFASTTASKSWITCH:                 /*     36 */
1113         /* the action is disabled */
1114         ret = FALSE;
1115         break;
1116     
1117     case SPI_SETDRAGFULLWINDOWS:                /*     37  WINVER >= 0x0400 */
1118     {
1119         char buf[5];
1120
1121         spi_idx = SPI_SETDRAGFULLWINDOWS_IDX;
1122         sprintf(buf, "%u", uiParam);
1123         if (SYSPARAMS_Save( SPI_SETDRAGFULLWINDOWS_REGKEY,
1124                             SPI_SETDRAGFULLWINDOWS_VALNAME,
1125                             buf, fWinIni ))
1126         {
1127             drag_full_windows = uiParam;
1128             spi_loaded[spi_idx] = TRUE;
1129         }
1130         else
1131             ret = FALSE;
1132         break;
1133     }
1134
1135     case SPI_GETDRAGFULLWINDOWS:                /*     38  WINVER >= 0x0400 */
1136         spi_idx = SPI_SETDRAGFULLWINDOWS_IDX;
1137         if (!spi_loaded[spi_idx])
1138         {
1139             char buf[5];
1140
1141             if (SYSPARAMS_Load( SPI_SETDRAGFULLWINDOWS_REGKEY,
1142                                 SPI_SETDRAGFULLWINDOWS_VALNAME, buf ))
1143                 drag_full_windows  = atoi(buf);
1144             spi_loaded[spi_idx] = TRUE;
1145         }
1146         
1147         *(BOOL *)pvParam = drag_full_windows;
1148         break;
1149
1150     case SPI_GETNONCLIENTMETRICS:               /*     41  WINVER >= 0x400 */
1151     {
1152         LPNONCLIENTMETRICSA lpnm = (LPNONCLIENTMETRICSA)pvParam;
1153                 
1154         if (lpnm->cbSize == sizeof(NONCLIENTMETRICSA))
1155         {
1156             LPLOGFONTA lpLogFont = &(lpnm->lfMenuFont);
1157             
1158             /* clear the struct, so we have 'sane' members */
1159             memset(
1160                 (char *)pvParam + sizeof(lpnm->cbSize),
1161                 0,
1162                 lpnm->cbSize - sizeof(lpnm->cbSize)
1163                 );
1164
1165             /* initialize geometry entries */
1166             lpnm->iBorderWidth = -1;      /* FIXME */
1167             lpnm->iScrollWidth = GetSystemMetrics(SM_CXVSCROLL);
1168             lpnm->iScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
1169             /* caption */
1170             lpnm->iCaptionWidth = GetSystemMetrics(SM_CXSIZE);
1171             lpnm->iCaptionHeight = lpnm->iCaptionWidth;
1172             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, (LPVOID)&(lpnm->lfCaptionFont), 0 );
1173             lpnm->lfCaptionFont.lfWeight = FW_BOLD;
1174
1175             /* small caption */
1176             lpnm->iSmCaptionWidth = GetSystemMetrics(SM_CXSMSIZE);
1177             lpnm->iSmCaptionHeight = lpnm->iSmCaptionWidth;
1178             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, (LPVOID)&(lpnm->lfSmCaptionFont), 0 );
1179
1180             /* menus, FIXME: names of wine.conf entries are bogus */
1181
1182             lpnm->iMenuWidth = GetProfileIntA( "Desktop", "MenuWidth", 13 );    /* size of the menu buttons*/
1183             lpnm->iMenuHeight = GetProfileIntA( "Desktop", "MenuHeight", 
1184                                                 (TWEAK_WineLook > WIN31_LOOK) ? 13 : 27 );
1185
1186             GetProfileStringA( "Desktop", "MenuFont", 
1187                                (TWEAK_WineLook > WIN31_LOOK) ? lpnm->lfCaptionFont.lfFaceName : "System", 
1188                                lpLogFont->lfFaceName, LF_FACESIZE );
1189
1190             lpLogFont->lfHeight = -GetProfileIntA( "Desktop", "MenuFontSize", 13 );
1191             lpLogFont->lfWidth = 0;
1192             lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
1193             lpLogFont->lfWeight = (TWEAK_WineLook > WIN31_LOOK) ? FW_NORMAL : FW_BOLD;
1194             lpLogFont->lfItalic = FALSE;
1195             lpLogFont->lfStrikeOut = FALSE;
1196             lpLogFont->lfUnderline = FALSE;
1197             lpLogFont->lfCharSet = lpnm->lfCaptionFont.lfCharSet;
1198             lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1199             lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1200             lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
1201
1202             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0,
1203                                    (LPVOID)&(lpnm->lfStatusFont), 0 );
1204             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0,
1205                                    (LPVOID)&(lpnm->lfMessageFont), 0 );
1206         }
1207         else
1208         {
1209             WARN("size mismatch !! (is %d; should be %d)\n", lpnm->cbSize, sizeof(NONCLIENTMETRICSA));
1210             /* FIXME: SetLastError? */
1211             ret = FALSE;
1212         }
1213         break;
1214     }
1215     WINE_SPI_FIXME(SPI_SETNONCLIENTMETRICS);    /*     42  WINVER >= 0x400 */
1216
1217     WINE_SPI_FIXME(SPI_GETMINIMIZEDMETRICS);    /*     43  WINVER >= 0x400 */
1218     WINE_SPI_FIXME(SPI_SETMINIMIZEDMETRICS);    /*     44  WINVER >= 0x400 */
1219
1220     case SPI_GETICONMETRICS:                    /*     45  WINVER >= 0x400 */
1221     {
1222         LPICONMETRICSA lpIcon = pvParam;
1223         if(lpIcon && lpIcon->cbSize == sizeof(*lpIcon))
1224         {
1225             SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0,
1226                                    &lpIcon->iHorzSpacing, FALSE );
1227             SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0,
1228                                    &lpIcon->iVertSpacing, FALSE );
1229             SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0,
1230                                    &lpIcon->iTitleWrap, FALSE );
1231             SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0,
1232                                    &lpIcon->lfFont, FALSE );
1233         }
1234         else
1235         {
1236             ret = FALSE;
1237         }
1238         break;
1239     }
1240     WINE_SPI_FIXME(SPI_SETICONMETRICS);         /*     46  WINVER >= 0x400 */
1241
1242     case SPI_SETWORKAREA:                       /*     47  WINVER >= 0x400 */
1243     {
1244         char buf[20];
1245         RECT *pr = (RECT *) pvParam;
1246
1247         spi_idx = SPI_SETWORKAREA_IDX;
1248         sprintf(buf, "%d %d %d %d",
1249                 pr->left, pr->top,
1250                 pr->right, pr->bottom );
1251
1252         if (SYSPARAMS_Save( SPI_SETWORKAREA_REGKEY,
1253                             SPI_SETWORKAREA_VALNAME,
1254                             buf, fWinIni ))
1255         {
1256             CopyRect( &work_area, (RECT *)pvParam );
1257             spi_loaded[spi_idx] = TRUE;
1258         }
1259         else
1260             ret = FALSE;
1261         break;
1262     }
1263
1264     case SPI_GETWORKAREA:                       /*     48  WINVER >= 0x400 */
1265       spi_idx = SPI_SETWORKAREA_IDX;
1266       if (!spi_loaded[spi_idx])
1267       {
1268           char buf[20];
1269
1270           SetRect( &work_area, 0, 0,
1271                    GetSystemMetrics( SM_CXSCREEN ),
1272                    GetSystemMetrics( SM_CYSCREEN ) );
1273           
1274           if (SYSPARAMS_Load( SPI_SETWORKAREA_REGKEY,
1275                               SPI_SETWORKAREA_VALNAME,
1276                               buf ))
1277           {
1278               sscanf( buf, "%d %d %d %d",
1279                       &work_area.left, &work_area.top,
1280                       &work_area.right, &work_area.bottom );
1281           }
1282           spi_loaded[spi_idx] = TRUE;
1283       }
1284       CopyRect( (RECT *)pvParam, &work_area );
1285
1286       break;
1287
1288     WINE_SPI_FIXME(SPI_SETPENWINDOWS);          /*     49  WINVER >= 0x400 */
1289
1290     case SPI_GETFILTERKEYS:                     /*     50 */
1291     {
1292         LPFILTERKEYS lpFilterKeys = (LPFILTERKEYS)pvParam;
1293         WARN("SPI_GETFILTERKEYS not fully implemented\n");
1294         if (lpFilterKeys->cbSize == sizeof(FILTERKEYS))
1295         {
1296             /* Indicate that no FilterKeys feature available */
1297             lpFilterKeys->dwFlags = 0;
1298             lpFilterKeys->iWaitMSec = 0;
1299             lpFilterKeys->iDelayMSec = 0;
1300             lpFilterKeys->iRepeatMSec = 0;
1301             lpFilterKeys->iBounceMSec = 0;
1302          }
1303         else
1304         {
1305             ret = FALSE;
1306         }
1307         break;
1308     }
1309     WINE_SPI_FIXME(SPI_SETFILTERKEYS);          /*     51 */
1310
1311     case SPI_GETTOGGLEKEYS:                     /*     52 */
1312     {
1313         LPTOGGLEKEYS lpToggleKeys = (LPTOGGLEKEYS)pvParam;
1314         WARN("SPI_GETTOGGLEKEYS not fully implemented\n");
1315         if (lpToggleKeys->cbSize == sizeof(TOGGLEKEYS))
1316         {
1317             /* Indicate that no ToggleKeys feature available */
1318             lpToggleKeys->dwFlags = 0;
1319         }
1320         else
1321         {
1322             ret = FALSE;
1323         }
1324         break;
1325     }
1326     WINE_SPI_FIXME(SPI_SETTOGGLEKEYS);          /*     53 */
1327
1328     case SPI_GETMOUSEKEYS:                      /*     54 */
1329     {
1330         LPMOUSEKEYS lpMouseKeys = (LPMOUSEKEYS)pvParam;
1331         WARN("SPI_GETMOUSEKEYS not fully implemented\n");
1332         if (lpMouseKeys->cbSize == sizeof(MOUSEKEYS))
1333         {
1334             /* Indicate that no MouseKeys feature available */
1335             lpMouseKeys->dwFlags = 0;
1336             lpMouseKeys->iMaxSpeed = 360;
1337             lpMouseKeys->iTimeToMaxSpeed = 1000;
1338             lpMouseKeys->iCtrlSpeed = 0;
1339             lpMouseKeys->dwReserved1 = 0;
1340             lpMouseKeys->dwReserved2 = 0;
1341         }
1342         else
1343         {
1344             ret = FALSE;
1345         }
1346         break;
1347     }
1348     WINE_SPI_FIXME(SPI_SETMOUSEKEYS);           /*     55 */
1349
1350     case SPI_GETSHOWSOUNDS:                     /*     56 */
1351         spi_idx = SPI_SETSHOWSOUNDS_IDX;
1352
1353         if (!spi_loaded[spi_idx])
1354         {
1355             char buf[10];
1356             
1357             if (SYSPARAMS_Load( SPI_SETSHOWSOUNDS_REGKEY,
1358                                 SPI_SETSHOWSOUNDS_VALNAME, buf ))
1359             {
1360                 SYSMETRICS_Set( SM_SHOWSOUNDS, atoi( buf ) );
1361             }
1362             spi_loaded[spi_idx] = TRUE;
1363         }
1364         
1365
1366         *(INT *)pvParam = GetSystemMetrics( SM_SHOWSOUNDS );
1367         break;
1368
1369     case SPI_SETSHOWSOUNDS:                     /*     57 */
1370     {
1371         char buf[10];
1372         spi_idx = SPI_SETSHOWSOUNDS_IDX;
1373
1374         sprintf(buf, "%u", uiParam);
1375         if (SYSPARAMS_Save( SPI_SETSHOWSOUNDS_REGKEY,
1376                             SPI_SETSHOWSOUNDS_VALNAME,
1377                             buf, fWinIni ))
1378         {
1379             SYSMETRICS_Set( SM_SHOWSOUNDS, uiParam );
1380             spi_loaded[spi_idx] = TRUE;
1381         }
1382         else
1383             ret = FALSE;
1384         break;
1385     }
1386
1387     case SPI_GETSTICKYKEYS:                     /*     58 */
1388     {
1389         LPSTICKYKEYS lpStickyKeys = (LPSTICKYKEYS)pvParam;
1390         WARN("SPI_GETSTICKYKEYS not fully implemented\n");
1391         if (lpStickyKeys->cbSize == sizeof(STICKYKEYS))
1392         {
1393             /* Indicate that no StickyKeys feature available */
1394             lpStickyKeys->dwFlags = 0;
1395         }
1396         else
1397         {
1398             ret = FALSE;
1399         }
1400         break;
1401     }
1402     WINE_SPI_FIXME(SPI_SETSTICKYKEYS);          /*     59 */
1403
1404     case SPI_GETACCESSTIMEOUT:                  /*     60 */
1405     {
1406         LPACCESSTIMEOUT lpAccessTimeout = (LPACCESSTIMEOUT)pvParam;
1407         WARN("SPI_GETACCESSTIMEOUT not fully implemented\n");
1408         if (lpAccessTimeout->cbSize == sizeof(ACCESSTIMEOUT))
1409         {
1410             /* Indicate that no accessibility features timeout is available */
1411             lpAccessTimeout->dwFlags = 0;
1412             lpAccessTimeout->iTimeOutMSec = 0;
1413         }
1414         else
1415         {
1416             ret = FALSE;
1417         }
1418         break;
1419     }
1420     WINE_SPI_FIXME(SPI_SETACCESSTIMEOUT);       /*     61 */
1421
1422     case SPI_GETSERIALKEYS:                     /*     62  WINVER >= 0x400 */
1423     {
1424         LPSERIALKEYSA lpSerialKeysA = (LPSERIALKEYSA)pvParam;
1425         WARN("SPI_GETSERIALKEYS not fully implemented\n");
1426         if (lpSerialKeysA->cbSize == sizeof(SERIALKEYSA))
1427         {
1428             /* Indicate that no SerialKeys feature available */
1429             lpSerialKeysA->dwFlags = 0;
1430             lpSerialKeysA->lpszActivePort = NULL;
1431             lpSerialKeysA->lpszPort = NULL;
1432             lpSerialKeysA->iBaudRate = 0;
1433             lpSerialKeysA->iPortState = 0;
1434         }
1435         else
1436         {
1437             ret = FALSE;
1438         }
1439         break;
1440     }
1441     WINE_SPI_FIXME(SPI_SETSERIALKEYS);          /*     63  WINVER >= 0x400 */
1442
1443     case SPI_GETSOUNDSENTRY:                    /*     64 */
1444     {
1445         LPSOUNDSENTRYA lpSoundSentryA = (LPSOUNDSENTRYA)pvParam;
1446         WARN("SPI_GETSOUNDSENTRY not fully implemented\n");
1447         if (lpSoundSentryA->cbSize == sizeof(SOUNDSENTRYA))
1448         {
1449             /* Indicate that no SoundSentry feature available */
1450             lpSoundSentryA->dwFlags = 0;
1451             lpSoundSentryA->iFSTextEffect = 0;
1452             lpSoundSentryA->iFSTextEffectMSec = 0;
1453             lpSoundSentryA->iFSTextEffectColorBits = 0;
1454             lpSoundSentryA->iFSGrafEffect = 0;
1455             lpSoundSentryA->iFSGrafEffectMSec = 0;
1456             lpSoundSentryA->iFSGrafEffectColor = 0;
1457             lpSoundSentryA->iWindowsEffect = 0;
1458             lpSoundSentryA->iWindowsEffectMSec = 0;
1459             lpSoundSentryA->lpszWindowsEffectDLL = 0;
1460             lpSoundSentryA->iWindowsEffectOrdinal = 0;
1461         }
1462         else
1463         {
1464             ret = FALSE;
1465         }
1466         break;
1467     }
1468     WINE_SPI_FIXME(SPI_SETSOUNDSENTRY);         /*     65 */
1469     
1470     case SPI_GETHIGHCONTRAST:                   /*     66  WINVER >= 0x400 */
1471     {
1472         LPHIGHCONTRASTA lpHighContrastA = (LPHIGHCONTRASTA)pvParam;
1473         WARN("SPI_GETHIGHCONTRAST not fully implemented\n");
1474         if (lpHighContrastA->cbSize == sizeof(HIGHCONTRASTA))
1475         {
1476             /* Indicate that no high contrast feature available */
1477             lpHighContrastA->dwFlags = 0;
1478             lpHighContrastA->lpszDefaultScheme = NULL;
1479         }
1480         else
1481         {
1482             ret = FALSE;
1483         }
1484         break;
1485     }
1486     WINE_SPI_FIXME(SPI_SETHIGHCONTRAST);        /*     67  WINVER >= 0x400 */
1487
1488     case SPI_GETKEYBOARDPREF:                   /*     68  WINVER >= 0x400 */
1489         spi_idx = SPI_SETKEYBOARDPREF_IDX;
1490         if (!spi_loaded[spi_idx])
1491         {
1492             char buf[5];
1493
1494             if (SYSPARAMS_Load( SPI_SETKEYBOARDPREF_REGKEY,
1495                                 SPI_SETKEYBOARDPREF_VALNAME, buf ))
1496                 keyboard_pref  = atoi(buf);
1497             spi_loaded[spi_idx] = TRUE;
1498         }
1499         
1500         *(BOOL *)pvParam = keyboard_pref;
1501         break;
1502
1503     case SPI_SETKEYBOARDPREF:                   /*     69  WINVER >= 0x400 */
1504     {
1505         char buf[5];
1506
1507         spi_idx = SPI_SETKEYBOARDPREF_IDX;
1508         sprintf(buf, "%u", uiParam);
1509         if (SYSPARAMS_Save( SPI_SETKEYBOARDPREF_REGKEY,
1510                             SPI_SETKEYBOARDPREF_VALNAME,
1511                             buf, fWinIni ))
1512         {
1513             keyboard_pref = uiParam;
1514             spi_loaded[spi_idx] = TRUE;
1515         }
1516         else
1517             ret = FALSE;
1518         break;
1519     }
1520
1521     case SPI_GETSCREENREADER:                   /*     70  WINVER >= 0x400 */
1522         spi_idx = SPI_SETSCREENREADER_IDX;
1523         if (!spi_loaded[spi_idx])
1524         {
1525             char buf[5];
1526
1527             if (SYSPARAMS_Load( SPI_SETSCREENREADER_REGKEY,
1528                                 SPI_SETSCREENREADER_VALNAME, buf ))
1529                 screen_reader  = atoi(buf);
1530             spi_loaded[spi_idx] = TRUE;
1531         }
1532         
1533         *(BOOL *)pvParam = screen_reader;
1534         break;
1535
1536     case SPI_SETSCREENREADER:                   /*     71  WINVER >= 0x400 */
1537     {
1538         char buf[5];
1539
1540         spi_idx = SPI_SETSCREENREADER_IDX;
1541         sprintf(buf, "%u", uiParam);
1542         if (SYSPARAMS_Save( SPI_SETSCREENREADER_REGKEY,
1543                             SPI_SETSCREENREADER_VALNAME,
1544                             buf, fWinIni ))
1545         {
1546             screen_reader = uiParam;
1547             spi_loaded[spi_idx] = TRUE;
1548         }
1549         else
1550             ret = FALSE;
1551         break;
1552     }
1553
1554     case SPI_GETANIMATION:                      /*     72  WINVER >= 0x400 */
1555     {
1556         LPANIMATIONINFO lpAnimInfo = (LPANIMATIONINFO)pvParam;
1557  
1558         /* Tell it "disabled" */
1559         if (lpAnimInfo->cbSize == sizeof(ANIMATIONINFO))
1560             lpAnimInfo->iMinAnimate = 0; /* Minimise and restore animation is disabled (nonzero == enabled) */
1561         else
1562             ret = FALSE;
1563         break;
1564     }
1565     WINE_SPI_WARN(SPI_SETANIMATION);            /*     73  WINVER >= 0x400 */
1566
1567     WINE_SPI_FIXME(SPI_GETFONTSMOOTHING);       /*     74  WINVER >= 0x400 */
1568     WINE_SPI_FIXME(SPI_SETFONTSMOOTHING);       /*     75  WINVER >= 0x400 */
1569
1570     WINE_SPI_FIXME(SPI_SETDRAGWIDTH);           /*     76  WINVER >= 0x400 */
1571     WINE_SPI_FIXME(SPI_SETDRAGHEIGHT);          /*     77  WINVER >= 0x400 */
1572
1573     WINE_SPI_FIXME(SPI_SETHANDHELD);            /*     78  WINVER >= 0x400 */
1574
1575     WINE_SPI_FIXME(SPI_GETLOWPOWERTIMEOUT);     /*     79  WINVER >= 0x400 */
1576     WINE_SPI_FIXME(SPI_GETPOWEROFFTIMEOUT);     /*     80  WINVER >= 0x400 */
1577     WINE_SPI_FIXME(SPI_SETLOWPOWERTIMEOUT);     /*     81  WINVER >= 0x400 */
1578     WINE_SPI_FIXME(SPI_SETPOWEROFFTIMEOUT);     /*     82  WINVER >= 0x400 */
1579     WINE_SPI_FIXME(SPI_GETLOWPOWERACTIVE);      /*     83  WINVER >= 0x400 */
1580     WINE_SPI_FIXME(SPI_GETPOWEROFFACTIVE);      /*     84  WINVER >= 0x400 */
1581     WINE_SPI_FIXME(SPI_SETLOWPOWERACTIVE);      /*     85  WINVER >= 0x400 */
1582     WINE_SPI_FIXME(SPI_SETPOWEROFFACTIVE);      /*     86  WINVER >= 0x400 */
1583     
1584     WINE_SPI_FIXME(SPI_SETCURSORS);             /*     87  WINVER >= 0x400 */
1585     WINE_SPI_FIXME(SPI_SETICONS);               /*     88  WINVER >= 0x400 */
1586
1587     WINE_SPI_FIXME(SPI_GETDEFAULTINPUTLANG);    /*     89  WINVER >= 0x400 */
1588     WINE_SPI_FIXME(SPI_SETDEFAULTINPUTLANG);    /*     90  WINVER >= 0x400 */
1589
1590     WINE_SPI_FIXME(SPI_SETLANGTOGGLE);          /*     91  WINVER >= 0x400 */
1591
1592     case SPI_GETWINDOWSEXTENSION:               /*     92  WINVER >= 0x400 */
1593         WARN("pretend no support for Win9x Plus! for now.\n");
1594         ret = FALSE; /* yes, this is the result value */
1595         break;
1596
1597     WINE_SPI_FIXME(SPI_SETMOUSETRAILS);         /*     93  WINVER >= 0x400 */
1598     WINE_SPI_FIXME(SPI_GETMOUSETRAILS);         /*     94  WINVER >= 0x400 */
1599         
1600     case SPI_SETSCREENSAVERRUNNING:             /*     97  WINVER >= 0x400 */
1601         {
1602         /* SPI_SCREENSAVERRUNNING is an alias for SPI_SETSCREENSAVERRUNNING */
1603         char buf[5];
1604
1605         spi_idx = SPI_SETSCREENSAVERRUNNING_IDX;
1606         sprintf(buf, "%u", uiParam);
1607
1608         /* save only temporarily */
1609         if (SYSPARAMS_Save( SPI_SETSCREENSAVERRUNNING_REGKEY,
1610                             SPI_SETSCREENSAVERRUNNING_VALNAME,
1611                             buf, 0 ))
1612         {
1613             screensaver_running = uiParam;
1614             spi_loaded[spi_idx] = TRUE;
1615         }
1616         else
1617             ret = FALSE;
1618         break;
1619     }
1620
1621     case SPI_GETMOUSEHOVERWIDTH:                /*     98  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1622         *(UINT *)pvParam = 4;
1623         break;
1624     WINE_SPI_FIXME(SPI_SETMOUSEHOVERWIDTH);     /*     99  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1625
1626     case SPI_GETMOUSEHOVERHEIGHT:               /*    100  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1627         *(UINT *)pvParam = 4;
1628         break;
1629     WINE_SPI_FIXME(SPI_SETMOUSEHOVERHEIGHT);    /*    101  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1630
1631     case SPI_GETMOUSEHOVERTIME:                 /*    102  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1632         *(UINT *)pvParam = 400; /* default for menu dropdowns */
1633         break;
1634     WINE_SPI_FIXME(SPI_SETMOUSEHOVERTIME);      /*    103  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1635               
1636     case SPI_GETWHEELSCROLLLINES:               /*    104  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1637         *(UINT *)pvParam = 3; /* default for num scroll lines */  
1638         break;
1639
1640     WINE_SPI_FIXME(SPI_SETWHEELSCROLLLINES);    /*    105  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1641
1642     case SPI_GETMENUSHOWDELAY:                  /*    106  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1643         *(UINT *)pvParam = 400; /* Tested against Windows NT 4.0 and Windows 2000 */
1644         break;
1645
1646     WINE_SPI_FIXME(SPI_GETSHOWIMEUI);           /*    110  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1647     WINE_SPI_FIXME(SPI_SETSHOWIMEUI);           /*    111  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1648
1649     case SPI_GETSCREENSAVERRUNNING:             /*    114  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1650         spi_idx = SPI_SETSCREENSAVERRUNNING_IDX;
1651         if (!spi_loaded[spi_idx])
1652         {
1653             char buf[5];
1654             
1655             if (SYSPARAMS_Load( SPI_SETSCREENSAVERRUNNING_REGKEY,
1656                                 SPI_SETSCREENSAVERRUNNING_VALNAME, buf ))
1657                 screensaver_running  = atoi( buf );
1658             spi_loaded[spi_idx] = TRUE;
1659         }
1660         
1661         *(BOOL *)pvParam = screensaver_running;
1662         break;
1663
1664     WINE_SPI_FIXME(SPI_GETDESKWALLPAPER);       /*    115  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1665     WINE_SPI_FIXME(SPI_GETACTIVEWINDOWTRACKING);/* 0x1000  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1666     WINE_SPI_FIXME(SPI_SETACTIVEWINDOWTRACKING);/* 0x1001  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1667     WINE_SPI_FIXME(SPI_GETMENUANIMATION);       /* 0x1002  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1668     WINE_SPI_FIXME(SPI_SETMENUANIMATION);       /* 0x1003  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1669     WINE_SPI_FIXME(SPI_GETCOMBOBOXANIMATION);   /* 0x1004  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1670     WINE_SPI_FIXME(SPI_SETCOMBOBOXANIMATION);   /* 0x1005  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1671     WINE_SPI_FIXME(SPI_GETLISTBOXSMOOTHSCROLLING);/* 0x1006  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1672     WINE_SPI_FIXME(SPI_SETLISTBOXSMOOTHSCROLLING);/* 0x1007  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1673     WINE_SPI_FIXME(SPI_GETGRADIENTCAPTIONS);    /* 0x1008  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1674     WINE_SPI_FIXME(SPI_SETGRADIENTCAPTIONS);    /* 0x1009  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1675     WINE_SPI_FIXME(SPI_GETMENUUNDERLINES);      /* 0x100A  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1676     WINE_SPI_FIXME(SPI_SETMENUUNDERLINES);      /* 0x100B  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1677     WINE_SPI_FIXME(SPI_GETACTIVEWNDTRKZORDER);  /* 0x100C  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1678     WINE_SPI_FIXME(SPI_SETACTIVEWNDTRKZORDER);  /* 0x100D  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1679     WINE_SPI_FIXME(SPI_GETHOTTRACKING);         /* 0x100E  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1680     WINE_SPI_FIXME(SPI_SETHOTTRACKING);         /* 0x100F  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1681     WINE_SPI_FIXME(SPI_GETFOREGROUNDLOCKTIMEOUT);/* 0x2000  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1682     WINE_SPI_FIXME(SPI_SETFOREGROUNDLOCKTIMEOUT);/* 0x2001  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1683     WINE_SPI_FIXME(SPI_GETACTIVEWNDTRKTIMEOUT); /* 0x2002  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1684     WINE_SPI_FIXME(SPI_SETACTIVEWNDTRKTIMEOUT); /* 0x2003  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1685     WINE_SPI_FIXME(SPI_GETFOREGROUNDFLASHCOUNT);/* 0x2004  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1686     WINE_SPI_FIXME(SPI_SETFOREGROUNDFLASHCOUNT);/* 0x2005  _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */
1687
1688     default:
1689         FIXME( "Unknown action: %u\n", uiAction );
1690         SetLastError( ERROR_INVALID_SPI_VALUE );
1691         ret = FALSE;
1692         break;
1693     }
1694
1695     if (ret)
1696         SYSPARAMS_NotifyChange( uiAction, fWinIni );
1697     return ret;
1698     
1699 #undef WINE_SPI_FIXME
1700 #undef WINE_SPI_WARN
1701 }
1702
1703
1704 /***********************************************************************
1705  *              SystemParametersInfo (USER.483)
1706  */
1707 BOOL16 WINAPI SystemParametersInfo16( UINT16 uAction, UINT16 uParam,
1708                                       LPVOID lpvParam, UINT16 fuWinIni )
1709 {
1710     BOOL16 ret;
1711
1712     TRACE("(%u, %u, %p, %u)\n", uAction, uParam, lpvParam, fuWinIni);
1713     
1714     switch (uAction)
1715     {
1716     case SPI_GETBEEP:                           /*      1 */
1717     case SPI_GETSCREENSAVEACTIVE:               /*     16 */
1718     case SPI_GETICONTITLEWRAP:                  /*     25 */
1719     case SPI_GETMENUDROPALIGNMENT:              /*     27 */
1720     case SPI_GETFASTTASKSWITCH:                 /*     35 */
1721     case SPI_GETDRAGFULLWINDOWS:                /*     38  WINVER >= 0x0400 */
1722     {
1723         BOOL tmp;
1724         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1725         if (ret && lpvParam)
1726             *(BOOL16 *)lpvParam = tmp;
1727         break;
1728     }
1729
1730     case SPI_GETBORDER:                         /*      5 */
1731     case SPI_ICONHORIZONTALSPACING:             /*     13 */
1732     case SPI_GETSCREENSAVETIMEOUT:              /*     14 */
1733     case SPI_GETGRIDGRANULARITY:                /*     18 */
1734     case SPI_GETKEYBOARDDELAY:                  /*     22 */
1735     case SPI_ICONVERTICALSPACING:               /*     24 */
1736     {
1737         INT tmp;
1738         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1739         if (ret && lpvParam)
1740             *(INT16 *)lpvParam = tmp;
1741         break;
1742     }
1743
1744     case SPI_GETKEYBOARDSPEED:                  /*     10 */
1745     {
1746         DWORD tmp;
1747         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1748         if (ret && lpvParam)
1749             *(WORD *)lpvParam = tmp;
1750         break;
1751     }
1752
1753     case SPI_GETICONTITLELOGFONT:               /*     31 */
1754     {
1755         LOGFONTA tmp;
1756         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1757         if (ret && lpvParam)
1758             SYSPARAMS_LogFont32ATo16( &tmp, (LPLOGFONT16)lpvParam );
1759         break;
1760     }
1761
1762     case SPI_GETNONCLIENTMETRICS:               /*     41  WINVER >= 0x400 */
1763     {
1764         NONCLIENTMETRICSA tmp;
1765         LPNONCLIENTMETRICS16 lpnm16 = (LPNONCLIENTMETRICS16)lpvParam;
1766         if (lpnm16 && lpnm16->cbSize == sizeof(NONCLIENTMETRICS16))
1767         {
1768             tmp.cbSize = sizeof(NONCLIENTMETRICSA);
1769             ret = SystemParametersInfoA( uAction, uParam, &tmp, fuWinIni );
1770             if (ret)
1771                 SYSPARAMS_NonClientMetrics32ATo16( &tmp, lpnm16 );
1772         }
1773         else /* winfile 95 sets cbSize to 340 */
1774             ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
1775         break;
1776     }
1777     
1778     case SPI_GETWORKAREA:                       /*     48  WINVER >= 0x400 */
1779     {
1780         RECT tmp;
1781         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1782         if (ret && lpvParam)
1783             CONV_RECT32TO16( &tmp, (RECT16 *)lpvParam );
1784         break;
1785     }
1786         
1787     case SPI_GETMOUSEHOVERWIDTH:                /*     98  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1788     case SPI_GETMOUSEHOVERHEIGHT:               /*    100  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1789     case SPI_GETMOUSEHOVERTIME:                 /*    102  _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */
1790     {
1791         UINT tmp;
1792         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
1793         if (ret && lpvParam)
1794             *(UINT16 *)lpvParam = tmp;
1795         break;
1796     }
1797
1798     default:
1799         ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
1800     }
1801
1802     return ret;
1803 }
1804
1805 /***********************************************************************
1806  *              SystemParametersInfoW (USER32.@)
1807  */
1808 BOOL WINAPI SystemParametersInfoW( UINT uiAction, UINT uiParam,
1809                                    PVOID pvParam, UINT fuWinIni )
1810 {
1811     BOOL ret;
1812
1813     TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fuWinIni);
1814     
1815     switch (uiAction)
1816     {
1817     case SPI_SETDESKWALLPAPER:                  /*     20 */
1818     case SPI_SETDESKPATTERN:                    /*     21 */
1819     {
1820         char buffer[256];
1821         if (pvParam)
1822             if (!WideCharToMultiByte( CP_ACP, 0, (LPWSTR)pvParam, -1,
1823                                       buffer, sizeof(buffer), NULL, NULL ))
1824                 buffer[sizeof(buffer)-1] = 0;
1825         ret = SystemParametersInfoA( uiAction, uiParam, pvParam ? buffer : NULL, fuWinIni );
1826         break;
1827     }
1828
1829     case SPI_GETICONTITLELOGFONT:               /*     31 */
1830     {
1831         LOGFONTA tmp;
1832         ret = SystemParametersInfoA( uiAction, uiParam, pvParam ? &tmp : NULL, fuWinIni );
1833         if (ret && pvParam)
1834             SYSPARAMS_LogFont32ATo32W( &tmp, (LPLOGFONTW)pvParam );
1835         break;
1836     }
1837
1838     case SPI_GETNONCLIENTMETRICS:               /*     41  WINVER >= 0x400 */
1839     {
1840         NONCLIENTMETRICSA tmp;
1841         LPNONCLIENTMETRICSW lpnmW = (LPNONCLIENTMETRICSW)pvParam;
1842         if (lpnmW && lpnmW->cbSize == sizeof(NONCLIENTMETRICSW))
1843         {
1844             tmp.cbSize = sizeof(NONCLIENTMETRICSA);
1845             ret = SystemParametersInfoA( uiAction, uiParam, &tmp, fuWinIni );
1846             if (ret)
1847                 SYSPARAMS_NonClientMetrics32ATo32W( &tmp, lpnmW );
1848         }
1849         else
1850             ret = FALSE;
1851         break;
1852     }
1853
1854     case SPI_GETICONMETRICS:                    /*     45  WINVER >= 0x400 */
1855     {
1856         ICONMETRICSA tmp;
1857         LPICONMETRICSW lpimW = (LPICONMETRICSW)pvParam;
1858         if (lpimW && lpimW->cbSize == sizeof(ICONMETRICSW))
1859         {
1860             tmp.cbSize = sizeof(ICONMETRICSA);
1861             ret = SystemParametersInfoA( uiAction, uiParam, &tmp, fuWinIni );
1862             if (ret)
1863             {
1864                 lpimW->iHorzSpacing = tmp.iHorzSpacing;
1865                 lpimW->iVertSpacing = tmp.iVertSpacing;
1866                 lpimW->iTitleWrap   = tmp.iTitleWrap;
1867                 SYSPARAMS_LogFont32ATo32W( &tmp.lfFont, &lpimW->lfFont );
1868             }
1869         }
1870         else
1871             ret = FALSE;
1872         break;
1873     }
1874
1875     case SPI_GETHIGHCONTRAST:                   /*     66  WINVER >= 0x400 */
1876     {
1877         HIGHCONTRASTA tmp;
1878         LPHIGHCONTRASTW lphcW = (LPHIGHCONTRASTW)pvParam;
1879         if (lphcW && lphcW->cbSize == sizeof(HIGHCONTRASTW))
1880         {
1881             tmp.cbSize = sizeof(HIGHCONTRASTA);
1882             ret = SystemParametersInfoA( uiAction, uiParam, &tmp, fuWinIni );
1883             if (ret)
1884             {
1885                 lphcW->dwFlags = tmp.dwFlags;
1886                 lphcW->lpszDefaultScheme = NULL;  /* FIXME? */
1887             }
1888         }
1889         else
1890             ret = FALSE;
1891         break;
1892     }
1893     
1894     default:
1895         ret = SystemParametersInfoA( uiAction, uiParam, pvParam, fuWinIni );
1896         break;
1897     }
1898     return ret;
1899 }
1900
1901
1902 /**********************************************************************
1903  *              SetDoubleClickTime (USER32.@)
1904  */
1905 BOOL WINAPI SetDoubleClickTime( UINT interval )
1906 {
1907     return SystemParametersInfoA(SPI_SETDOUBLECLICKTIME, interval, 0, 0);
1908 }
1909
1910
1911 /**********************************************************************
1912  *              GetDoubleClickTime (USER32.@)
1913  */
1914 UINT WINAPI GetDoubleClickTime(void)
1915 {
1916     char buf[10];
1917
1918     if (!spi_loaded[SPI_SETDOUBLECLICKTIME_IDX])
1919     {
1920         if (SYSPARAMS_Load( SPI_SETDOUBLECLICKTIME_REGKEY,
1921                             SPI_SETDOUBLECLICKTIME_VALNAME,
1922                             buf ))
1923         {
1924             double_click_time = atoi( buf );
1925             if (!double_click_time) double_click_time = 500;
1926         }
1927         spi_loaded[SPI_SETDOUBLECLICKTIME_IDX] = TRUE;
1928     }
1929     return double_click_time;
1930 }