Release 980601
[wine] / misc / main.c
1 /*
2  * Main function.
3  *
4  * Copyright 1994 Alexandre Julliard
5  */
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <ctype.h>
11 /* #include <locale.h> */
12 #ifdef MALLOC_DEBUGGING
13 #include <malloc.h>
14 #endif
15 #include "ts_xlib.h"
16 #include "ts_xresource.h"
17 #include "ts_xutil.h"
18 #include <X11/Xlocale.h>
19 #include <X11/cursorfont.h>
20 #include "winsock.h"
21 #include "heap.h"
22 #include "message.h"
23 #include "msdos.h"
24 #include "windows.h"
25 #include "color.h"
26 #include "options.h"
27 #include "desktop.h"
28 #include "process.h"
29 #include "shell.h"
30 #include "winbase.h"
31 #include "debug.h"
32 #include "debugdefs.h"
33 #include "xmalloc.h"
34 #include "version.h"
35
36 const WINE_LANGUAGE_DEF Languages[] =
37 {
38     {"En",0x0409},      /* LANG_En */
39     {"Es",0x040A},      /* LANG_Es */
40     {"De",0x0407},      /* LANG_De */
41     {"No",0x0414},      /* LANG_No */
42     {"Fr",0x0400},      /* LANG_Fr */
43     {"Fi",0x040B},      /* LANG_Fi */
44     {"Da",0x0406},      /* LANG_Da */
45     {"Cz",0x0405},      /* LANG_Cz */
46     {"Eo",0x0425},      /* LANG_Eo */
47     {"It",0x0410},      /* LANG_It */
48     {"Ko",0x0412},      /* LANG_Ko */
49     {"Hu",0x0436},      /* LANG_Hu */
50     {"Pl",0x0415},      /* LANG_Pl */
51     {"Po",0x0416},      /* LANG_Po */
52     {"Sw",0x0417},      /* LANG_Sw */
53     {"Ca",0x0426},      /* LANG_Ca */
54     {NULL,0}
55 };
56
57 WORD WINE_LanguageId = 0;
58
59 #define WINE_CLASS    "Wine"    /* Class name for resources */
60
61 #define WINE_APP_DEFAULTS "/usr/lib/X11/app-defaults/Wine"
62
63 Display *display;
64 Screen *screen;
65 Window rootWindow;
66 int screenWidth = 0, screenHeight = 0;  /* Desktop window dimensions */
67 int screenDepth = 0;  /* Screen depth to use */
68
69 struct options Options =
70 {  /* default options */
71     NULL,           /* desktopGeometry */
72     NULL,           /* programName */
73     NULL,           /* argv0 */
74     NULL,           /* dllFlags */
75     FALSE,          /* usePrivateMap */
76     FALSE,          /* useFixedMap */
77     FALSE,          /* synchronous */
78     FALSE,          /* backing store */
79     SW_SHOWNORMAL,  /* cmdShow */
80     FALSE,
81     FALSE,          /* failReadOnly */
82     MODE_ENHANCED,  /* Enhanced mode */
83 #ifdef DEFAULT_LANG
84     DEFAULT_LANG,   /* Default language */
85 #else
86     LANG_En,
87 #endif
88     FALSE,          /* Managed windows */
89     FALSE           /* Perfect graphics */
90 };
91
92
93 static XrmOptionDescRec optionsTable[] =
94 {
95     { "-backingstore",  ".backingstore",    XrmoptionNoArg,  (caddr_t)"on" },
96     { "-desktop",       ".desktop",         XrmoptionSepArg, (caddr_t)NULL },
97     { "-depth",         ".depth",           XrmoptionSepArg, (caddr_t)NULL },
98     { "-display",       ".display",         XrmoptionSepArg, (caddr_t)NULL },
99     { "-iconic",        ".iconic",          XrmoptionNoArg,  (caddr_t)"on" },
100     { "-language",      ".language",        XrmoptionSepArg, (caddr_t)"En" },
101     { "-name",          ".name",            XrmoptionSepArg, (caddr_t)NULL },
102     { "-perfect",       ".perfect",         XrmoptionNoArg,  (caddr_t)"on" },
103     { "-privatemap",    ".privatemap",      XrmoptionNoArg,  (caddr_t)"on" },
104     { "-fixedmap",      ".fixedmap",        XrmoptionNoArg,  (caddr_t)"on" },
105     { "-synchronous",   ".synchronous",     XrmoptionNoArg,  (caddr_t)"on" },
106     { "-debug",         ".debug",           XrmoptionNoArg,  (caddr_t)"on" },
107     { "-debugmsg",      ".debugmsg",        XrmoptionSepArg, (caddr_t)NULL },
108     { "-dll",           ".dll",             XrmoptionSepArg, (caddr_t)NULL },
109     { "-failreadonly",  ".failreadonly",    XrmoptionNoArg,  (caddr_t)"on" },
110     { "-mode",          ".mode",            XrmoptionSepArg, (caddr_t)NULL },
111     { "-managed",       ".managed",         XrmoptionNoArg,  (caddr_t)"off"},
112     { "-winver",        ".winver",          XrmoptionSepArg, (caddr_t)NULL }
113 };
114
115 #define NB_OPTIONS  (sizeof(optionsTable) / sizeof(optionsTable[0]))
116
117 #define USAGE \
118   "%s\n" \
119   "Usage:  %s [options] \"program_name [arguments]\"\n" \
120   "\n" \
121   "Options:\n" \
122   "    -backingstore   Turn on backing store\n" \
123   "    -debug          Enter debugger before starting application\n" \
124   "    -debugmsg name  Turn debugging-messages on or off\n" \
125   "    -depth n        Change the depth to use for multiple-depth screens\n" \
126   "    -desktop geom   Use a desktop window of the given geometry\n" \
127   "    -display name   Use the specified display\n" \
128   "    -dll name       Enable or disable built-in DLLs\n" \
129   "    -failreadonly   Read only files may not be opened in write mode\n" \
130   "    -fixedmap       Use a \"standard\" color map\n" \
131   "    -help           Show this help message\n" \
132   "    -iconic         Start as an icon\n" \
133   "    -language xx    Set the language (one of En,Es,De,No,Fr,Fi,Da,Cz,Eo,It,Ko,\n                    Hu,Pl,Po,Sw,Ca)\n" \
134   "    -managed        Allow the window manager to manage created windows\n" \
135   "    -mode mode      Start Wine in a particular mode (standard or enhanced)\n" \
136   "    -name name      Set the application name\n" \
137   "    -perfect        Favor correctness over speed for graphical operations\n" \
138   "    -privatemap     Use a private color map\n" \
139   "    -synchronous    Turn on synchronous display mode\n" \
140   "    -version        Display the Wine version\n" \
141   "    -winver         Version to imitate (one of win31,win95,nt351,nt40)\n"
142
143
144
145 /***********************************************************************
146  *           MAIN_Usage
147  */
148 void MAIN_Usage( char *name )
149 {
150     MSG( USAGE, WINE_RELEASE_INFO, name );
151     exit(1);
152 }
153
154
155 /***********************************************************************
156  *           MAIN_GetProgramName
157  *
158  * Get the program name. The name is specified by (in order of precedence):
159  * - the option '-name'.
160  * - the environment variable 'WINE_NAME'.
161  * - the last component of argv[0].
162  */
163 static char *MAIN_GetProgramName( int argc, char *argv[] )
164 {
165     int i;
166     char *p;
167
168     for (i = 1; i < argc-1; i++)
169         if (!strcmp( argv[i], "-name" )) return argv[i+1];
170     if ((p = getenv( "WINE_NAME" )) != NULL) return p;
171     if ((p = strrchr( argv[0], '/' )) != NULL) return p+1;
172     return argv[0];
173 }
174
175
176 /***********************************************************************
177  *           MAIN_GetResource
178  *
179  * Fetch the value of resource 'name' using the correct instance name.
180  * 'name' must begin with '.' or '*'
181  */
182 static int MAIN_GetResource( XrmDatabase db, char *name, XrmValue *value )
183 {
184     char *buff_instance, *buff_class;
185     char *dummy;
186     int retval;
187
188     buff_instance = (char *)xmalloc(strlen(Options.programName)+strlen(name)+1);
189     buff_class    = (char *)xmalloc( strlen(WINE_CLASS) + strlen(name) + 1 );
190
191     strcpy( buff_instance, Options.programName );
192     strcat( buff_instance, name );
193     strcpy( buff_class, WINE_CLASS );
194     strcat( buff_class, name );
195     retval = TSXrmGetResource( db, buff_instance, buff_class, &dummy, value );
196     free( buff_instance );
197     free( buff_class );
198     return retval;
199 }
200
201
202 /***********************************************************************
203  *          MAIN_ParseDebugOptions
204  *
205  *  Turns specific debug messages on or off, according to "options".
206  *  
207  *  RETURNS
208  *    TRUE if parsing was successful
209  */
210 static BOOL32 MAIN_ParseDebugOptions(char *options)
211 {
212   int l, cls;
213   if (strlen(options)<3)
214     return FALSE;
215   do
216   {
217     if ((*options!='+')&&(*options!='-')){
218       int j;
219
220       for(j=0; j<DEBUG_CLASS_COUNT; j++)
221         if(!lstrncmpi32A(options, debug_cl_name[j], strlen(debug_cl_name[j])))
222           break;
223       if(j==DEBUG_CLASS_COUNT)
224         return FALSE;
225       options += strlen(debug_cl_name[j]);
226       if ((*options!='+')&&(*options!='-'))
227         return FALSE;
228       cls = j;
229     }
230     else
231       cls = -1; /* all classes */
232
233     if (strchr(options,','))
234       l=strchr(options,',')-options;
235     else
236       l=strlen(options);
237
238     if (!lstrncmpi32A(options+1,"all",l-1))
239       {
240         int i, j;
241         for (i=0; i<DEBUG_CHANNEL_COUNT; i++)
242           for(j=0; j<DEBUG_CLASS_COUNT; j++)
243             if(cls == -1 || cls == j)
244               debug_msg_enabled[i][j]=(*options=='+');
245       }
246     else
247       {
248         int i, j;
249         for (i=0; i<DEBUG_CHANNEL_COUNT; i++)
250           if (debug_ch_name && (!lstrncmpi32A(options+1,debug_ch_name[i],l-1))){
251             for(j=0; j<DEBUG_CLASS_COUNT; j++)
252               if(cls == -1 || cls == j)
253                 debug_msg_enabled[i][j]=(*options=='+');
254             break;
255           }
256         if (i==DEBUG_CHANNEL_COUNT)
257           return FALSE;
258       }
259     options+=l;
260   }
261   while((*options==',')&&(*(++options)));
262   if (*options)
263     return FALSE;
264   else
265     return TRUE;
266 }
267
268 /***********************************************************************
269  *           MAIN_ParseLanguageOption
270  *
271  * Parse -language option.
272  */
273 static void MAIN_ParseLanguageOption( char *arg )
274 {
275     const WINE_LANGUAGE_DEF *p = Languages;
276
277     Options.language = LANG_En;  /* First language */
278     for (;p->name;p++)
279     {
280         if (!lstrcmpi32A( p->name, arg ))
281         {
282             WINE_LanguageId = p->langid;
283             return;
284         }
285         Options.language++;
286     }
287     MSG( "Invalid language specified '%s'. Supported languages are: ", arg );
288     for (p = Languages; p->name; p++) MSG( "%s ", p->name );
289     MSG( "\n" );
290     exit(1);
291 }
292
293
294 /***********************************************************************
295  *           MAIN_ParseModeOption
296  *
297  * Parse -mode option.
298  */
299 static void MAIN_ParseModeOption( char *arg )
300 {
301     if (!lstrcmpi32A("enhanced", arg)) Options.mode = MODE_ENHANCED;
302     else if (!lstrcmpi32A("standard", arg)) Options.mode = MODE_STANDARD;
303     else
304     {
305         MSG( "Invalid mode '%s' specified.\n", arg);
306         MSG( "Valid modes are: 'standard', 'enhanced' (default).\n");
307         exit(1);
308     }
309 }
310
311 /***********************************************************************
312  *           MAIN_ParseOptions
313  *
314  * Parse command line options and open display.
315  */
316 static void MAIN_ParseOptions( int *argc, char *argv[] )
317 {
318     char *display_name = NULL;
319     XrmValue value;
320     XrmDatabase db = TSXrmGetFileDatabase(WINE_APP_DEFAULTS);
321     int i;
322     char *xrm_string;
323
324     Options.programName = MAIN_GetProgramName( *argc, argv );
325     Options.argv0 = argv[0];
326
327       /* Get display name from command line */
328     for (i = 1; i < *argc; i++)
329     {
330         if (!strcmp( argv[i], "-display" )) display_name = argv[i+1];
331         if (!strcmp( argv[i], "-v" ) || !strcmp( argv[i], "-version" ))
332         {
333             MSG( "%s\n", WINE_RELEASE_INFO );
334             exit(0);
335         }
336         if (!strcmp( argv[i], "-h" ) || !strcmp( argv[i], "-help" ))
337         {
338             MAIN_Usage(argv[0]);
339             exit(0);
340         }
341     }
342
343       /* Open display */
344
345     if (display_name == NULL &&
346         MAIN_GetResource( db, ".display", &value )) display_name = value.addr;
347
348     if (!(display = TSXOpenDisplay( display_name )))
349     {
350         MSG( "%s: Can't open display: %s\n",
351                  argv[0], display_name ? display_name : "(none specified)" );
352         exit(1);
353     }
354
355       /* Merge file and screen databases */
356     if ((xrm_string = TSXResourceManagerString( display )) != NULL)
357     {
358         XrmDatabase display_db = TSXrmGetStringDatabase( xrm_string );
359         TSXrmMergeDatabases( display_db, &db );
360     }
361
362       /* Parse command line */
363     TSXrmParseCommand( &db, optionsTable, NB_OPTIONS,
364                      Options.programName, argc, argv );
365
366       /* Get all options */
367     if (MAIN_GetResource( db, ".iconic", &value ))
368         Options.cmdShow = SW_SHOWMINIMIZED;
369     if (MAIN_GetResource( db, ".privatemap", &value ))
370         Options.usePrivateMap = TRUE;
371     if (MAIN_GetResource( db, ".fixedmap", &value ))
372         Options.useFixedMap = TRUE;
373     if (MAIN_GetResource( db, ".synchronous", &value ))
374         Options.synchronous = TRUE;
375     if (MAIN_GetResource( db, ".backingstore", &value ))
376         Options.backingstore = TRUE;    
377     if (MAIN_GetResource( db, ".debug", &value ))
378         Options.debug = TRUE;
379     if (MAIN_GetResource( db, ".failreadonly", &value ))
380         Options.failReadOnly = TRUE;
381     if (MAIN_GetResource( db, ".perfect", &value ))
382         Options.perfectGraphics = TRUE;
383     if (MAIN_GetResource( db, ".depth", &value))
384         screenDepth = atoi( value.addr );
385     if (MAIN_GetResource( db, ".desktop", &value))
386         Options.desktopGeometry = value.addr;
387     if (MAIN_GetResource( db, ".language", &value))
388         MAIN_ParseLanguageOption( (char *)value.addr );
389     if (MAIN_GetResource( db, ".managed", &value))
390         Options.managed = TRUE;
391     if (MAIN_GetResource( db, ".mode", &value))
392         MAIN_ParseModeOption( (char *)value.addr );
393     if (MAIN_GetResource( db, ".debugoptions", &value))
394         MAIN_ParseDebugOptions((char*)value.addr);
395     if (MAIN_GetResource( db, ".debugmsg", &value))
396       {
397 #ifndef DEBUG_RUNTIME
398         MSG("%s: Option \"-debugmsg\" not implemented.\n" \
399           "    Recompile with DEBUG_RUNTIME in include/debugtools.h defined.\n",
400           argv[0]);
401         exit(1);
402 #else
403         if (MAIN_ParseDebugOptions((char*)value.addr)==FALSE)
404           {
405             int i;
406             MSG("%s: Syntax: -debugmsg [class]+xxx,...  or "
407                     "-debugmsg [class]-xxx,...\n",argv[0]);
408             MSG("Example: -debugmsg +all,warn-heap"
409                     "turn on all messages except warning heap messages\n");
410
411             MSG("Available message classes:\n");
412             for(i=0;i<DEBUG_CLASS_COUNT;i++)
413               MSG( "%-9s", debug_cl_name[i]);
414             MSG("\n\n");
415
416             MSG("Available message types:\n");
417             MSG("%-9s ","all");
418             for(i=0;i<DEBUG_CHANNEL_COUNT;i++)
419               if(debug_ch_name[i])
420                 MSG("%-9s%c",debug_ch_name[i],
421                         (((i+2)%8==0)?'\n':' '));
422             MSG("\n\n");
423             exit(1);
424           }
425 #endif
426       }
427
428       if (MAIN_GetResource( db, ".dll", &value))
429       {
430           /* Hack: store option value in Options to be retrieved */
431           /* later on inside the emulator code. */
432           if (!__winelib) Options.dllFlags = xstrdup((char *)value.addr);
433           else
434           {
435               MSG("-dll not supported in Winelib\n" );
436               exit(1);
437           }
438       }
439
440       if (MAIN_GetResource( db, ".winver", &value))
441           VERSION_ParseVersion( (char*)value.addr );
442 }
443
444
445 /***********************************************************************
446  *           MAIN_CreateDesktop
447  */
448 static void MAIN_CreateDesktop( int argc, char *argv[] )
449 {
450     int x, y, flags;
451     unsigned int width = 640, height = 480;  /* Default size = 640x480 */
452     char *name = "Wine desktop";
453     XSizeHints *size_hints;
454     XWMHints   *wm_hints;
455     XClassHint *class_hints;
456     XSetWindowAttributes win_attr;
457     XTextProperty window_name;
458     Atom XA_WM_DELETE_WINDOW;
459
460     flags = TSXParseGeometry( Options.desktopGeometry, &x, &y, &width, &height );
461     screenWidth  = width;
462     screenHeight = height;
463
464       /* Create window */
465
466     win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
467                          PointerMotionMask | ButtonPressMask |
468                          ButtonReleaseMask | EnterWindowMask;
469     win_attr.cursor = TSXCreateFontCursor( display, XC_top_left_arrow );
470
471     rootWindow = TSXCreateWindow( display, DefaultRootWindow(display),
472                                 x, y, width, height, 0,
473                                 CopyFromParent, InputOutput, CopyFromParent,
474                                 CWEventMask | CWCursor, &win_attr );
475
476       /* Set window manager properties */
477
478     size_hints  = TSXAllocSizeHints();
479     wm_hints    = TSXAllocWMHints();
480     class_hints = TSXAllocClassHint();
481     if (!size_hints || !wm_hints || !class_hints)
482     {
483         MSG("Not enough memory for window manager hints.\n" );
484         exit(1);
485     }
486     size_hints->min_width = size_hints->max_width = width;
487     size_hints->min_height = size_hints->max_height = height;
488     size_hints->flags = PMinSize | PMaxSize;
489     if (flags & (XValue | YValue)) size_hints->flags |= USPosition;
490     if (flags & (WidthValue | HeightValue)) size_hints->flags |= USSize;
491     else size_hints->flags |= PSize;
492
493     wm_hints->flags = InputHint | StateHint;
494     wm_hints->input = True;
495     wm_hints->initial_state = NormalState;
496     class_hints->res_name = argv[0];
497     class_hints->res_class = "Wine";
498
499     TSXStringListToTextProperty( &name, 1, &window_name );
500     TSXSetWMProperties( display, rootWindow, &window_name, &window_name,
501                       argv, argc, size_hints, wm_hints, class_hints );
502     XA_WM_DELETE_WINDOW = TSXInternAtom( display, "WM_DELETE_WINDOW", False );
503     TSXSetWMProtocols( display, rootWindow, &XA_WM_DELETE_WINDOW, 1 );
504     TSXFree( size_hints );
505     TSXFree( wm_hints );
506     TSXFree( class_hints );
507
508       /* Map window */
509
510     TSXMapWindow( display, rootWindow );
511 }
512
513
514 XKeyboardState keyboard_state;
515
516 /***********************************************************************
517  *           MAIN_SaveSetup
518  */
519 static void MAIN_SaveSetup(void)
520 {
521     TSXGetKeyboardControl(display, &keyboard_state);
522 }
523
524 /***********************************************************************
525  *           MAIN_RestoreSetup
526  */
527 static void MAIN_RestoreSetup(void)
528 {
529     XKeyboardControl keyboard_value;
530
531     keyboard_value.key_click_percent    = keyboard_state.key_click_percent;
532     keyboard_value.bell_percent         = keyboard_state.bell_percent;
533     keyboard_value.bell_pitch           = keyboard_state.bell_pitch;
534     keyboard_value.bell_duration        = keyboard_state.bell_duration;
535     keyboard_value.auto_repeat_mode     = keyboard_state.global_auto_repeat;
536
537     XChangeKeyboardControl(display, KBKeyClickPercent | KBBellPercent | 
538         KBBellPitch | KBBellDuration | KBAutoRepeatMode, &keyboard_value);
539 }
540
541
542 /***********************************************************************
543  *           called_at_exit
544  */
545 static void called_at_exit(void)
546 {
547     MAIN_RestoreSetup();
548     COLOR_Cleanup();
549     WINSOCK_Shutdown();
550     /* FIXME: should check for other processes or threads */
551     DeleteCriticalSection( HEAP_SystemLock );
552 }
553
554 /***********************************************************************
555  *           MAIN_WineInit
556  *
557  * Wine initialisation and command-line parsing
558  */
559 BOOL32 MAIN_WineInit( int *argc, char *argv[] )
560 {    
561     int depth_count, i;
562     int *depth_list;
563     struct timeval tv;
564
565 #ifdef MALLOC_DEBUGGING
566     char *trace;
567
568     mcheck(NULL);
569     if (!(trace = getenv("MALLOC_TRACE")))
570     {       
571         MSG( "MALLOC_TRACE not set. No trace generated\n" );
572     }
573     else
574     {
575         MSG( "malloc trace goes to %s\n", trace );
576         mtrace();
577     }
578 #endif
579
580     setbuf(stdout,NULL);
581     setbuf(stderr,NULL);
582
583     setlocale(LC_CTYPE,"");
584     gettimeofday( &tv, NULL);
585     MSG_WineStartTicks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
586
587     /* We need this before calling any Xlib function */
588     InitializeCriticalSection( &X11DRV_CritSection );
589
590     TSXrmInitialize();
591
592     putenv("XKB_DISABLE="); /* Disable XKB extension if present. */
593
594     MAIN_ParseOptions( argc, argv );
595
596     if (Options.desktopGeometry && Options.managed)
597     {
598 #if 0
599         MSG( "%s: -managed and -desktop options cannot be used together\n",
600                  Options.programName );
601         exit(1);
602 #else
603         Options.managed = FALSE;
604 #endif
605     }
606
607     screen       = DefaultScreenOfDisplay( display );
608     screenWidth  = WidthOfScreen( screen );
609     screenHeight = HeightOfScreen( screen );
610     if (screenDepth)  /* -depth option specified */
611     {
612         depth_list = TSXListDepths(display,DefaultScreen(display),&depth_count);
613         for (i = 0; i < depth_count; i++)
614             if (depth_list[i] == screenDepth) break;
615         TSXFree( depth_list );
616         if (i >= depth_count)
617         {
618             MSG( "%s: Depth %d not supported on this screen.\n",
619                               Options.programName, screenDepth );
620             exit(1);
621         }
622     }
623     else screenDepth  = DefaultDepthOfScreen( screen );
624     if (Options.synchronous) TSXSynchronize( display, True );
625     if (Options.desktopGeometry) MAIN_CreateDesktop( *argc, argv );
626     else rootWindow = DefaultRootWindow( display );
627
628     MAIN_SaveSetup();
629     atexit(called_at_exit);
630     return TRUE;
631 }
632
633
634 /***********************************************************************
635  *           MessageBeep16   (USER.104)
636  */
637 void WINAPI MessageBeep16( UINT16 i )
638 {
639     MessageBeep32( i );
640 }
641
642
643 /***********************************************************************
644  *           MessageBeep32   (USER32.390)
645  */
646 BOOL32 WINAPI MessageBeep32( UINT32 i )
647 {
648     TSXBell( display, 0 );
649     return TRUE;
650 }
651
652
653 /***********************************************************************
654  *           Beep   (KERNEL32.11)
655  */
656 BOOL32 WINAPI Beep( DWORD dwFreq, DWORD dwDur )
657 {
658     /* dwFreq and dwDur are ignored by Win95 */
659     TSXBell(display, 0);
660     return TRUE;
661 }
662
663
664 /***********************************************************************
665  *      GetTimerResolution (USER.14)
666  */
667 LONG WINAPI GetTimerResolution(void)
668 {
669         return (1000);
670 }
671
672 /***********************************************************************
673  *      SystemParametersInfo32A   (USER32.540)
674  */
675 BOOL32 WINAPI SystemParametersInfo32A( UINT32 uAction, UINT32 uParam,
676                                        LPVOID lpvParam, UINT32 fuWinIni )
677 {
678         int timeout, temp;
679         XKeyboardState          keyboard_state;
680
681         switch (uAction) {
682         case SPI_GETBEEP:
683                 TSXGetKeyboardControl(display, &keyboard_state);
684                 if (keyboard_state.bell_percent == 0)
685                         *(BOOL32 *) lpvParam = FALSE;
686                 else
687                         *(BOOL32 *) lpvParam = TRUE;
688                 break;
689
690         case SPI_GETBORDER:
691                 *(INT32 *)lpvParam = GetSystemMetrics32( SM_CXFRAME );
692                 break;
693
694         case SPI_GETFASTTASKSWITCH:
695                 if ( GetProfileInt32A( "windows", "CoolSwitch", 1 ) == 1 )
696                         *(BOOL32 *) lpvParam = TRUE;
697                 else
698                         *(BOOL32 *) lpvParam = FALSE;
699                 break;
700
701         case SPI_GETDRAGFULLWINDOWS:
702           *(BOOL32 *) lpvParam = FALSE;
703                 
704         case SPI_GETGRIDGRANULARITY:
705                 *(INT32*)lpvParam=GetProfileInt32A("desktop","GridGranularity",1);
706                 break;
707
708         case SPI_GETICONTITLEWRAP:
709                 *(BOOL32*)lpvParam=GetProfileInt32A("desktop","IconTitleWrap",TRUE);
710                 break;
711
712         case SPI_GETKEYBOARDDELAY:
713                 *(INT32*)lpvParam=GetProfileInt32A("keyboard","KeyboardDelay",1);
714                 break;
715
716         case SPI_GETKEYBOARDSPEED:
717                 *(DWORD*)lpvParam=GetProfileInt32A("keyboard","KeyboardSpeed",30);
718                 break;
719
720         case SPI_GETMENUDROPALIGNMENT:
721                 *(BOOL32*)lpvParam=GetSystemMetrics32(SM_MENUDROPALIGNMENT); /* XXX check this */
722                 break;
723
724         case SPI_GETSCREENSAVEACTIVE:
725                 if ( GetProfileInt32A( "windows", "ScreenSaveActive", 1 ) == 1 )
726                         *(BOOL32*)lpvParam = TRUE;
727                 else
728                         *(BOOL32*)lpvParam = FALSE;
729                 break;
730
731         case SPI_GETSCREENSAVETIMEOUT:
732         /* FIXME GetProfileInt( "windows", "ScreenSaveTimeout", 300 ); */
733                 TSXGetScreenSaver(display, &timeout, &temp,&temp,&temp);
734                 *(INT32 *) lpvParam = timeout * 1000;
735                 break;
736
737         case SPI_ICONHORIZONTALSPACING:
738                 /* FIXME Get/SetProfileInt */
739                 if (lpvParam == NULL)
740                         /*SetSystemMetrics( SM_CXICONSPACING, uParam )*/ ;
741                 else
742                         *(INT32*)lpvParam=GetSystemMetrics32(SM_CXICONSPACING);
743                 break;
744
745         case SPI_ICONVERTICALSPACING:
746                 /* FIXME Get/SetProfileInt */
747                 if (lpvParam == NULL)
748                         /*SetSystemMetrics( SM_CYICONSPACING, uParam )*/ ;
749                 else
750                         *(INT32*)lpvParam=GetSystemMetrics32(SM_CYICONSPACING);
751                 break;
752
753         case SPI_GETICONTITLELOGFONT: {
754                 LPLOGFONT32A lpLogFont = (LPLOGFONT32A)lpvParam;
755
756                 /* from now on we always have an alias for MS Sans Serif */
757
758                 GetProfileString32A("Desktop", "IconTitleFaceName", "MS Sans Serif", 
759                         lpLogFont->lfFaceName, LF_FACESIZE );
760                 lpLogFont->lfHeight = -GetProfileInt32A("Desktop","IconTitleSize", 8);
761
762                 lpLogFont->lfWidth = 0;
763                 lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
764                 lpLogFont->lfWeight = FW_NORMAL;
765                 lpLogFont->lfItalic = FALSE;
766                 lpLogFont->lfStrikeOut = FALSE;
767                 lpLogFont->lfUnderline = FALSE;
768                 lpLogFont->lfCharSet = ANSI_CHARSET;
769                 lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
770                 lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
771                 lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
772                 break;
773         }
774         case SPI_GETWORKAREA:
775                 SetRect32( (RECT32 *)lpvParam, 0, 0,
776                         GetSystemMetrics32( SM_CXSCREEN ),
777                         GetSystemMetrics32( SM_CYSCREEN )
778                 );
779                 break;
780         case SPI_GETNONCLIENTMETRICS: 
781
782 #define lpnm ((LPNONCLIENTMETRICS32A)lpvParam)
783                 
784                 if( lpnm->cbSize == sizeof(NONCLIENTMETRICS32A) )
785                 {
786                     /* FIXME: initialize geometry entries */
787
788                     SystemParametersInfo32A(SPI_GETICONTITLELOGFONT, 0,
789                                                         (LPVOID)&(lpnm->lfCaptionFont),0);
790                     SystemParametersInfo32A(SPI_GETICONTITLELOGFONT, 0,
791                                                         (LPVOID)&(lpnm->lfMenuFont),0);
792                     SystemParametersInfo32A(SPI_GETICONTITLELOGFONT, 0,
793                                                         (LPVOID)&(lpnm->lfStatusFont),0);
794                     SystemParametersInfo32A(SPI_GETICONTITLELOGFONT, 0,
795                                                         (LPVOID)&(lpnm->lfMessageFont),0);
796                 }
797 #undef lpnm
798                 break;
799
800         case SPI_GETANIMATION: {
801                 LPANIMATIONINFO lpAnimInfo = (LPANIMATIONINFO)lpvParam;
802  
803                 /* Tell it "disabled" */
804                 lpAnimInfo->cbSize = sizeof(ANIMATIONINFO);
805                 uParam = sizeof(ANIMATIONINFO);
806                 lpAnimInfo->iMinAnimate = 0; /* Minimise and restore animation is disabled (nonzero == enabled) */
807                 break;
808         }
809  
810         case SPI_SETANIMATION: {
811                 LPANIMATIONINFO lpAnimInfo = (LPANIMATIONINFO)lpvParam;
812  
813                 /* Do nothing */
814                 WARN(system, "SPI_SETANIMATION ignored.\n");
815                 lpAnimInfo->cbSize = sizeof(ANIMATIONINFO);
816                 uParam = sizeof(ANIMATIONINFO);
817                 break;
818         }
819
820         case SPI_GETHIGHCONTRAST:
821         {
822                 LPHIGHCONTRASTA lpHighContrastA = (LPHIGHCONTRASTA)lpvParam;
823
824                 FIXME(system,"SPI_GETHIGHCONTRAST not fully implemented\n");
825
826                 if ( lpHighContrastA->cbSize == sizeof( HIGHCONTRASTA ) )
827                 {
828                         /* Indicate that there is no high contrast available */
829                         lpHighContrastA->dwFlags = 0;
830                         lpHighContrastA->lpszDefaultScheme = NULL;
831                 }
832                 else
833                 {
834                         return FALSE;
835                 }
836
837                 break;
838         }
839
840         default:
841                 return SystemParametersInfo16(uAction,uParam,lpvParam,fuWinIni);
842         }
843         return TRUE;
844 }
845
846
847 /***********************************************************************
848  *      SystemParametersInfo16   (USER.483)
849  */
850 BOOL16 WINAPI SystemParametersInfo16( UINT16 uAction, UINT16 uParam,
851                                       LPVOID lpvParam, UINT16 fuWinIni )
852 {
853         int timeout, temp;
854         char buffer[256];
855         XKeyboardState          keyboard_state;
856         XKeyboardControl        keyboard_value;
857
858
859         switch (uAction)
860         {
861                 case SPI_GETBEEP:
862                         TSXGetKeyboardControl(display, &keyboard_state);
863                         if (keyboard_state.bell_percent == 0)
864                                 *(BOOL16 *) lpvParam = FALSE;
865                         else
866                                 *(BOOL16 *) lpvParam = TRUE;
867                         break;
868                 
869                 case SPI_GETBORDER:
870                         *(INT16 *)lpvParam = GetSystemMetrics16( SM_CXFRAME );
871                         break;
872
873                 case SPI_GETFASTTASKSWITCH:
874                     if ( GetProfileInt32A( "windows", "CoolSwitch", 1 ) == 1 )
875                           *(BOOL16 *) lpvParam = TRUE;
876                         else
877                           *(BOOL16 *) lpvParam = FALSE;
878                         break;
879
880                 case SPI_GETGRIDGRANULARITY:
881                     *(INT16 *) lpvParam = GetProfileInt32A( "desktop", 
882                                                           "GridGranularity",
883                                                           1 );
884                     break;
885
886                 case SPI_GETICONTITLEWRAP:
887                     *(BOOL16 *) lpvParam = GetProfileInt32A( "desktop",
888                                                            "IconTitleWrap",
889                                                            TRUE );
890                     break;
891
892                 case SPI_GETKEYBOARDDELAY:
893                     *(INT16 *) lpvParam = GetProfileInt32A( "keyboard",
894                                                           "KeyboardDelay", 1 );
895                     break;
896
897                 case SPI_GETKEYBOARDSPEED:
898                     *(WORD *) lpvParam = GetProfileInt32A( "keyboard",
899                                                            "KeyboardSpeed",
900                                                            30 );
901                     break;
902
903                 case SPI_GETMENUDROPALIGNMENT:
904                         *(BOOL16 *) lpvParam = GetSystemMetrics16( SM_MENUDROPALIGNMENT ); /* XXX check this */
905                         break;
906
907                 case SPI_GETSCREENSAVEACTIVE:
908                     if ( GetProfileInt32A( "windows", "ScreenSaveActive", 1 ) == 1 )
909                         *(BOOL16 *) lpvParam = TRUE;
910                     else
911                         *(BOOL16 *) lpvParam = FALSE;
912                     break;
913
914                 case SPI_GETSCREENSAVETIMEOUT:
915                         /* FIXME GetProfileInt( "windows", "ScreenSaveTimeout", 300 ); */
916                         TSXGetScreenSaver(display, &timeout, &temp,&temp,&temp);
917                         *(INT16 *) lpvParam = timeout * 1000;
918                         break;
919
920                 case SPI_ICONHORIZONTALSPACING:
921                     /* FIXME Get/SetProfileInt */
922                         if (lpvParam == NULL)
923                             /*SetSystemMetrics( SM_CXICONSPACING, uParam )*/ ;
924                         else
925                             *(INT16 *)lpvParam = GetSystemMetrics16( SM_CXICONSPACING );
926                         break;
927
928                 case SPI_ICONVERTICALSPACING:
929                     /* FIXME Get/SetProfileInt */
930                     if (lpvParam == NULL)
931                         /*SetSystemMetrics( SM_CYICONSPACING, uParam )*/ ;
932                     else
933                         *(INT16 *)lpvParam = GetSystemMetrics16(SM_CYICONSPACING);
934                     break;
935
936                 case SPI_SETBEEP:
937                         if (uParam == TRUE)
938                                 keyboard_value.bell_percent = -1;
939                         else
940                                 keyboard_value.bell_percent = 0;                        
941                         TSXChangeKeyboardControl(display, KBBellPercent, 
942                                                         &keyboard_value);
943                         break;
944
945                 case SPI_SETSCREENSAVEACTIVE:
946                         if (uParam == TRUE)
947                                 TSXActivateScreenSaver(display);
948                         else
949                                 TSXResetScreenSaver(display);
950                         break;
951
952                 case SPI_SETSCREENSAVETIMEOUT:
953                         TSXSetScreenSaver(display, uParam, 60, DefaultBlanking, 
954                                                         DefaultExposures);
955                         break;
956
957                 case SPI_SETDESKWALLPAPER:
958                         return (SetDeskWallPaper32((LPSTR) lpvParam));
959                         break;
960
961                 case SPI_SETDESKPATTERN:
962                         if ((INT16)uParam == -1) {
963                                 GetProfileString32A("Desktop", "Pattern", 
964                                                 "170 85 170 85 170 85 170 85", 
965                                                 buffer, sizeof(buffer) );
966                                 return (DESKTOP_SetPattern((LPSTR) buffer));
967                         } else
968                                 return (DESKTOP_SetPattern((LPSTR) lpvParam));
969                         break;
970
971                 case SPI_GETICONTITLELOGFONT: 
972                 {
973                     LPLOGFONT16 lpLogFont = (LPLOGFONT16)lpvParam;
974
975                     GetProfileString32A("Desktop", "IconTitleFaceName", "MS Sans Serif", 
976                                         lpLogFont->lfFaceName, LF_FACESIZE );
977                     lpLogFont->lfHeight = -GetProfileInt32A("Desktop","IconTitleSize", 8);
978
979                     lpLogFont->lfWidth = 0;
980                     lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
981                     lpLogFont->lfWeight = FW_NORMAL;
982                     lpLogFont->lfItalic = FALSE;
983                     lpLogFont->lfStrikeOut = FALSE;
984                     lpLogFont->lfUnderline = FALSE;
985                     lpLogFont->lfCharSet = ANSI_CHARSET;
986                     lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
987                     lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
988                     lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
989                     break;
990                 }
991                 case SPI_GETNONCLIENTMETRICS:
992
993 #define lpnm ((LPNONCLIENTMETRICS16)lpvParam)
994                     if( lpnm->cbSize == sizeof(NONCLIENTMETRICS16) )
995                     {
996                         /* FIXME: initialize geometry entries */
997                         SystemParametersInfo16( SPI_GETICONTITLELOGFONT, 0, 
998                                                         (LPVOID)&(lpnm->lfCaptionFont),0);
999                         SystemParametersInfo16( SPI_GETICONTITLELOGFONT, 0,
1000                                                         (LPVOID)&(lpnm->lfMenuFont),0);
1001                         SystemParametersInfo16( SPI_GETICONTITLELOGFONT, 0,
1002                                                         (LPVOID)&(lpnm->lfStatusFont),0);
1003                         SystemParametersInfo16( SPI_GETICONTITLELOGFONT, 0,
1004                                                         (LPVOID)&(lpnm->lfMessageFont),0);
1005                     }
1006                     else /* winfile 95 sets sbSize to 340 */
1007                         SystemParametersInfo32A( uAction, uParam, lpvParam, fuWinIni );
1008 #undef lpnm
1009                     break;
1010
1011                 case SPI_LANGDRIVER:
1012                 case SPI_SETBORDER:
1013                 case SPI_SETDOUBLECLKHEIGHT:
1014                 case SPI_SETDOUBLECLICKTIME:
1015                 case SPI_SETDOUBLECLKWIDTH:
1016                 case SPI_SETFASTTASKSWITCH:
1017                 case SPI_SETKEYBOARDDELAY:
1018                 case SPI_SETKEYBOARDSPEED:
1019                         WARN(system, "Option %d ignored.\n", uAction);
1020                         break;
1021
1022                 case SPI_GETWORKAREA:
1023                     SetRect16( (RECT16 *)lpvParam, 0, 0,
1024                                GetSystemMetrics16( SM_CXSCREEN ),
1025                                GetSystemMetrics16( SM_CYSCREEN ) );
1026                     break;
1027
1028                 default:
1029                         WARN(system, "Unknown option %d.\n", uAction);
1030                         break;
1031         }
1032         return 1;
1033 }
1034
1035 /***********************************************************************
1036  *      SystemParametersInfo32W   (USER32.541)
1037  */
1038 BOOL32 WINAPI SystemParametersInfo32W( UINT32 uAction, UINT32 uParam,
1039                                        LPVOID lpvParam, UINT32 fuWinIni )
1040 {
1041     char buffer[256];
1042
1043     switch (uAction)
1044     {
1045     case SPI_SETDESKWALLPAPER:
1046         if (lpvParam)
1047         {
1048             lstrcpynWtoA(buffer,(LPWSTR)lpvParam,sizeof(buffer));
1049             return SetDeskWallPaper32(buffer);
1050         }
1051         return SetDeskWallPaper32(NULL);
1052
1053     case SPI_SETDESKPATTERN:
1054         if ((INT32) uParam == -1)
1055         {
1056             GetProfileString32A("Desktop", "Pattern", 
1057                                 "170 85 170 85 170 85 170 85", 
1058                                 buffer, sizeof(buffer) );
1059             return (DESKTOP_SetPattern((LPSTR) buffer));
1060         }
1061         if (lpvParam)
1062         {
1063             lstrcpynWtoA(buffer,(LPWSTR)lpvParam,sizeof(buffer));
1064             return DESKTOP_SetPattern(buffer);
1065         }
1066         return DESKTOP_SetPattern(NULL);
1067
1068     case SPI_GETICONTITLELOGFONT:
1069         {
1070             /* FIXME GetProfileString32A( "?", "?", "?" ) */
1071             LPLOGFONT32W lpLogFont = (LPLOGFONT32W)lpvParam;
1072             lpLogFont->lfHeight = 10;
1073             lpLogFont->lfWidth = 0;
1074             lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
1075             lpLogFont->lfWeight = FW_NORMAL;
1076             lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
1077             lpLogFont->lfCharSet = ANSI_CHARSET;
1078             lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1079             lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1080             lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
1081         }
1082         break;
1083     case SPI_GETNONCLIENTMETRICS: {
1084         /* FIXME: implement correctly */
1085         LPNONCLIENTMETRICS32W   lpnm=(LPNONCLIENTMETRICS32W)lpvParam;
1086
1087         SystemParametersInfo32W(SPI_GETICONTITLELOGFONT,0,(LPVOID)&(lpnm->lfCaptionFont),0);
1088         SystemParametersInfo32W(SPI_GETICONTITLELOGFONT,0,(LPVOID)&(lpnm->lfMenuFont),0);
1089         SystemParametersInfo32W(SPI_GETICONTITLELOGFONT,0,(LPVOID)&(lpnm->lfStatusFont),0);
1090         SystemParametersInfo32W(SPI_GETICONTITLELOGFONT,0,(LPVOID)&(lpnm->lfMessageFont),0);
1091         break;
1092     }
1093
1094     case SPI_GETHIGHCONTRAST:
1095     {
1096        LPHIGHCONTRASTA lpHighContrastW = (LPHIGHCONTRASTW)lpvParam;
1097
1098        FIXME(system,"SPI_GETHIGHCONTRAST not fully implemented\n");
1099
1100        if ( lpHighContrastW->cbSize == sizeof( HIGHCONTRASTW ) )
1101        {
1102           /* Indicate that there is no high contrast available */
1103           lpHighContrastW->dwFlags = 0;
1104           lpHighContrastW->lpszDefaultScheme = NULL;
1105        }
1106        else
1107        {
1108           return FALSE;
1109        }
1110
1111        break;
1112     }
1113
1114     default:
1115         return SystemParametersInfo32A(uAction,uParam,lpvParam,fuWinIni);
1116         
1117     }
1118     return TRUE;
1119 }
1120
1121
1122 /***********************************************************************
1123 *       FileCDR (KERNEL.130)
1124 */
1125 void WINAPI FileCDR(FARPROC16 x)
1126 {
1127         FIXME(file,"(%8x): stub\n", (int) x);
1128 }