Release 960405
[wine] / misc / main.c
1 /*
2  * Main function.
3  *
4  * Copyright 1994 Alexandre Julliard
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.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 "message.h"
22 #include "msdos.h"
23 #include "windows.h"
24 #include "winsock.h"
25 #include "options.h"
26 #include "desktop.h"
27 #include "shell.h"
28 #include "dlls.h"
29 #define DEBUG_DEFINE_VARIABLES
30 #include "stddebug.h"
31 #include "debug.h"
32 #include "xmalloc.h"
33
34 const char people[] = "Wine is available thanks to the work of "
35 "Bob Amstadt, Dag Asheim, Martin Ayotte, Ross Biro, Erik Bos, "
36 "Fons Botman, John Brezak, Andrew Bulhak, John Burton, Paul Falstad, "
37 "Olaf Flebbe, Peter Galbavy, Ramon Garcia, Hans de Graaff, "
38 "Charles M. Hannum, Cameron Heide, Jochen Hoenicke, Jeffrey Hsu, "
39 "Miguel de Icaza, Alexandre Julliard, Jon Konrath, Scott A. Laird, "
40 "Martin von Loewis, Kenneth MacDonald, Peter MacDonald, William Magro, "
41 "Marcus Meissner, Graham Menhennitt, David Metcalfe, Michael Patra, "
42 "John Richardson, Johannes Ruscheinski, Thomas Sandford, "
43 "Constantine Sapuntzakis, Daniel Schepler, Bernd Schmidt, "
44 "Yngvi Sigurjonsson, Rick Sladkey, William Smith, Erik Svendsen, "
45 "Goran Thyni, Jimmy Tirtawangsa, Jon Tombs, Linus Torvalds, "
46 "Gregory Trubetskoy, Michael Veksler, Morten Welinder, Jan Willamowius, "
47 "Carl Williams, Karl Guenter Wuensch, Eric Youngdale, and James Youngman.";
48
49 static const char *langNames[] =
50 {
51     "En",  /* LANG_En */
52     "Es",  /* LANG_Es */
53     "De",  /* LANG_De */
54     "No",  /* LANG_No */
55     "Fr",  /* LANG_Fr */
56     "Fi",  /* LANG_Fi */
57     "Da",  /* LANG_Da */
58     "Cz",  /* LANG_Cz */
59     "Eo",  /* LANG_Eo */
60     "It",  /* LANG_It */
61     NULL
62 };
63
64 #define WINE_CLASS    "Wine"    /* Class name for resources */
65
66 typedef struct tagENVENTRY {
67   LPSTR                 Name;
68   LPSTR                 Value;
69   WORD                  wSize;
70   struct tagENVENTRY    *Prev;
71   struct tagENVENTRY    *Next;
72 } ENVENTRY, *LPENVENTRY;
73
74 LPENVENTRY      lpEnvList = NULL;
75
76 Display *display;
77 Screen *screen;
78 Window rootWindow;
79 int screenWidth = 0, screenHeight = 0;  /* Desktop window dimensions */
80 int screenDepth = 0;  /* Screen depth to use */
81 int desktopX = 0, desktopY = 0;  /* Desktop window position (if any) */
82
83 struct options Options =
84 {  /* default options */
85     NULL,           /* desktopGeometry */
86     NULL,           /* programName */
87     FALSE,          /* usePrivateMap */
88     FALSE,          /* useFixedMap */
89     FALSE,          /* synchronous */
90     FALSE,          /* backing store */
91     SW_SHOWNORMAL,  /* cmdShow */
92     FALSE,
93     FALSE,          /* AllowReadOnly */
94     MODE_ENHANCED,  /* Enhanced mode */
95     FALSE,          /* IPC enabled */
96 #ifdef DEFAULT_LANG
97     DEFAULT_LANG,   /* Default language */
98 #else
99     LANG_En,
100 #endif
101     FALSE           /* Managed windows */
102 };
103
104
105 static XrmOptionDescRec optionsTable[] =
106 {
107     { "-backingstore",  ".backingstore",    XrmoptionNoArg,  (caddr_t)"on" },
108     { "-desktop",       ".desktop",         XrmoptionSepArg, (caddr_t)NULL },
109     { "-depth",         ".depth",           XrmoptionSepArg, (caddr_t)NULL },
110     { "-display",       ".display",         XrmoptionSepArg, (caddr_t)NULL },
111     { "-iconic",        ".iconic",          XrmoptionNoArg,  (caddr_t)"on" },
112     { "-ipc",           ".ipc",             XrmoptionNoArg,  (caddr_t)"off"},
113     { "-language",      ".language",        XrmoptionSepArg, (caddr_t)"En" },
114     { "-name",          ".name",            XrmoptionSepArg, (caddr_t)NULL },
115     { "-privatemap",    ".privatemap",      XrmoptionNoArg,  (caddr_t)"on" },
116     { "-fixedmap",      ".fixedmap",        XrmoptionNoArg,  (caddr_t)NULL },
117     { "-synchronous",   ".synchronous",     XrmoptionNoArg,  (caddr_t)"on" },
118     { "-debug",         ".debug",           XrmoptionNoArg,  (caddr_t)"on" },
119     { "-debugmsg",      ".debugmsg",        XrmoptionSepArg, (caddr_t)NULL },
120     { "-dll",           ".dll",             XrmoptionSepArg, (caddr_t)NULL },
121     { "-allowreadonly", ".allowreadonly",   XrmoptionNoArg,  (caddr_t)"on" },
122     { "-mode",          ".mode",            XrmoptionSepArg, (caddr_t)NULL },
123     { "-managed",       ".managed",         XrmoptionNoArg,  (caddr_t)"off"}
124 };
125
126 #define NB_OPTIONS  (sizeof(optionsTable) / sizeof(optionsTable[0]))
127
128 #define USAGE \
129   "Usage:  %s [options] program_name [arguments]\n" \
130   "\n" \
131   "Options:\n" \
132   "    -allowreadonly  Read only files may be opened in write mode\n" \
133   "    -backingstore   Turn on backing store\n" \
134   "    -debug          Enter debugger before starting application\n" \
135   "    -debugmsg name  Turn debugging-messages on or off\n" \
136   "    -depth n        Change the depth to use for multiple-depth screens\n" \
137   "    -desktop geom   Use a desktop window of the given geometry\n" \
138   "    -display name   Use the specified display\n" \
139   "    -dll name       Enable or disable built-in DLLs\n" \
140   "    -fixedmap       Use a \"standard\" color map\n" \
141   "    -iconic         Start as an icon\n" \
142   "    -ipc            Enable IPC facilities\n" \
143   "    -language xx    Set the language (one of En,Es,De,No,Fr,Fi,Da,Cz,Eo,It)\n" \
144   "    -managed        Allow the window manager to manage created windows\n" \
145   "    -mode mode      Start Wine in a particular mode (standard or enhanced)\n" \
146   "    -name name      Set the application name\n" \
147   "    -privatemap     Use a private color map\n" \
148   "    -synchronous    Turn on synchronous display mode\n"
149
150
151
152 /***********************************************************************
153  *           MAIN_Usage
154  */
155 #ifndef WINELIB32
156 static void MAIN_Usage( char *name )
157 {
158     fprintf( stderr, USAGE, name );
159     exit(1);
160 }
161 #endif
162
163
164 /***********************************************************************
165  *           MAIN_GetProgramName
166  *
167  * Get the program name. The name is specified by (in order of precedence):
168  * - the option '-name'.
169  * - the environment variable 'WINE_NAME'.
170  * - the last component of argv[0].
171  */
172 static char *MAIN_GetProgramName( int argc, char *argv[] )
173 {
174     int i;
175     char *p;
176
177     for (i = 1; i < argc-1; i++)
178         if (!strcmp( argv[i], "-name" )) return argv[i+1];
179     if ((p = getenv( "WINE_NAME" )) != NULL) return p;
180     if ((p = strrchr( argv[0], '/' )) != NULL) return p+1;
181     return argv[0];
182 }
183
184
185 /***********************************************************************
186  *           MAIN_GetResource
187  *
188  * Fetch the value of resource 'name' using the correct instance name.
189  * 'name' must begin with '.' or '*'
190  */
191 static int MAIN_GetResource( XrmDatabase db, char *name, XrmValue *value )
192 {
193     char *buff_instance, *buff_class;
194     char *dummy;
195     int retval;
196
197     buff_instance = (char *)xmalloc(strlen(Options.programName)+strlen(name)+1);
198     buff_class    = (char *)xmalloc( strlen(WINE_CLASS) + strlen(name) + 1 );
199
200     strcpy( buff_instance, Options.programName );
201     strcat( buff_instance, name );
202     strcpy( buff_class, WINE_CLASS );
203     strcat( buff_class, name );
204     retval = XrmGetResource( db, buff_instance, buff_class, &dummy, value );
205     free( buff_instance );
206     free( buff_class );
207     return retval;
208 }
209
210
211 /***********************************************************************
212  *                    ParseDebugOptions
213  *
214  *  Turns specific debug messages on or off, according to "options".
215  *  Returns TRUE if parsing was successfull 
216  */
217 #ifdef DEBUG_RUNTIME
218
219 BOOL ParseDebugOptions(char *options)
220 {
221   int l;
222   if (strlen(options)<3)
223     return FALSE;
224   do
225   {
226     if ((*options!='+')&&(*options!='-'))
227       return FALSE;
228     if (strchr(options,','))
229       l=strchr(options,',')-options;
230     else
231       l=strlen(options);
232     if (!lstrncmpi(options+1,"all",l-1))
233       {
234         int i;
235         for (i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
236           debug_msg_enabled[i]=(*options=='+');
237       }
238     else
239       {
240         int i;
241         for (i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
242           if (debug_msg_name && (!lstrncmpi(options+1,debug_msg_name[i],l-1)))
243             {
244               debug_msg_enabled[i]=(*options=='+');
245               break;
246             }
247         if (i==sizeof(debug_msg_enabled)/sizeof(short))
248           return FALSE;
249       }
250     options+=l;
251   }
252   while((*options==',')&&(*(++options)));
253   if (*options)
254     return FALSE;
255   else
256     return TRUE;
257 }
258
259 #endif
260
261 #ifndef WINELIB
262 /***********************************************************************
263  *           MAIN_ParseDLLOptions
264  *
265  * Set runtime DLL usage flags
266  */
267 static BOOL MAIN_ParseDLLOptions(char *options)
268 {
269     int l;
270     BUILTIN_DLL *dll;
271
272     if (strlen(options)<3) return FALSE;
273     do
274     {
275         if ((*options!='+') && (*options!='-')) return FALSE;
276         if (strchr(options,',')) l=strchr(options,',')-options;
277         else l=strlen(options);
278         for (dll = dll_builtin_table; dll->name; dll++)
279         {
280             if (!lstrncmpi(options+1,dll->name,l-1))
281             {
282                 if (*options == '+') dll->flags &= ~DLL_FLAG_NOT_USED;
283                 else
284                 {
285                     if (dll->flags & DLL_FLAG_ALWAYS_USED) return FALSE;
286                     dll->flags |= DLL_FLAG_NOT_USED;
287                 }
288                 break;
289             }
290         }
291         if (!dll->name) return FALSE;
292         options+=l;
293     }
294     while((*options==',')&&(*(++options)));
295     if (*options)
296         return FALSE;
297     else
298         return TRUE;
299 }
300 #endif
301
302
303
304 /***********************************************************************
305  *           MAIN_ParseLanguageOption
306  *
307  * Parse -language option.
308  */
309 static void MAIN_ParseLanguageOption( char *arg )
310 {
311     const char **p = langNames;
312
313     Options.language = LANG_En;  /* First language */
314     for (p = langNames; *p; p++)
315     {
316         if (!lstrcmpi( *p, arg )) return;
317         Options.language++;
318     }
319     fprintf( stderr, "Invalid language specified '%s'. Supported languages are: ", arg );
320     for (p = langNames; *p; p++) fprintf( stderr, "%s ", *p );
321     fprintf( stderr, "\n" );
322     exit(1);
323 }
324
325
326 /***********************************************************************
327  *           MAIN_ParseModeOption
328  *
329  * Parse -mode option.
330  */
331 static void MAIN_ParseModeOption( char *arg )
332 {
333     if (!lstrcmpi("enhanced", arg)) Options.mode = MODE_ENHANCED;
334     else if (!lstrcmpi("standard", arg)) Options.mode = MODE_STANDARD;
335     else
336     {
337         fprintf(stderr, "Invalid mode '%s' specified.\n", arg);
338         fprintf(stderr, "Valid modes are: 'standard', 'enhanced' (default).\n");
339         exit(1);
340     }
341 }
342
343
344 /***********************************************************************
345  *           MAIN_ParseOptions
346  *
347  * Parse command line options and open display.
348  */
349 static void MAIN_ParseOptions( int *argc, char *argv[] )
350 {
351     char *display_name;
352     XrmValue value;
353     XrmDatabase db = XrmGetFileDatabase("/usr/lib/X11/app-defaults/Wine");
354
355       /* Parse command line */
356     Options.programName = MAIN_GetProgramName( *argc, argv );
357     XrmParseCommand( &db, optionsTable, NB_OPTIONS,
358                      Options.programName, argc, argv );
359
360 #ifdef WINELIB
361     /* Need to assemble command line and pass it to WinMain */
362 #else
363     if (*argc < 2 || lstrcmpi(argv[1], "-h") == 0) 
364         MAIN_Usage( argv[0] );
365 #endif
366
367       /* Open display */
368
369     if (MAIN_GetResource( db, ".display", &value )) display_name = value.addr;
370     else display_name = NULL;
371
372     if (!(display = XOpenDisplay( display_name )))
373     {
374         fprintf( stderr, "%s: Can't open display: %s\n",
375                  argv[0], display_name ? display_name : "(none specified)" );
376         exit(1);
377     }
378
379       /* Get all options */
380     if (MAIN_GetResource( db, ".iconic", &value ))
381         Options.cmdShow = SW_SHOWMINIMIZED;
382     if (MAIN_GetResource( db, ".privatemap", &value ))
383         Options.usePrivateMap = TRUE;
384     if (MAIN_GetResource( db, ".fixedmap", &value ))
385         Options.useFixedMap = TRUE;
386     if (MAIN_GetResource( db, ".synchronous", &value ))
387         Options.synchronous = TRUE;
388     if (MAIN_GetResource( db, ".backingstore", &value ))
389         Options.backingstore = TRUE;    
390     if (MAIN_GetResource( db, ".debug", &value ))
391         Options.debug = TRUE;
392     if (MAIN_GetResource( db, ".allowreadonly", &value ))
393         Options.allowReadOnly = TRUE;
394     if (MAIN_GetResource( db, ".ipc", &value ))
395         Options.ipc = TRUE;
396     if (MAIN_GetResource( db, ".depth", &value))
397         screenDepth = atoi( value.addr );
398     if (MAIN_GetResource( db, ".desktop", &value))
399         Options.desktopGeometry = value.addr;
400     if (MAIN_GetResource( db, ".language", &value))
401         MAIN_ParseLanguageOption( (char *)value.addr );
402     if (MAIN_GetResource( db, ".managed", &value))
403         Options.managed = TRUE;
404     if (MAIN_GetResource( db, ".mode", &value))
405         MAIN_ParseModeOption( (char *)value.addr );
406
407 #ifdef DEBUG_RUNTIME
408     if (MAIN_GetResource( db, ".debugoptions", &value))
409         ParseDebugOptions((char*)value.addr);
410 #endif
411     if (MAIN_GetResource( db, ".debugmsg", &value))
412       {
413 #ifndef DEBUG_RUNTIME
414         fprintf(stderr,"%s: Option \"-debugmsg\" not implemented.\n" \
415           "    Recompile with DEBUG_RUNTIME in include/stddebug.h defined.\n",
416           argv[0]);
417         exit(1);
418 #else
419         if (ParseDebugOptions((char*)value.addr)==FALSE)
420           {
421             int i;
422             fprintf(stderr,"%s: Syntax: -debugmsg +xxx,...  or -debugmsg -xxx,...\n",argv[0]);
423             fprintf(stderr,"Example: -debugmsg +all,-heap    turn on all messages except heap messages\n");
424             fprintf(stderr,"Available message types:\n");
425             fprintf(stderr,"%-9s ","all");
426             for(i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
427               if(debug_msg_name[i])
428                 fprintf(stderr,"%-9s%c",debug_msg_name[i],
429                         (((i+2)%8==0)?'\n':' '));
430             fprintf(stderr,"\n\n");
431             exit(1);
432           }
433 #endif
434       }
435
436       if(MAIN_GetResource( db, ".dll", &value))
437 #ifndef WINELIB
438        if(MAIN_ParseDLLOptions((char*)value.addr)==FALSE)
439        {
440          int i;
441          BUILTIN_DLL *dll;
442          fprintf(stderr,"%s: Syntax: -dll +xxx,... or -dll -xxx,...\n",argv[0]);
443          fprintf(stderr,"Example: -dll -ole2    Do not use emulated OLE2.DLL\n");
444          fprintf(stderr,"Available DLLs\n");
445          for (i = 0, dll = dll_builtin_table; dll->name; dll++)
446              if (!(dll->flags & DLL_FLAG_ALWAYS_USED))
447                  fprintf(stderr,"%-9s%c",dll->name, (((++i)%8==0)?'\n':' '));
448          fprintf(stderr,"\n\n");
449          exit(1);
450        }
451 #else
452                 fprintf(stderr,"-dll not supported in libwine\n");
453 #endif
454 }
455
456
457 /***********************************************************************
458  *           MAIN_CreateDesktop
459  */
460 static void MAIN_CreateDesktop( int argc, char *argv[] )
461 {
462     int flags;
463     unsigned int width = 640, height = 480;  /* Default size = 640x480 */
464     char *name = "Wine desktop";
465     XSizeHints *size_hints;
466     XWMHints   *wm_hints;
467     XClassHint *class_hints;
468     XSetWindowAttributes win_attr;
469     XTextProperty window_name;
470     Atom XA_WM_DELETE_WINDOW;
471
472     flags = XParseGeometry( Options.desktopGeometry,
473                             &desktopX, &desktopY, &width, &height );
474     screenWidth  = width;
475     screenHeight = height;
476
477       /* Create window */
478
479     win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
480                          PointerMotionMask | ButtonPressMask |
481                          ButtonReleaseMask | EnterWindowMask | 
482                          StructureNotifyMask;
483     win_attr.cursor = XCreateFontCursor( display, XC_top_left_arrow );
484
485     rootWindow = XCreateWindow( display, DefaultRootWindow(display),
486                                 desktopX, desktopY, width, height, 0,
487                                 CopyFromParent, InputOutput, CopyFromParent,
488                                 CWEventMask | CWCursor, &win_attr );
489
490       /* Set window manager properties */
491
492     size_hints  = XAllocSizeHints();
493     wm_hints    = XAllocWMHints();
494     class_hints = XAllocClassHint();
495     if (!size_hints || !wm_hints || !class_hints)
496     {
497         fprintf( stderr, "Not enough memory for window manager hints.\n" );
498         exit(1);
499     }
500     size_hints->min_width = size_hints->max_width = width;
501     size_hints->min_height = size_hints->max_height = height;
502     size_hints->flags = PMinSize | PMaxSize;
503     if (flags & (XValue | YValue)) size_hints->flags |= USPosition;
504     if (flags & (WidthValue | HeightValue)) size_hints->flags |= USSize;
505     else size_hints->flags |= PSize;
506
507     wm_hints->flags = InputHint | StateHint;
508     wm_hints->input = True;
509     wm_hints->initial_state = NormalState;
510     class_hints->res_name = argv[0];
511     class_hints->res_class = "Wine";
512
513     XStringListToTextProperty( &name, 1, &window_name );
514     XSetWMProperties( display, rootWindow, &window_name, &window_name,
515                       argv, argc, size_hints, wm_hints, class_hints );
516     XA_WM_DELETE_WINDOW = XInternAtom( display, "WM_DELETE_WINDOW", False );
517     XSetWMProtocols( display, rootWindow, &XA_WM_DELETE_WINDOW, 1 );
518     XFree( size_hints );
519     XFree( wm_hints );
520     XFree( class_hints );
521
522       /* Map window */
523
524     XMapWindow( display, rootWindow );
525 }
526
527
528 XKeyboardState keyboard_state;
529
530 /***********************************************************************
531  *           MAIN_SaveSetup
532  */
533 static void MAIN_SaveSetup(void)
534 {
535     XGetKeyboardControl(display, &keyboard_state);
536 }
537
538 /***********************************************************************
539  *           MAIN_RestoreSetup
540  */
541 static void MAIN_RestoreSetup(void)
542 {
543     XKeyboardControl keyboard_value;
544
545     keyboard_value.key_click_percent    = keyboard_state.key_click_percent;
546     keyboard_value.bell_percent         = keyboard_state.bell_percent;
547     keyboard_value.bell_pitch           = keyboard_state.bell_pitch;
548     keyboard_value.bell_duration        = keyboard_state.bell_duration;
549     keyboard_value.auto_repeat_mode     = keyboard_state.global_auto_repeat;
550
551     XChangeKeyboardControl(display, KBKeyClickPercent | KBBellPercent | 
552         KBBellPitch | KBBellDuration | KBAutoRepeatMode, &keyboard_value);
553 }
554
555
556 static void called_at_exit(void)
557 {
558     MAIN_RestoreSetup();
559     WSACleanup();
560 }
561
562 /***********************************************************************
563  *           main
564  */
565 #if defined(WINELIB) && defined(WINELIBDLL)
566 int _wine_main (int argc, char *argv[])
567 #else
568 int main( int argc, char *argv[] )
569 #endif
570 {    
571     int ret_val;
572     int depth_count, i;
573     int *depth_list;
574     struct timeval tv;
575
576     extern int _WinMain(int argc, char **argv);
577
578 #ifdef MALLOC_DEBUGGING
579     char *trace;
580
581     mcheck(NULL);
582     if (!(trace = getenv("MALLOC_TRACE")))
583     {       
584         fprintf( stderr, "MALLOC_TRACE not set. No trace generated\n" );
585     }
586     else
587     {
588         fprintf( stderr, "malloc trace goes to %s\n", trace );
589         mtrace();
590     }
591 #endif
592
593     setbuf(stdout,NULL);
594     setbuf(stderr,NULL);
595
596     setlocale(LC_CTYPE,"");
597     gettimeofday( &tv, NULL);
598     MSG_WineStartTicks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
599
600     XrmInitialize();
601     
602     MAIN_ParseOptions( &argc, argv );
603
604     SHELL_Init();
605     SHELL_LoadRegistry();
606
607     screen       = DefaultScreenOfDisplay( display );
608     screenWidth  = WidthOfScreen( screen );
609     screenHeight = HeightOfScreen( screen );
610     if (screenDepth)  /* -depth option specified */
611     {
612         depth_list = XListDepths(display,DefaultScreen(display),&depth_count);
613         for (i = 0; i < depth_count; i++)
614             if (depth_list[i] == screenDepth) break;
615         XFree( depth_list );
616         if (i >= depth_count)
617         {
618             fprintf( stderr, "%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) XSynchronize( 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
631     ret_val = _WinMain( argc, argv );
632
633     return ret_val;
634 }
635
636 /***********************************************************************
637  *           MessageBeep    (USER.104)
638  */
639 void MessageBeep(WORD i)
640 {
641         XBell(display, 100);
642 }
643
644 /***********************************************************************
645  *      GetVersion (KERNEL.3)
646  */
647 LONG GetVersion(void)
648 {
649     return MAKELONG( WINVERSION, WINDOSVER );
650 }
651
652 /***********************************************************************
653  *      GetWinFlags (KERNEL.132)
654  */
655 LONG GetWinFlags(void)
656 {
657   static const long cpuflags[5] =
658     { WF_CPU086, WF_CPU186, WF_CPU286, WF_CPU386, WF_CPU486 };
659
660   long result = 0;
661
662   /* There doesn't seem to be any Pentium flag.  */
663 #ifndef WINELIB
664   long cpuflag = cpuflags[MIN (runtime_cpu (), 4)];
665 #else
666   long cpuflag = cpuflags[4];
667 #endif
668
669   switch(Options.mode) {
670   case MODE_STANDARD:
671     result = (WF_STANDARD | cpuflag | WF_PMODE | WF_80x87);
672     break;
673
674   case MODE_ENHANCED:
675     result = (WF_ENHANCED | cpuflag | WF_PMODE | WF_80x87 | WF_PAGING);
676     break;
677
678   default:
679     fprintf(stderr, "Unknown mode set? This shouldn't happen. Check GetWinFlags()!\n");
680     break;
681   }
682
683   return result;
684 }
685
686 /***********************************************************************
687  *      SetEnvironment (GDI.132)
688  */
689 int SetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nCount)
690 {
691     LPENVENTRY  lpNewEnv;
692     LPENVENTRY  lpEnv = lpEnvList;
693     dprintf_env(stddeb, "SetEnvironment('%s', '%s', %d) !\n", 
694                 lpPortName, lpEnviron, nCount);
695     if (lpPortName == NULL) return -1;
696     while (lpEnv != NULL) {
697         if (lpEnv->Name != NULL && strcmp(lpEnv->Name, lpPortName) == 0) {
698             if (nCount == 0 || lpEnviron == NULL) {
699                 if (lpEnv->Prev != NULL) lpEnv->Prev->Next = lpEnv->Next;
700                 if (lpEnv->Next != NULL) lpEnv->Next->Prev = lpEnv->Prev;
701                 free(lpEnv->Value);
702                 free(lpEnv->Name);
703                 free(lpEnv);
704                 dprintf_env(stddeb, "SetEnvironment() // entry deleted !\n");
705                 return -1;
706             }
707             free(lpEnv->Value);
708             lpEnv->Value = malloc(nCount);
709             if (lpEnv->Value == NULL) {
710                 dprintf_env(stddeb, "SetEnvironment() // Error allocating entry value !\n");
711                 return 0;
712             }
713             memcpy(lpEnv->Value, lpEnviron, nCount);
714             lpEnv->wSize = nCount;
715             dprintf_env(stddeb, "SetEnvironment() // entry modified !\n");
716             return nCount;
717         }
718         if (lpEnv->Next == NULL) break;
719         lpEnv = lpEnv->Next;
720     }
721     if (nCount == 0 || lpEnviron == NULL) return -1;
722     dprintf_env(stddeb, "SetEnvironment() // new entry !\n");
723     lpNewEnv = malloc(sizeof(ENVENTRY));
724     if (lpNewEnv == NULL) {
725         dprintf_env(stddeb, "SetEnvironment() // Error allocating new entry !\n");
726         return 0;
727     }
728     if (lpEnvList == NULL) {
729         lpEnvList = lpNewEnv;
730         lpNewEnv->Prev = NULL;
731     }
732     else 
733     {
734         lpEnv->Next = lpNewEnv;
735         lpNewEnv->Prev = lpEnv;
736     }
737     lpNewEnv->Next = NULL;
738     lpNewEnv->Name = malloc(strlen(lpPortName) + 1);
739     if (lpNewEnv->Name == NULL) {
740         dprintf_env(stddeb, "SetEnvironment() // Error allocating entry name !\n");
741         return 0;
742     }
743     strcpy(lpNewEnv->Name, lpPortName);
744     lpNewEnv->Value = malloc(nCount);
745     if (lpNewEnv->Value == NULL) {
746         dprintf_env(stddeb, "SetEnvironment() // Error allocating entry value !\n");
747         return 0;
748     }
749     memcpy(lpNewEnv->Value, lpEnviron, nCount);
750     lpNewEnv->wSize = nCount;
751     return nCount;
752 }
753
754 /***********************************************************************
755  *      SetEnvironmentVariableA (KERNEL32.484)
756  */
757 BOOL SetEnvironmentVariableA(LPSTR lpName, LPSTR lpValue)
758 {
759     int rc;
760
761     rc = SetEnvironment(lpName, lpValue, strlen(lpValue) + 1);
762     return (rc > 0) ? 1 : 0;
763 }
764
765 /***********************************************************************
766  *      GetEnvironment (GDI.134)
767  */
768 int GetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nMaxSiz)
769 {
770     WORD       nCount;
771     LPENVENTRY lpEnv = lpEnvList;
772     dprintf_env(stddeb, "GetEnvironment('%s', '%s', %d) !\n",
773                 lpPortName, lpEnviron, nMaxSiz);
774     while (lpEnv != NULL) {
775         if (lpEnv->Name != NULL && strcmp(lpEnv->Name, lpPortName) == 0) {
776             nCount = MIN(nMaxSiz, lpEnv->wSize);
777             memcpy(lpEnviron, lpEnv->Value, nCount);
778             dprintf_env(stddeb, "GetEnvironment() // found '%s' !\n", lpEnviron);
779             return nCount;
780         }
781         lpEnv = lpEnv->Next;
782     }
783     dprintf_env(stddeb, "GetEnvironment() // not found !\n");
784     return 0;
785 }
786
787 /***********************************************************************
788  *      GetEnvironmentVariableA (KERNEL32.213)
789  */
790 DWORD GetEnvironmentVariableA(LPSTR lpName, LPSTR lpValue, DWORD size)
791 {
792     return GetEnvironment(lpName, lpValue, size);
793 }
794
795 /***********************************************************************
796  *      GetEnvironmentStrings (KERNEL32.210)
797  */
798 LPVOID GetEnvironmentStrings(void)
799 {
800     int count;
801     LPENVENTRY lpEnv;
802     char *envtable, *envptr;
803
804     /* Count the total number of bytes we'll need for the string
805      * table.  Include the trailing nuls and the final double nul.
806      */
807     count = 1;
808     lpEnv = lpEnvList;
809     while(lpEnv != NULL)
810     {
811         if(lpEnv->Name != NULL)
812         {
813             count += strlen(lpEnv->Name) + 1;
814             count += strlen(lpEnv->Value) + 1;
815         }
816         lpEnv = lpEnv->Next;
817     }
818
819     envtable = malloc(count);
820     if(envtable)
821     {
822         lpEnv = lpEnvList;
823         envptr = envtable;
824
825         while(lpEnv != NULL)
826         {
827             if(lpEnv->Name != NULL)
828             {
829                 count = sprintf(envptr, "%s=%s", lpEnv->Name, lpEnv->Value);
830                 envptr += count + 1;
831             }
832             lpEnv = lpEnv->Next;
833         }
834         *envptr = '\0';
835     }
836
837     return envtable;
838 }
839
840
841 LPVOID GetEnvironmentStringsW(void)
842 {
843     int count,len;
844     LPENVENTRY lpEnv;
845     char *envtable, *envptr;
846         WCHAR *wenvtable;
847
848     /* Count the total number of bytes we'll need for the string
849      * table.  Include the trailing nuls and the final double nul.
850      */
851     count = 1;
852     lpEnv = lpEnvList;
853     while(lpEnv != NULL)
854     {
855         if(lpEnv->Name != NULL)
856         {
857             count += strlen(lpEnv->Name) + 1;
858             count += strlen(lpEnv->Value) + 1;
859         }
860         lpEnv = lpEnv->Next;
861     }
862
863         len=count;
864     envtable = malloc(count);
865     if(envtable)
866     {
867         lpEnv = lpEnvList;
868         envptr = envtable;
869
870         while(lpEnv != NULL)
871         {
872             if(lpEnv->Name != NULL)
873             {
874                 count = sprintf(envptr, "%s=%s", lpEnv->Name, lpEnv->Value);
875                 envptr += count + 1;
876             }
877             lpEnv = lpEnv->Next;
878         }
879         *envptr = '\0';
880     }
881
882         wenvtable = malloc(2*len);
883         for(count=0;count<len;count++)
884                 wenvtable[count]=(WCHAR)envtable[count];
885         free(envtable);
886
887     return envtable;
888 }
889
890 void FreeEnvironmentStringsA(void *e)
891 {
892         free(e);
893 }
894
895 void FreeEnvironmentStringsW(void* e)
896 {
897         free(e);
898 }
899
900 /***********************************************************************
901  *      GetTimerResolution (USER.14)
902  */
903 LONG GetTimerResolution(void)
904 {
905         return (1000);
906 }
907
908 /***********************************************************************
909  *      SystemParametersInfo (USER.483)
910  */
911 BOOL SystemParametersInfo (UINT uAction, UINT uParam, LPVOID lpvParam, UINT fuWinIni)
912 {
913         int timeout, temp;
914         char buffer[256];
915         XKeyboardState          keyboard_state;
916         XKeyboardControl        keyboard_value;
917
918
919         fprintf(stderr, "SystemParametersInfo: action %d, param %x, flag %x\n", 
920                         uAction, uParam, fuWinIni);
921
922         switch (uAction) {
923                 case SPI_GETBEEP:
924                         XGetKeyboardControl(display, &keyboard_state);
925                         if (keyboard_state.bell_percent == 0)
926                                 *(BOOL *) lpvParam = FALSE;
927                         else
928                                 *(BOOL *) lpvParam = TRUE;
929                         break;
930                 
931                 case SPI_GETBORDER:
932                         *(INT *) lpvParam = 1;
933                         break;
934
935                 case SPI_GETFASTTASKSWITCH:
936                         *(BOOL *) lpvParam = FALSE;
937                         break;
938
939                 case SPI_GETGRIDGRANULARITY:
940                         *(INT *) lpvParam = 1;
941                         break;
942
943                 case SPI_GETICONTITLEWRAP:
944                         *(BOOL *) lpvParam = FALSE;
945                         break;
946
947                 case SPI_GETKEYBOARDDELAY:
948                         *(INT *) lpvParam = 1;
949                         break;
950
951                 case SPI_GETKEYBOARDSPEED:
952                         *(WORD *) lpvParam = 30;
953                         break;
954
955                 case SPI_GETMENUDROPALIGNMENT:
956                         *(BOOL *) lpvParam = FALSE;
957                         break;
958
959                 case SPI_GETSCREENSAVEACTIVE:
960                         *(BOOL *) lpvParam = FALSE;
961                         break;
962
963                 case SPI_GETSCREENSAVETIMEOUT:
964                         XGetScreenSaver(display, &timeout, &temp,&temp,&temp);
965                         *(INT *) lpvParam = timeout * 1000;
966                         break;
967
968                 case SPI_ICONHORIZONTALSPACING:
969                         if (lpvParam == NULL)
970                                 fprintf(stderr, "SystemParametersInfo: Horizontal icon spacing set to %d\n.", uParam);
971                         else
972                                 *(INT *) lpvParam = 50;
973                         break;
974
975                 case SPI_ICONVERTICALSPACING:
976                         if (lpvParam == NULL)
977                                 fprintf(stderr, "SystemParametersInfo: Vertical icon spacing set to %d\n.", uParam);
978                         else
979                                 *(INT *) lpvParam = 50;
980                         break;
981
982                 case SPI_SETBEEP:
983                         if (uParam == TRUE)
984                                 keyboard_value.bell_percent = -1;
985                         else
986                                 keyboard_value.bell_percent = 0;                        
987                         XChangeKeyboardControl(display, KBBellPercent, 
988                                                         &keyboard_value);
989                         break;
990
991                 case SPI_SETSCREENSAVEACTIVE:
992                         if (uParam == TRUE)
993                                 XActivateScreenSaver(display);
994                         else
995                                 XResetScreenSaver(display);
996                         break;
997
998                 case SPI_SETSCREENSAVETIMEOUT:
999                         XSetScreenSaver(display, uParam, 60, DefaultBlanking, 
1000                                                 DefaultExposures);
1001                         break;
1002
1003                 case SPI_SETDESKWALLPAPER:
1004                         return (SetDeskWallPaper((LPSTR) lpvParam));
1005                         break;
1006
1007                 case SPI_SETDESKPATTERN:
1008                         if ((INT) uParam == -1) {
1009                                 GetProfileString("Desktop", "Pattern", 
1010                                                 "170 85 170 85 170 85 170 85", 
1011                                                 buffer, sizeof(buffer) );
1012                                 return (DESKTOP_SetPattern((LPSTR) buffer));
1013                         } else
1014                                 return (DESKTOP_SetPattern((LPSTR) lpvParam));
1015                         break;
1016
1017                 case SPI_GETICONTITLELOGFONT: 
1018                 {
1019                   LPLOGFONT lpLogFont = (LPLOGFONT)lpvParam;
1020                   lpLogFont->lfHeight = 10;
1021                   lpLogFont->lfWidth = 0;
1022                   lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
1023                   lpLogFont->lfWeight = FW_NORMAL;
1024                   lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
1025                   lpLogFont->lfCharSet = ANSI_CHARSET;
1026                   lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1027                   lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1028                   lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
1029                   break;
1030                 }
1031                 case SPI_LANGDRIVER:
1032                 case SPI_SETBORDER:
1033                 case SPI_SETDOUBLECLKHEIGHT:
1034                 case SPI_SETDOUBLECLICKTIME:
1035                 case SPI_SETDOUBLECLKWIDTH:
1036                 case SPI_SETFASTTASKSWITCH:
1037                 case SPI_SETKEYBOARDDELAY:
1038                 case SPI_SETKEYBOARDSPEED:
1039                         fprintf(stderr, "SystemParametersInfo: option %d ignored.\n", uParam);
1040                         break;
1041
1042                 default:
1043                         fprintf(stderr, "SystemParametersInfo: unknown option %d.\n", uParam);
1044                         break;
1045         }
1046         return 1;
1047 }
1048
1049 /***********************************************************************
1050 *       HMEMCPY (KERNEL.348)
1051 */
1052 void hmemcpy(LPVOID hpvDest, LPCVOID hpvSource, LONG cbCopy)
1053 {
1054         memcpy(hpvDest, hpvSource, cbCopy);
1055 }
1056
1057 /***********************************************************************
1058 *       COPY (GDI.250)
1059 */
1060 void Copy(LPVOID lpSource, LPVOID lpDest, WORD nBytes)
1061 {
1062         memcpy(lpDest, lpSource, nBytes);
1063 }
1064
1065 /***********************************************************************
1066 *       SWAPMOUSEBUTTON (USER.186)
1067 */
1068 BOOL SwapMouseButton(BOOL fSwap)
1069 {
1070         return 0;       /* don't swap */
1071 }
1072
1073 /***********************************************************************
1074 *       FileCDR (KERNEL.130)
1075 */
1076 void FileCDR(FARPROC x)
1077 {
1078         printf("FileCDR(%8x)\n", (int) x);
1079 }
1080
1081 /***********************************************************************
1082 *       GetWinDebugInfo (KERNEL.355)
1083 */
1084 BOOL GetWinDebugInfo(WINDEBUGINFO FAR* lpwdi, UINT flags)
1085 {
1086         printf("GetWinDebugInfo(%8lx,%d) stub returning 0\n", (unsigned long)lpwdi, flags);
1087         /* 0 means not in debugging mode/version */
1088         /* Can this type of debugging be used in wine ? */
1089         /* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */
1090         return 0;
1091 }
1092
1093 /***********************************************************************
1094 *       GetWinDebugInfo (KERNEL.355)
1095 */
1096 BOOL SetWinDebugInfo(WINDEBUGINFO FAR* lpwdi)
1097 {
1098         printf("SetWinDebugInfo(%8lx) stub returning 0\n", (unsigned long)lpwdi);
1099         /* 0 means not in debugging mode/version */
1100         /* Can this type of debugging be used in wine ? */
1101         /* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */
1102         return 0;
1103 }