Release 950620
[wine] / misc / main.c
1 /*
2  * Main function.
3  *
4  * Copyright 1994 Alexandre Julliard
5  *
6 static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
7 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <locale.h>
13 #ifdef MALLOC_DEBUGGING
14 #include <malloc.h>
15 #endif
16 #include <X11/Xlib.h>
17 #include <X11/Xresource.h>
18 #include <X11/Xutil.h>
19 #include <X11/cursorfont.h>
20 #include "wine.h"
21 #include "msdos.h"
22 #include "windows.h"
23 #include "miscemu.h"
24 #include "winsock.h"
25 #include "options.h"
26 #include "desktop.h"
27 #include "prototypes.h"
28 #include "dlls.h"
29 #define DEBUG_DEFINE_VARIABLES
30 #include "stddebug.h"
31 #include "debug.h"
32
33 const char people[] = "Wine is available thanks to the work of "\
34 "Bob Amstadt, Dag Asheim, Martin Ayotte, Ross Biro, Erik Bos, Fons Botman, "\
35 "John Brezak, Andrew Bulhak, John Burton, Paul Falstad, Olaf Flebbe, "\
36 "Peter Galbavy, Cameron Heide, Jeffrey Hsu, Miguel de Icaza, "\
37 "Alexandre Julliard, Jon Konrath, Scott A. Laird, Martin von Loewis, "\
38 "Kenneth MacDonald, Peter MacDonald, William Magro, David Metcalfe, "\
39 "Michael Patra, John Richardson, Johannes Ruscheinski, Thomas Sandford, "\
40 "Constantine Sapuntzakis, Bernd Schmidt, Yngvi Sigurjonsson, Rick Sladkey, "\
41 "William Smith, Erik Svendsen, Goran Thyni, Jimmy Tirtawangsa, Jon Tombs, "\
42 "Linus Torvalds, Michael Veksler, Carl Williams, Karl Guenter Wuensch, "\
43 "Eric Youngdale, and James Youngman.";
44
45 #define WINE_CLASS    "Wine"    /* Class name for resources */
46
47 typedef struct tagENVENTRY {
48   LPSTR                 Name;
49   LPSTR                 Value;
50   WORD                  wSize;
51   struct tagENVENTRY    *Prev;
52   struct tagENVENTRY    *Next;
53 } ENVENTRY, *LPENVENTRY;
54
55 LPENVENTRY      lpEnvList = NULL;
56
57 Display *display;
58 Screen *screen;
59 Window rootWindow;
60 int screenWidth = 0, screenHeight = 0;  /* Desktop window dimensions */
61 int screenDepth = 0;  /* Screen depth to use */
62 int desktopX = 0, desktopY = 0;  /* Desktop window position (if any) */
63
64 struct options Options =
65 {  /* default options */
66     NULL,           /* spyFilename */
67     NULL,           /* desktopGeometry */
68     NULL,           /* programName */
69     FALSE,          /* usePrivateMap */
70     FALSE,          /* synchronous */
71     FALSE,          /* backing store */
72     SW_SHOWNORMAL,  /* cmdShow */
73     FALSE,
74     FALSE,          /* AllowReadOnly */
75     FALSE           /* Enhanced mode */
76 };
77
78
79 static XrmOptionDescRec optionsTable[] =
80 {
81     { "-backingstore",  ".backingstore",    XrmoptionNoArg,  (caddr_t)"on" },
82     { "-desktop",       ".desktop",         XrmoptionSepArg, (caddr_t)NULL },
83     { "-depth",         ".depth",           XrmoptionSepArg, (caddr_t)NULL },
84     { "-display",       ".display",         XrmoptionSepArg, (caddr_t)NULL },
85     { "-iconic",        ".iconic",          XrmoptionNoArg,  (caddr_t)"on" },
86     { "-name",          ".name",            XrmoptionSepArg, (caddr_t)NULL },
87     { "-privatemap",    ".privatemap",      XrmoptionNoArg,  (caddr_t)"on" },
88     { "-synchronous",   ".synchronous",     XrmoptionNoArg,  (caddr_t)"on" },
89     { "-spy",           ".spy",             XrmoptionSepArg, (caddr_t)NULL },
90     { "-debug",         ".debug",           XrmoptionNoArg,  (caddr_t)"on" },
91     { "-debugmsg",      ".debugmsg",        XrmoptionSepArg, (caddr_t)NULL },
92     { "-dll",           ".dll",             XrmoptionSepArg, (caddr_t)NULL },
93     { "-allowreadonly", ".allowreadonly",   XrmoptionNoArg,  (caddr_t)"on" },
94     { "-enhanced",      ".enhanced",        XrmoptionNoArg,  (caddr_t)"off"}
95 };
96
97 #define NB_OPTIONS  (sizeof(optionsTable) / sizeof(optionsTable[0]))
98
99 #define USAGE \
100   "Usage:  %s [options] program_name [arguments]\n" \
101   "\n" \
102   "Options:\n" \
103   "    -depth n        Change the depth to use for multiple-depth screens\n" \
104   "    -desktop geom   Use a desktop window of the given geometry\n" \
105   "    -display name   Use the specified display\n" \
106   "    -iconic         Start as an icon\n" \
107   "    -debug          Enter debugger before starting application\n" \
108   "    -name name      Set the application name\n" \
109   "    -privatemap     Use a private color map\n" \
110   "    -synchronous    Turn on synchronous display mode\n" \
111   "    -backingstore   Turn on backing store\n" \
112   "    -spy file       Turn on message spying to the specified file\n" \
113   "    -debugmsg name  Turn debugging-messages on or off\n" \
114   "    -dll name       Enable or disable built-in DLLs\n" \
115   "    -allowreadonly  Read only files may be opened in write mode\n" \
116   "    -enhanced       Start wine in enhanced mode\n"
117
118
119
120 /***********************************************************************
121  *           MAIN_Usage
122  */
123 static void MAIN_Usage( char *name )
124 {
125     fprintf( stderr, USAGE, name );
126     exit(1);
127 }
128
129
130 /***********************************************************************
131  *           MAIN_GetProgramName
132  *
133  * Get the program name. The name is specified by (in order of precedence):
134  * - the option '-name'.
135  * - the environment variable 'WINE_NAME'.
136  * - the last component of argv[0].
137  */
138 static char *MAIN_GetProgramName( int argc, char *argv[] )
139 {
140     int i;
141     char *p;
142
143     for (i = 1; i < argc-1; i++)
144         if (!strcmp( argv[i], "-name" )) return argv[i+1];
145     if ((p = getenv( "WINE_NAME" )) != NULL) return p;
146     if ((p = strrchr( argv[0], '/' )) != NULL) return p+1;
147     return argv[0];
148 }
149
150
151 /***********************************************************************
152  *           MAIN_GetResource
153  *
154  * Fetch the value of resource 'name' using the correct instance name.
155  * 'name' must begin with '.' or '*'
156  */
157 static int MAIN_GetResource( XrmDatabase db, char *name, XrmValue *value )
158 {
159     char *buff_instance, *buff_class;
160     char *dummy;
161     int retval;
162
163     buff_instance = (char *)malloc(strlen(Options.programName)+strlen(name)+1);
164     buff_class    = (char *)malloc( strlen(WINE_CLASS) + strlen(name) + 1 );
165
166     strcpy( buff_instance, Options.programName );
167     strcat( buff_instance, name );
168     strcpy( buff_class, WINE_CLASS );
169     strcat( buff_class, name );
170     retval = XrmGetResource( db, buff_instance, buff_class, &dummy, value );
171     free( buff_instance );
172     free( buff_class );
173     return retval;
174 }
175
176
177 /***********************************************************************
178  *                    ParseDebugOptions
179  *
180  *  Turns specific debug messages on or off, according to "options".
181  *  Returns TRUE if parsing was successfull 
182  */
183 #ifdef DEBUG_RUNTIME
184
185 BOOL ParseDebugOptions(char *options)
186 {
187   int l;
188   if (strlen(options)<3)
189     return FALSE;
190   do
191   {
192     if ((*options!='+')&&(*options!='-'))
193       return FALSE;
194     if (strchr(options,','))
195       l=strchr(options,',')-options;
196     else
197       l=strlen(options);
198     if (!strncasecmp(options+1,"all",l-1))
199       {
200         int i;
201         for (i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
202           debug_msg_enabled[i]=(*options=='+');
203       }
204     else
205       {
206         int i;
207         for (i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
208           if (debug_msg_name && (!strncasecmp(options+1,debug_msg_name[i],l-1)))
209             {
210               debug_msg_enabled[i]=(*options=='+');
211               break;
212             }
213         if (i==sizeof(debug_msg_enabled)/sizeof(short))
214           return FALSE;
215       }
216     options+=l;
217   }
218   while((*options==',')&&(*(++options)));
219   if (*options)
220     return FALSE;
221   else
222     return TRUE;
223 }
224
225 #endif
226
227 /***********************************************************************
228  *           MAIN_ParseDLLOptions
229  *
230  * Set runtime DLL usage flags
231  */
232 static BOOL MAIN_ParseDLLOptions(char *options)
233 {
234   int l;
235   int i;
236   if (strlen(options)<3)
237     return FALSE;
238   do
239   {
240     if ((*options!='+')&&(*options!='-'))
241       return FALSE;
242     if (strchr(options,','))
243       l=strchr(options,',')-options;
244     else l=strlen(options);
245     for (i=0;i<N_BUILTINS;i++)
246          if (!strncasecmp(options+1,dll_builtin_table[i].name,l-1))
247            {
248              dll_builtin_table[i].used = (*options=='+');
249              break;
250            }
251     if (i==N_BUILTINS)
252          return FALSE;
253     options+=l;
254   }
255   while((*options==',')&&(*(++options)));
256   if (*options)
257     return FALSE;
258   else
259     return TRUE;
260 }
261
262
263
264 /***********************************************************************
265  *           MAIN_ParseOptions
266  *
267  * Parse command line options and open display.
268  */
269 static void MAIN_ParseOptions( int *argc, char *argv[] )
270 {
271     char *display_name;
272     XrmValue value;
273     XrmDatabase db = XrmGetFileDatabase("/usr/lib/X11/app-defaults/Wine");
274
275       /* Parse command line */
276     Options.programName = MAIN_GetProgramName( *argc, argv );
277     XrmParseCommand( &db, optionsTable, NB_OPTIONS,
278                      Options.programName, argc, argv );
279
280 #ifdef WINELIB
281     /* Need to assemble command line and pass it to WinMain */
282 #else
283     if (*argc < 2 || strcasecmp(argv[1], "-h") == 0) 
284         MAIN_Usage( argv[0] );
285 #endif
286
287       /* Open display */
288
289     if (MAIN_GetResource( db, ".display", &value )) display_name = value.addr;
290     else display_name = NULL;
291
292     if (!(display = XOpenDisplay( display_name )))
293     {
294         fprintf( stderr, "%s: Can't open display: %s\n",
295                  argv[0], display_name ? display_name : "" );
296         exit(1);
297     }
298
299       /* Get all options */
300     if (MAIN_GetResource( db, ".iconic", &value ))
301         Options.cmdShow = SW_SHOWMINIMIZED;
302     if (MAIN_GetResource( db, ".privatemap", &value ))
303         Options.usePrivateMap = TRUE;
304     if (MAIN_GetResource( db, ".synchronous", &value ))
305         Options.synchronous = TRUE;
306     if (MAIN_GetResource( db, ".backingstore", &value ))
307         Options.backingstore = TRUE;    
308     if (MAIN_GetResource( db, ".debug", &value ))
309         Options.debug = TRUE;
310     if (MAIN_GetResource( db, ".allowreadonly", &value ))
311         Options.allowReadOnly = TRUE;
312     if (MAIN_GetResource( db, ".enhanced", &value ))
313         Options.enhanced = TRUE;
314     if (MAIN_GetResource( db, ".spy", &value))
315         Options.spyFilename = value.addr;
316     if (MAIN_GetResource( db, ".depth", &value))
317         screenDepth = atoi( value.addr );
318     if (MAIN_GetResource( db, ".desktop", &value))
319         Options.desktopGeometry = value.addr;
320 #ifdef DEBUG_RUNTIME
321     if (MAIN_GetResource( db, ".debugoptions", &value))
322         ParseDebugOptions((char*)value.addr);
323 #endif
324     if (MAIN_GetResource( db, ".debugmsg", &value))
325       {
326 #ifndef DEBUG_RUNTIME
327         fprintf(stderr,"%s: Option \"-debugmsg\" not implemented.\n" \
328           "    Recompile with DEBUG_RUNTIME in include/stddebug.h defined.\n",
329           argv[0]);
330         exit(1);
331 #else
332         if (ParseDebugOptions((char*)value.addr)==FALSE)
333           {
334             int i;
335             fprintf(stderr,"%s: Syntax: -debugmsg +xxx,...  or -debugmsg -xxx,...\n",argv[0]);
336             fprintf(stderr,"Example: -debugmsg +all,-heap    turn on all messages except heap messages\n");
337             fprintf(stderr,"Available message types:\n");
338             fprintf(stderr,"%-9s ","all");
339             for(i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
340               if(debug_msg_name[i])
341                 fprintf(stderr,"%-9s%c",debug_msg_name[i],
342                         (((i+2)%8==0)?'\n':' '));
343             fprintf(stderr,"\n\n");
344             exit(1);
345           }
346 #endif
347       }
348
349       if(MAIN_GetResource( db, ".dll", &value))
350        if(MAIN_ParseDLLOptions((char*)value.addr)==FALSE)
351        {
352          int i;
353          fprintf(stderr,"%s: Syntax: -dll +xxx,... or -dll -xxx,...\n",argv[0]);
354          fprintf(stderr,"Example: -dll -ole2    Do not use emulated OLE2.DLL\n");
355          fprintf(stderr,"Available DLLs\n");
356          for(i=0;i<N_BUILTINS;i++)
357                fprintf(stderr,"%-9s%c",dll_builtin_table[i].name,
358                        (((i+2)%8==0)?'\n':' '));
359          fprintf(stderr,"\n\n");
360          exit(1);
361        }
362 }
363
364
365 /***********************************************************************
366  *           MAIN_CreateDesktop
367  */
368 static void MAIN_CreateDesktop( int argc, char *argv[] )
369 {
370     int flags;
371     unsigned int width = 640, height = 480;  /* Default size = 640x480 */
372     char *name = "Wine desktop";
373     XSizeHints *size_hints;
374     XWMHints   *wm_hints;
375     XClassHint *class_hints;
376     XSetWindowAttributes win_attr;
377     XTextProperty window_name;
378
379     flags = XParseGeometry( Options.desktopGeometry,
380                             &desktopX, &desktopY, &width, &height );
381     screenWidth  = width;
382     screenHeight = height;
383
384       /* Create window */
385
386     win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
387                          PointerMotionMask | ButtonPressMask |
388                          ButtonReleaseMask | EnterWindowMask | 
389                          StructureNotifyMask;
390     win_attr.cursor = XCreateFontCursor( display, XC_top_left_arrow );
391
392     rootWindow = XCreateWindow( display, DefaultRootWindow(display),
393                                 desktopX, desktopY, width, height, 0,
394                                 CopyFromParent, InputOutput, CopyFromParent,
395                                 CWEventMask | CWCursor, &win_attr );
396
397       /* Set window manager properties */
398
399     size_hints  = XAllocSizeHints();
400     wm_hints    = XAllocWMHints();
401     class_hints = XAllocClassHint();
402     if (!size_hints || !wm_hints || !class_hints)
403     {
404         fprintf( stderr, "Not enough memory for window manager hints.\n" );
405         exit(1);
406     }
407     size_hints->min_width = size_hints->max_width = width;
408     size_hints->min_height = size_hints->max_height = height;
409     size_hints->flags = PMinSize | PMaxSize;
410     if (flags & (XValue | YValue)) size_hints->flags |= USPosition;
411     if (flags & (WidthValue | HeightValue)) size_hints->flags |= USSize;
412     else size_hints->flags |= PSize;
413
414     wm_hints->flags = InputHint | StateHint;
415     wm_hints->input = True;
416     wm_hints->initial_state = NormalState;
417     class_hints->res_name = argv[0];
418     class_hints->res_class = "Wine";
419
420     XStringListToTextProperty( &name, 1, &window_name );
421     XSetWMProperties( display, rootWindow, &window_name, &window_name,
422                       argv, argc, size_hints, wm_hints, class_hints );
423     XFree( size_hints );
424     XFree( wm_hints );
425     XFree( class_hints );
426
427       /* Map window */
428
429     XMapWindow( display, rootWindow );
430 }
431
432
433 XKeyboardState keyboard_state;
434
435 /***********************************************************************
436  *           MAIN_SaveSetup
437  */
438 static void MAIN_SaveSetup(void)
439 {
440     XGetKeyboardControl(display, &keyboard_state);
441 }
442
443 /***********************************************************************
444  *           MAIN_RestoreSetup
445  */
446 static void MAIN_RestoreSetup(void)
447 {
448     XKeyboardControl keyboard_value;
449
450     keyboard_value.key_click_percent    = keyboard_state.key_click_percent;
451     keyboard_value.bell_percent         = keyboard_state.bell_percent;
452     keyboard_value.bell_pitch           = keyboard_state.bell_pitch;
453     keyboard_value.bell_duration        = keyboard_state.bell_duration;
454     keyboard_value.auto_repeat_mode     = keyboard_state.global_auto_repeat;
455
456     XChangeKeyboardControl(display, KBKeyClickPercent | KBBellPercent | 
457         KBBellPitch | KBBellDuration | KBAutoRepeatMode, &keyboard_value);
458 }
459
460 static void malloc_error()
461 {
462        fprintf(stderr,"malloc is not feeling well. Good bye\n");
463        exit(1);
464 }
465
466 static void called_at_exit(void)
467 {
468     sync_profiles();
469     MAIN_RestoreSetup();
470     WSACleanup();
471 }
472
473 /***********************************************************************
474  *           main
475  */
476 int main( int argc, char *argv[] )
477 {    
478     int ret_val;
479     int depth_count, i;
480     int *depth_list;
481
482         setbuf(stdout,NULL);
483         setbuf(stderr,NULL);
484
485     setlocale(LC_CTYPE,"");
486
487     XrmInitialize();
488     
489     MAIN_ParseOptions( &argc, argv );
490
491 #ifdef MALLOC_DEBUGGING
492     if(debugging_malloc)
493     {
494        char *trace=getenv("MALLOC_TRACE");
495        if(!trace)
496        {       
497         dprintf_malloc(stddeb,"MALLOC_TRACE not set. No trace generated\n");
498        }else
499        {
500                dprintf_malloc(stddeb,"malloc trace goes to %s\n",trace);
501                mtrace();
502        }
503       mcheck(malloc_error);
504     }
505 #endif
506
507     screen       = DefaultScreenOfDisplay( display );
508     screenWidth  = WidthOfScreen( screen );
509     screenHeight = HeightOfScreen( screen );
510     if (screenDepth)  /* -depth option specified */
511     {
512         depth_list = XListDepths(display,DefaultScreen(display),&depth_count);
513         for (i = 0; i < depth_count; i++)
514             if (depth_list[i] == screenDepth) break;
515         XFree( depth_list );
516         if (i >= depth_count)
517         {
518             fprintf( stderr, "%s: Depth %d not supported on this screen.\n",
519                               Options.programName, screenDepth );
520             exit(1);
521         }
522     }
523     else screenDepth  = DefaultDepthOfScreen( screen );
524     if (Options.synchronous) XSynchronize( display, True );
525     if (Options.desktopGeometry) MAIN_CreateDesktop( argc, argv );
526     else rootWindow = DefaultRootWindow( display );
527
528     MAIN_SaveSetup();
529 #ifndef sparc
530     atexit(called_at_exit);
531 #else
532     on_exit (called_at_exit, 0);
533 #endif
534
535     ret_val = _WinMain( argc, argv );
536
537     return ret_val;
538 }
539
540 /***********************************************************************
541  *           MessageBeep    (USER.104)
542  */
543 void MessageBeep(WORD i)
544 {
545         XBell(display, 100);
546 }
547
548 /***********************************************************************
549  *      GetVersion (KERNEL.3)
550  */
551 LONG GetVersion(void)
552 {
553     return MAKELONG( WINVERSION, DOSVERSION );
554 }
555
556 /***********************************************************************
557  *      GetWinFlags (KERNEL.132)
558  */
559 LONG GetWinFlags(void)
560 {
561   if (Options.enhanced)
562     return (WF_STANDARD | WF_ENHANCED | WF_CPU286 | WF_PMODE | WF_80x87);
563   else
564     return (WF_STANDARD | WF_CPU286 | WF_PMODE | WF_80x87);
565 }
566
567 /***********************************************************************
568  *      SetEnvironment (GDI.132)
569  */
570 int SetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nCount)
571 {
572         LPENVENTRY      lpNewEnv;
573         LPENVENTRY      lpEnv = lpEnvList;
574         printf("SetEnvironnement('%s', '%s', %d) !\n", 
575                                 lpPortName, lpEnviron, nCount);
576         if (lpPortName == NULL) return -1;
577         while (lpEnv != NULL) {
578                 if (lpEnv->Name != NULL && strcmp(lpEnv->Name, lpPortName) == 0) {
579                         if (nCount == 0 || lpEnviron == NULL) {
580                                 if (lpEnv->Prev != NULL) lpEnv->Prev->Next = lpEnv->Next;
581                                 if (lpEnv->Next != NULL) lpEnv->Next->Prev = lpEnv->Prev;
582                                 free(lpEnv->Value);
583                                 free(lpEnv->Name);
584                                 free(lpEnv);
585                                 printf("SetEnvironnement() // entry deleted !\n");
586                                 return -1;
587                                 }
588                         free(lpEnv->Value);
589                         lpEnv->Value = malloc(nCount);
590                         if (lpEnv->Value == NULL) {
591                                 printf("SetEnvironment() // Error allocating entry value !\n");
592                                 return 0;
593                         }
594                         memcpy(lpEnv->Value, lpEnviron, nCount);
595                         lpEnv->wSize = nCount;
596                         printf("SetEnvironnement() // entry modified !\n");
597                         return nCount;
598                         }
599                 if (lpEnv->Next == NULL) break;
600                 lpEnv = lpEnv->Next;
601                 }
602         if (nCount == 0 || lpEnviron == NULL) return -1;
603         printf("SetEnvironnement() // new entry !\n");
604         lpNewEnv = malloc(sizeof(ENVENTRY));
605         if (lpNewEnv == NULL) {
606                 printf("SetEnvironment() // Error allocating new entry !\n");
607                 return 0;
608                 }
609         if (lpEnvList == NULL) {
610                 lpEnvList = lpNewEnv;
611                 lpNewEnv->Prev = NULL;
612                 }
613         else {
614                 lpEnv->Next = lpNewEnv;
615                 lpNewEnv->Prev = lpEnv;
616                 }
617         lpNewEnv->Next = NULL;
618         lpNewEnv->Name = malloc(strlen(lpPortName) + 1);
619         if (lpNewEnv->Name == NULL) {
620                 printf("SetEnvironment() // Error allocating entry name !\n");
621                 return 0;
622                 }
623         strcpy(lpNewEnv->Name, lpPortName);
624         lpNewEnv->Value = malloc(nCount);
625         if (lpNewEnv->Value == NULL) {
626                 printf("SetEnvironment() // Error allocating entry value !\n");
627                 return 0;
628                 }
629         memcpy(lpNewEnv->Value, lpEnviron, nCount);
630         lpNewEnv->wSize = nCount;
631         return nCount;
632 }
633
634 /***********************************************************************
635  *      GetEnvironment (GDI.134)
636  */
637 int GetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nMaxSiz)
638 {
639         WORD            nCount;
640         LPENVENTRY      lpEnv = lpEnvList;
641         printf("GetEnvironnement('%s', '%s', %d) !\n",
642                                         lpPortName, lpEnviron, nMaxSiz);
643         while (lpEnv != NULL) {
644                 if (lpEnv->Name != NULL && strcmp(lpEnv->Name, lpPortName) == 0) {
645                         nCount = min(nMaxSiz, lpEnv->wSize);
646                         memcpy(lpEnviron, lpEnv->Value, nCount);
647                         printf("GetEnvironnement() // found '%s' !\n", lpEnviron);
648                         return nCount;
649                         }
650                 lpEnv = lpEnv->Next;
651                 }
652         printf("GetEnvironnement() // not found !\n");
653         return 0;
654 }
655
656 /***********************************************************************
657  *      GetTimerResolution (USER.14)
658  */
659 LONG GetTimerResolution(void)
660 {
661         return (1000);
662 }
663
664 /***********************************************************************
665  *      SystemParametersInfo (USER.483)
666  */
667 BOOL SystemParametersInfo (UINT uAction, UINT uParam, void FAR *lpvParam, UINT fuWinIni)
668 {
669         int timeout, temp;
670         char buffer[256];
671         XKeyboardState          keyboard_state;
672         XKeyboardControl        keyboard_value;
673
674
675         fprintf(stderr, "SystemParametersInfo: action %d, param %x, flag %x\n", 
676                         uAction, uParam, fuWinIni);
677
678         switch (uAction) {
679                 case SPI_GETBEEP:
680                         XGetKeyboardControl(display, &keyboard_state);
681                         if (keyboard_state.bell_percent == 0)
682                                 *(BOOL *) lpvParam = FALSE;
683                         else
684                                 *(BOOL *) lpvParam = TRUE;
685                         break;
686                 
687                 case SPI_GETBORDER:
688                         *(INT *) lpvParam = 1;
689                         break;
690
691                 case SPI_GETFASTTASKSWITCH:
692                         *(BOOL *) lpvParam = FALSE;
693                         break;
694
695                 case SPI_GETGRIDGRANULARITY:
696                         *(INT *) lpvParam = 1;
697                         break;
698
699                 case SPI_GETICONTITLEWRAP:
700                         *(BOOL *) lpvParam = FALSE;
701                         break;
702
703                 case SPI_GETKEYBOARDDELAY:
704                         *(INT *) lpvParam = 1;
705                         break;
706
707                 case SPI_GETKEYBOARDSPEED:
708                         *(WORD *) lpvParam = 30;
709                         break;
710
711                 case SPI_GETMENUDROPALIGNMENT:
712                         *(BOOL *) lpvParam = FALSE;
713                         break;
714
715                 case SPI_GETSCREENSAVEACTIVE:
716                         *(BOOL *) lpvParam = FALSE;
717                         break;
718
719                 case SPI_GETSCREENSAVETIMEOUT:
720                         XGetScreenSaver(display, &timeout, &temp,&temp,&temp);
721                         *(INT *) lpvParam = timeout * 1000;
722                         break;
723
724                 case SPI_ICONHORIZONTALSPACING:
725                         if (lpvParam == NULL)
726                                 fprintf(stderr, "SystemParametersInfo: Horizontal icon spacing set to %d\n.", uParam);
727                         else
728                                 *(INT *) lpvParam = 50;
729                         break;
730
731                 case SPI_ICONVERTICALSPACING:
732                         if (lpvParam == NULL)
733                                 fprintf(stderr, "SystemParametersInfo: Vertical icon spacing set to %d\n.", uParam);
734                         else
735                                 *(INT *) lpvParam = 50;
736                         break;
737
738                 case SPI_SETBEEP:
739                         if (uParam == TRUE)
740                                 keyboard_value.bell_percent = -1;
741                         else
742                                 keyboard_value.bell_percent = 0;                        
743                         XChangeKeyboardControl(display, KBBellPercent, 
744                                                         &keyboard_value);
745                         break;
746
747                 case SPI_SETSCREENSAVEACTIVE:
748                         if (uParam == TRUE)
749                                 XActivateScreenSaver(display);
750                         else
751                                 XResetScreenSaver(display);
752                         break;
753
754                 case SPI_SETSCREENSAVETIMEOUT:
755                         XSetScreenSaver(display, uParam, 60, DefaultBlanking, 
756                                                 DefaultExposures);
757                         break;
758
759                 case SPI_SETDESKWALLPAPER:
760                         return (SetDeskWallPaper((LPSTR) lpvParam));
761                         break;
762
763                 case SPI_SETDESKPATTERN:
764                         if ((INT) uParam == -1) {
765                                 GetProfileString("Desktop", "Pattern", 
766                                                 "170 85 170 85 170 85 170 85", 
767                                                 buffer, sizeof(buffer) );
768                                 return (DESKTOP_SetPattern((LPSTR) buffer));
769                         } else
770                                 return (DESKTOP_SetPattern((LPSTR) lpvParam));
771                         break;
772
773                 case SPI_GETICONTITLELOGFONT: 
774                 {
775                   LPLOGFONT lpLogFont = (LPLOGFONT)lpvParam;
776                   lpLogFont->lfHeight = 10;
777                   lpLogFont->lfWidth = 0;
778                   lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
779                   lpLogFont->lfWeight = FW_NORMAL;
780                   lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
781                   lpLogFont->lfCharSet = ANSI_CHARSET;
782                   lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
783                   lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
784                   lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
785                   break;
786                 }
787                 case SPI_LANGDRIVER:
788                 case SPI_SETBORDER:
789                 case SPI_SETDOUBLECLKHEIGHT:
790                 case SPI_SETDOUBLECLICKTIME:
791                 case SPI_SETDOUBLECLKWIDTH:
792                 case SPI_SETFASTTASKSWITCH:
793                 case SPI_SETKEYBOARDDELAY:
794                 case SPI_SETKEYBOARDSPEED:
795                         fprintf(stderr, "SystemParametersInfo: option %d ignored.\n", uParam);
796                         break;
797
798                 default:
799                         fprintf(stderr, "SystemParametersInfo: unknown option %d.\n", uParam);
800                         break;
801         }
802         return 1;
803 }
804
805 /***********************************************************************
806 *       HMEMCPY (KERNEL.348)
807 */
808 void hmemcpy(void FAR *hpvDest, const void FAR *hpvSource, long cbCopy)
809 {
810         memcpy(hpvDest, hpvSource, cbCopy);
811 }
812
813 /***********************************************************************
814 *       COPY (GDI.250)
815 */
816 void Copy(LPVOID lpSource, LPVOID lpDest, WORD nBytes)
817 {
818         memcpy(lpDest, lpSource, nBytes);
819 }
820
821 /***********************************************************************
822 *       SWAPMOUSEBUTTON (USER.186)
823 */
824 BOOL SwapMouseButton(BOOL fSwap)
825 {
826         return 0;       /* don't swap */
827 }
828
829 /***********************************************************************
830 *       FileCDR (KERNEL.130)
831 */
832 void FileCDR(FARPROC x)
833 {
834         printf("FileCDR(%8x)\n", (int) x);
835 }