The right (source) data directory should now be found whether you use libtool to...
[supertux.git] / lib / app / setup.cpp
1 //  $Id$
2 //
3 //  SuperTux -  A Jump'n Run
4 //  Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #include <cassert>
21 #include <cstdio>
22 #include <iostream>
23 #include <cstdio>
24 #include <cstdlib>
25 #include <cstring>
26 #include <cerrno>
27 #include <unistd.h>
28
29 #include "SDL.h"
30 #include "SDL_image.h"
31 #ifndef NOOPENGL
32 #include "SDL_opengl.h"
33 #endif
34
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 #include <dirent.h>
38 #ifndef WIN32
39 #include <libgen.h>
40 #endif
41
42 #include <cctype>
43
44 #include "../app/globals.h"
45 #include "../app/setup.h"
46 #include "../video/screen.h"
47 #include "../video/surface.h"
48 #include "../gui/menu.h"
49 #include "../utils/configfile.h"
50 #include "../audio/sound_manager.h"
51 #include "../app/gettext.h"
52
53 using namespace SuperTux;
54
55 #ifdef WIN32
56 #define mkdir(dir, mode)    mkdir(dir)
57 // on win32 we typically don't want LFS paths
58 #undef DATA_PREFIX
59 #define DATA_PREFIX "./data/"
60 #endif
61
62 /* Local function prototypes: */
63
64 void seticon(void);
65 void usage(char * prog, int ret);
66
67 /* Does the given file exist and is it accessible? */
68 int FileSystem::faccessible(const std::string& filename)
69 {
70   struct stat filestat;
71   if (stat(filename.c_str(), &filestat) == -1)
72     {
73       return false;
74     }
75   else
76     {
77       if(S_ISREG(filestat.st_mode))
78         return true;
79       else
80         return false;
81     }
82 }
83
84 /* Can we write to this location? */
85 int FileSystem::fwriteable(const std::string& filename)
86 {
87   FILE* fi;
88   fi = fopen(filename.c_str(), "wa");
89   if (fi == NULL)
90     {
91       return false;
92     }
93   return true;
94 }
95
96 /* Makes sure a directory is created in either the SuperTux home directory or the SuperTux base directory.*/
97 int FileSystem::fcreatedir(const std::string& relative_dir)
98 {
99   std::string path = st_dir + "/" + relative_dir + "/";
100   if(mkdir(path.c_str(),0755) != 0)
101     {
102       path = datadir + "/" + relative_dir + "/";
103       if(mkdir(path.c_str(),0755) != 0)
104         {
105           return false;
106         }
107       else
108         {
109           return true;
110         }
111     }
112   else
113     {
114       return true;
115     }
116 }
117
118 /* Get all names of sub-directories in a certain directory. */
119 /* Returns the number of sub-directories found. */
120 /* Note: The user has to free the allocated space. */
121 std::set<std::string> FileSystem::dsubdirs(const std::string &rel_path,const  std::string& expected_file)
122 {
123   DIR *dirStructP;
124   struct dirent *direntp;
125   std::set<std::string> sdirs;
126   std::string filename;
127   std::string path = st_dir + "/" + rel_path;
128
129   if((dirStructP = opendir(path.c_str())) != NULL)
130     {
131       while((direntp = readdir(dirStructP)) != NULL)
132         {
133           std::string absolute_filename;
134           struct stat buf;
135
136           absolute_filename = path + "/" + direntp->d_name;
137
138           if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
139             {
140               if(!expected_file.empty())
141                 {
142                   filename = path + "/" + direntp->d_name + "/" + expected_file;
143                   if(!faccessible(filename))
144                     continue;
145                 }
146
147               sdirs.insert(direntp->d_name);
148             }
149         }
150       closedir(dirStructP);
151     }
152
153   path = datadir + "/" + rel_path;
154   if((dirStructP = opendir(path.c_str())) != NULL)
155     {
156       while((direntp = readdir(dirStructP)) != NULL)
157         {
158           std::string absolute_filename;
159           struct stat buf;
160
161           absolute_filename = path + "/" + direntp->d_name;
162
163           if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
164             {
165               if(!expected_file.empty())
166                 {
167                   filename = path + "/" + direntp->d_name + "/" + expected_file;
168                   if(!faccessible(filename.c_str()))
169                     {
170                       continue;
171                     }
172                   else
173                     {
174                       filename = st_dir + "/" + rel_path + "/" + direntp->d_name + "/" + expected_file;
175                       if(faccessible(filename.c_str()))
176                         continue;
177                     }
178                 }
179
180               sdirs.insert(direntp->d_name);
181             }
182         }
183       closedir(dirStructP);
184     }
185
186   return sdirs;
187 }
188
189 std::set<std::string> FileSystem::dfiles(const std::string& rel_path, const  std::string& glob, const  std::string& exception_str)
190 {
191   DIR *dirStructP;
192   struct dirent *direntp;
193   std::set<std::string> sdirs;
194   std::string path = st_dir + "/" + rel_path;
195
196   if((dirStructP = opendir(path.c_str())) != NULL)
197     {
198       while((direntp = readdir(dirStructP)) != NULL)
199         {
200           std::string absolute_filename;
201           struct stat buf;
202
203           absolute_filename = path + "/" + direntp->d_name;
204
205           if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
206             {
207               if(!exception_str.empty())
208                 {
209                   if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
210                     continue;
211                 }
212               if(!glob.empty())
213                 if(strstr(direntp->d_name,glob.c_str()) == NULL)
214                   continue;
215
216               sdirs.insert(direntp->d_name);
217             }
218         }
219       closedir(dirStructP);
220     }
221
222   path = datadir + "/" + rel_path;
223   if((dirStructP = opendir(path.c_str())) != NULL)
224     {
225       while((direntp = readdir(dirStructP)) != NULL)
226         {
227           std::string absolute_filename;
228           struct stat buf;
229
230           absolute_filename = path + "/" + direntp->d_name;
231
232           if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
233             {
234               if(!exception_str.empty())
235                 {
236                   if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
237                     continue;
238                 }
239               if(!glob.empty())
240                 if(strstr(direntp->d_name,glob.c_str()) == NULL)
241                   continue;
242
243               sdirs.insert(direntp->d_name);
244             }
245         }
246       closedir(dirStructP);
247     }
248
249   return sdirs;
250 }
251
252 void Setup::info(const std::string& _package_name, const std::string& _package_symbol_name, const std::string& _package_version)
253 {
254 package_name = _package_name;
255 package_symbol_name = _package_symbol_name;
256 package_version = _package_version;
257 }
258
259 /* --- SETUP --- */
260 /* Set SuperTux configuration and save directories */
261 void Setup::directories(void)
262 {
263   std::string home;
264   /* Get home directory (from $HOME variable)... if we can't determine it,
265      use the current directory ("."): */
266   if (getenv("HOME") != NULL)
267     home = getenv("HOME");
268   else
269     home = ".";
270
271   st_dir = home + "/." + package_symbol_name;
272
273   /* Remove .supertux config-file from old SuperTux versions */
274   if(FileSystem::faccessible(st_dir))
275     {
276       remove(st_dir.c_str());
277     }
278
279   st_save_dir = st_dir + "/save";
280
281   /* Create them. In the case they exist they won't destroy anything. */
282   mkdir(st_dir.c_str(), 0755);
283   mkdir(st_save_dir.c_str(), 0755);
284
285   mkdir((st_dir + "/levels").c_str(), 0755);
286
287   // User has not that a datadir, so we try some magic
288   if (datadir.empty())
289     {
290 #ifndef WIN32
291       // Detect datadir
292       char exe_file[PATH_MAX];
293       if (readlink("/proc/self/exe", exe_file, PATH_MAX) < 0)
294         {
295           puts("Couldn't read /proc/self/exe, using default path: " DATA_PREFIX);
296           datadir = DATA_PREFIX;
297         }
298       else
299         {
300           std::string exedir = std::string(dirname(exe_file)) + "/";
301           
302           datadir = exedir + "../data"; // SuperTux run from source dir
303           if (access(datadir.c_str(), F_OK) != 0)
304             {
305               datadir = exedir + "../../data";  //SuperTux run from source dir (with libtool script)
306               
307               if (access(datadir.c_str(), F_OK) != 0)
308               {
309               datadir = exedir + "../share/" + package_symbol_name; // SuperTux run from PATH
310               if (access(datadir.c_str(), F_OK) != 0) 
311                 { // If all fails, fall back to compiled path
312                   datadir = DATA_PREFIX; 
313                 }
314               }
315             }
316         }
317 #else
318   datadir = DATA_PREFIX;
319 #endif
320     }
321   printf("Datadir: %s\n", datadir.c_str());
322 }
323
324 void Setup::general(void)
325 {
326   /* Seed random number generator: */
327
328   srand(SDL_GetTicks());
329
330   /* Set icon image: */
331
332   seticon();
333
334   /* Unicode needed for input handling: */
335
336   SDL_EnableUNICODE(1);
337
338   /* Load GUI/menu images: */
339   checkbox = new Surface(datadir + "/images/status/checkbox.png", true);
340   checkbox_checked = new Surface(datadir + "/images/status/checkbox-checked.png", true);
341   back = new Surface(datadir + "/images/status/back.png", true);
342   arrow_left = new Surface(datadir + "/images/icons/left.png", true);
343   arrow_right = new Surface(datadir + "/images/icons/right.png", true);
344
345   /* Load the mouse-cursor */
346   mouse_cursor = new MouseCursor( datadir + "/images/status/mousecursor.png",1);
347   MouseCursor::set_current(mouse_cursor);
348   
349 }
350
351 void Setup::general_free(void)
352 {
353
354   /* Free GUI/menu images: */
355   delete checkbox;
356   delete checkbox_checked;
357   delete back;
358   delete arrow_left;
359   delete arrow_right;
360
361   /* Free mouse-cursor */
362   delete mouse_cursor;
363   
364 }
365
366 void Setup::video(unsigned int screen_w, unsigned int screen_h)
367 {
368   /* Init SDL Video: */
369   if (SDL_Init(SDL_INIT_VIDEO) < 0)
370     {
371       fprintf(stderr,
372               "\nError: I could not initialize video!\n"
373               "The Simple DirectMedia error that occured was:\n"
374               "%s\n\n", SDL_GetError());
375       exit(1);
376     }
377
378   /* Open display: */
379   if(use_gl)
380     video_gl(screen_w, screen_h);
381   else
382     video_sdl(screen_w, screen_h);
383
384   Surface::reload_all();
385
386   /* Set window manager stuff: */
387   SDL_WM_SetCaption((package_name + " " + package_version).c_str(), package_name.c_str());
388 }
389
390 void Setup::video_sdl(unsigned int screen_w, unsigned int screen_h)
391 {
392   if (use_fullscreen)
393     {
394       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_FULLSCREEN ) ; /* | SDL_HWSURFACE); */
395       if (screen == NULL)
396         {
397           fprintf(stderr,
398                   "\nWarning: I could not set up fullscreen video for "
399                   "800x600 mode.\n"
400                   "The Simple DirectMedia error that occured was:\n"
401                   "%s\n\n", SDL_GetError());
402           use_fullscreen = false;
403         }
404     }
405   else
406     {
407       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_HWSURFACE | SDL_DOUBLEBUF );
408
409       if (screen == NULL)
410         {
411           fprintf(stderr,
412                   "\nError: I could not set up video for 800x600 mode.\n"
413                   "The Simple DirectMedia error that occured was:\n"
414                   "%s\n\n", SDL_GetError());
415           exit(1);
416         }
417     }
418 }
419
420 void Setup::video_gl(unsigned int screen_w, unsigned int screen_h)
421 {
422 #ifndef NOOPENGL
423
424   SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
425   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
426   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
427   SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
428   SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
429
430   if (use_fullscreen)
431     {
432       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_FULLSCREEN | SDL_OPENGL) ; /* | SDL_HWSURFACE); */
433       if (screen == NULL)
434         {
435           fprintf(stderr,
436                   "\nWarning: I could not set up fullscreen video for "
437                   "640x480 mode.\n"
438                   "The Simple DirectMedia error that occured was:\n"
439                   "%s\n\n", SDL_GetError());
440           use_fullscreen = false;
441         }
442     }
443   else
444     {
445       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_OPENGL);
446
447       if (screen == NULL)
448         {
449           fprintf(stderr,
450                   "\nError: I could not set up video for 640x480 mode.\n"
451                   "The Simple DirectMedia error that occured was:\n"
452                   "%s\n\n", SDL_GetError());
453           exit(1);
454         }
455     }
456
457   /*
458    * Set up OpenGL for 2D rendering.
459    */
460   glDisable(GL_DEPTH_TEST);
461   glDisable(GL_CULL_FACE);
462
463   glViewport(0, 0, screen->w, screen->h);
464   glMatrixMode(GL_PROJECTION);
465   glLoadIdentity();
466   glOrtho(0, screen->w, screen->h, 0, -1.0, 1.0);
467
468   glMatrixMode(GL_MODELVIEW);
469   glLoadIdentity();
470   glTranslatef(0.0f, 0.0f, 0.0f);
471
472 #endif
473
474 }
475
476 void Setup::joystick(void)
477 {
478
479   /* Init Joystick: */
480
481   use_joystick = true;
482
483   if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
484     {
485       fprintf(stderr, "Warning: I could not initialize joystick!\n"
486               "The Simple DirectMedia error that occured was:\n"
487               "%s\n\n", SDL_GetError());
488
489       use_joystick = false;
490     }
491   else
492     {
493       /* Open joystick: */
494       if (SDL_NumJoysticks() <= 0)
495         {
496           fprintf(stderr, "Info: No joysticks were found.\n");
497
498           use_joystick = false;
499         }
500       else
501         {
502           js = SDL_JoystickOpen(joystick_num);
503
504           if (js == NULL)
505             {
506               fprintf(stderr, "Warning: Could not open joystick %d.\n"
507                       "The Simple DirectMedia error that occured was:\n"
508                       "%s\n\n", joystick_num, SDL_GetError());
509
510               use_joystick = false;
511             }
512           else
513             {
514               if (SDL_JoystickNumAxes(js) < 2)
515                 {
516                   fprintf(stderr,
517                           "Warning: Joystick does not have enough axes!\n");
518
519                   use_joystick = false;
520                 }
521               else
522                 {
523                   if (SDL_JoystickNumButtons(js) < 2)
524                     {
525                       fprintf(stderr,
526                               "Warning: "
527                               "Joystick does not have enough buttons!\n");
528
529                       use_joystick = false;
530                     }
531                 }
532             }
533         }
534     }
535 }
536
537 void Setup::audio(void)
538 {
539
540   /* Init SDL Audio silently even if --disable-sound : */
541
542   if (SoundManager::get()->audio_device_available())
543     {
544       if (SDL_Init(SDL_INIT_AUDIO) < 0)
545         {
546           /* only print out message if sound or music
547              was not disabled at command-line
548            */
549           if (SoundManager::get()->sound_enabled() || SoundManager::get()->music_enabled())
550             {
551               fprintf(stderr,
552                       "\nWarning: I could not initialize audio!\n"
553                       "The Simple DirectMedia error that occured was:\n"
554                       "%s\n\n", SDL_GetError());
555             }
556           /* keep the programming logic the same :-)
557              because in this case, use_sound & use_music' values are ignored
558              when there's no available audio device
559           */
560           SoundManager::get()->enable_sound(false);
561           SoundManager::get()->enable_music(false);
562           SoundManager::get()->set_audio_device_available(false);
563         }
564     }
565
566
567   /* Open sound silently regarless the value of "use_sound": */
568
569   if (SoundManager::get()->audio_device_available())
570     {
571       if (SoundManager::get()->open_audio(44100, AUDIO_S16, 2, 2048) < 0)
572         {
573           /* only print out message if sound or music
574              was not disabled at command-line
575            */
576           if (SoundManager::get()->sound_enabled() || SoundManager::get()->music_enabled())
577             {
578               fprintf(stderr,
579                       "\nWarning: I could not set up audio for 44100 Hz "
580                       "16-bit stereo.\n"
581                       "The Simple DirectMedia error that occured was:\n"
582                       "%s\n\n", SDL_GetError());
583             }
584           SoundManager::get()->enable_sound(false);
585           SoundManager::get()->enable_music(false);
586           SoundManager::get()->set_audio_device_available(false);
587         }
588     }
589
590 }
591
592
593 /* --- SHUTDOWN --- */
594
595 void Termination::shutdown(void)
596 {
597   config->save();
598   SoundManager::get()->close_audio();
599   SDL_Quit();
600 }
601
602 /* --- ABORT! --- */
603
604 void Termination::abort(const std::string& reason, const std::string& details)
605 {
606   fprintf(stderr, "\nError: %s\n%s\n\n", reason.c_str(), details.c_str());
607   shutdown();
608   ::abort();
609 }
610
611 /* Set Icon (private) */
612
613 void seticon(void)
614 {
615 //  int masklen;
616 //  Uint8 * mask;
617   SDL_Surface * icon;
618
619
620   /* Load icon into a surface: */
621
622   icon = IMG_Load((datadir + "/images/" + package_symbol_name + ".xpm").c_str());
623   if (icon == NULL)
624     {
625       fprintf(stderr,
626               "\nError: I could not load the icon image: %s%s\n"
627               "The Simple DirectMedia error that occured was:\n"
628               "%s\n\n", datadir.c_str(), ("/images/" + package_symbol_name + ".xpm").c_str(), SDL_GetError());
629       exit(1);
630     }
631
632
633   /* Create mask: */
634 /*
635   masklen = (((icon -> w) + 7) / 8) * (icon -> h);
636   mask = (Uint8*) malloc(masklen * sizeof(Uint8));
637   memset(mask, 0xFF, masklen);
638 */
639
640   /* Set icon: */
641
642   SDL_WM_SetIcon(icon, NULL);//mask);
643
644
645   /* Free icon surface & mask: */
646
647 //  free(mask);
648   SDL_FreeSurface(icon);
649 }
650
651
652 /* Parse command-line arguments: */
653
654 void Setup::parseargs(int argc, char * argv[])
655 {
656   int i;
657
658   config->load();
659
660   /* Parse arguments: */
661
662   for (i = 1; i < argc; i++)
663     {
664       if (strcmp(argv[i], "--fullscreen") == 0 ||
665           strcmp(argv[i], "-f") == 0)
666         {
667           use_fullscreen = true;
668         }
669       else if (strcmp(argv[i], "--window") == 0 ||
670                strcmp(argv[i], "-w") == 0)
671         {
672           use_fullscreen = false;
673         }
674       else if (strcmp(argv[i], "--joystick") == 0 || strcmp(argv[i], "-j") == 0)
675         {
676           assert(i+1 < argc);
677           joystick_num = atoi(argv[++i]);
678         }
679       else if (strcmp(argv[i], "--joymap") == 0)
680         {
681           assert(i+1 < argc);
682           if (sscanf(argv[++i],
683                      "%d:%d:%d:%d:%d", 
684                      &joystick_keymap.x_axis, 
685                      &joystick_keymap.y_axis, 
686                      &joystick_keymap.a_button, 
687                      &joystick_keymap.b_button, 
688                      &joystick_keymap.start_button) != 5)
689             {
690               puts("Warning: Invalid or incomplete joymap, should be: 'XAXIS:YAXIS:A:B:START'");
691             }
692           else
693             {
694               std::cout << "Using new joymap:\n"
695                         << "  X-Axis:       " << joystick_keymap.x_axis << "\n"
696                         << "  Y-Axis:       " << joystick_keymap.y_axis << "\n"
697                         << "  A-Button:     " << joystick_keymap.a_button << "\n"
698                         << "  B-Button:     " << joystick_keymap.b_button << "\n"
699                         << "  Start-Button: " << joystick_keymap.start_button << std::endl;
700             }
701         }
702       else if (strcmp(argv[i], "--leveleditor") == 0)
703         {
704           launch_leveleditor_mode = true;
705         }
706       else if (strcmp(argv[i], "--worldmap") == 0)
707         {
708           launch_worldmap_mode = true;
709         }
710       else if (strcmp(argv[i], "--flip-levels") == 0)
711         {
712           flip_levels_mode = true;
713         }
714       else if (strcmp(argv[i], "--datadir") == 0 
715                || strcmp(argv[i], "-d") == 0 )
716         {
717           assert(i+1 < argc);
718           datadir = argv[++i];
719         }
720       else if (strcmp(argv[i], "--show-fps") == 0)
721         {
722           /* Use full screen: */
723
724           show_fps = true;
725         }
726       else if (strcmp(argv[i], "--opengl") == 0 ||
727                strcmp(argv[i], "-gl") == 0)
728         {
729 #ifndef NOOPENGL
730           /* Use OpengGL: */
731
732           use_gl = true;
733 #endif
734         }
735       else if (strcmp(argv[i], "--sdl") == 0)
736           {
737             use_gl = false;
738           }
739       else if (strcmp(argv[i], "--usage") == 0)
740         {
741           /* Show usage: */
742
743           usage(argv[0], 0);
744         }
745       else if (strcmp(argv[i], "--version") == 0)
746         {
747           /* Show version: */
748           printf((package_name + package_version + "\n").c_str() );
749           exit(0);
750         }
751       else if (strcmp(argv[i], "--disable-sound") == 0)
752         {
753           /* Disable the compiled in sound feature */
754           printf("Sounds disabled \n");
755           SoundManager::get()->enable_sound(false); 
756         }
757       else if (strcmp(argv[i], "--disable-music") == 0)
758         {
759           /* Disable the compiled in sound feature */
760           printf("Music disabled \n");
761           SoundManager::get()->enable_music(false); 
762         }
763       else if (strcmp(argv[i], "--debug") == 0)
764         {
765           /* Enable the debug-mode */
766           debug_mode = true;
767
768         }
769       else if (strcmp(argv[i], "--help") == 0)
770         {     /* Show help: */
771           puts(_(("  SuperTux  " + package_version + "\n"
772                "  Please see the file \"README.txt\" for more details.\n").c_str()));
773           printf(_("Usage: %s [OPTIONS] FILENAME\n\n"), argv[0]);
774           puts(_("Display Options:\n"
775                "  -f, --fullscreen    Run in fullscreen mode.\n"
776                "  -w, --window        Run in window mode.\n"
777                "  --opengl            If OpenGL support was compiled in, this will tell\n"
778                "                      SuperTux to make use of it.\n"
779                "  --sdl               Use the SDL software graphical renderer\n"
780                "\n"
781                "Sound Options:\n"
782                "  --disable-sound     If sound support was compiled in,  this will\n"
783                "                      disable sound for this session of the game.\n"
784                "  --disable-music     Like above, but this will disable music.\n"
785                "\n"
786                "Misc Options:\n"
787                "  -j, --joystick NUM  Use joystick NUM (default: 0)\n" 
788                "  --joymap XAXIS:YAXIS:A:B:START\n"
789                "                      Define how joystick buttons and axis should be mapped\n"
790                "  --leveleditor       Opens the leveleditor in a file.\n"
791                "  --worldmap          Opens the specified worldmap file.\n"
792                "  --flip-levels       Flip levels upside-down.\n"
793                "  -d, --datadir DIR   Load Game data from DIR (default: automatic)\n"
794                "  --debug             Enables the debug mode, which is useful for developers.\n"
795                "  --help              Display a help message summarizing command-line\n"
796                "                      options, license and game controls.\n"
797                "  --usage             Display a brief message summarizing command-line options.\n"
798                "  --version           Display the version of SuperTux you're running.\n\n"
799                ));
800           exit(0);
801         }
802       else if (argv[i][0] != '-')
803         {
804           level_startup_file = argv[i];
805         }
806       else
807         {
808           /* Unknown - complain! */
809
810           usage(argv[0], 1);
811         }
812     }
813 }
814
815
816 /* Display usage: */
817
818 void usage(char * prog, int ret)
819 {
820   FILE * fi;
821
822
823   /* Determine which stream to write to: */
824
825   if (ret == 0)
826     fi = stdout;
827   else
828     fi = stderr;
829
830
831   /* Display the usage message: */
832
833   fprintf(fi, _("Usage: %s [--fullscreen] [--opengl] [--disable-sound] [--disable-music] [--debug] | [--usage | --help | --version] [--leveleditor] [--worldmap] [--flip-levels] FILENAME\n"),
834           prog);
835
836
837   /* Quit! */
838
839   exit(ret);
840 }
841
842 std::set<std::string> FileSystem::read_directory(const std::string& pathname)
843 {
844   std::set<std::string> dirnames;
845   
846   DIR* dir = opendir(pathname.c_str());
847   if (dir)
848     {
849       struct dirent *direntp;
850       
851       while((direntp = readdir(dir)))
852         {
853           dirnames.insert(direntp->d_name);
854         }
855       
856       closedir(dir);
857     }
858
859   return dirnames;
860 }
861
862 /* EOF */