Moved argument parsing into CommandLineArguments
[supertux.git] / src / supertux / command_line_arguments.cpp
1 //  SuperTux
2 //  Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 #include "supertux/command_line_arguments.hpp"
18
19 #include <stdexcept>
20 #include <physfs.h>
21 #include <boost/format.hpp>
22
23 #include "supertux/gameconfig.hpp"
24 #include "supertux/main.hpp"
25 #include "util/gettext.hpp"
26 #include "util/log.hpp"
27 #include "version.h"
28
29 CommandLineArguments::CommandLineArguments() :
30   m_action(NO_ACTION),
31   fullscreen_size(),
32   fullscreen_refresh_rate(),
33   window_size(),
34   aspect_size(),
35   use_fullscreen(),
36   video(),
37   show_fps(),
38   sound_enabled(),
39   music_enabled(),
40   console_enabled(),
41   start_level(),
42   enable_script_debugger(),
43   start_demo(),
44   record_demo()
45 {
46 }
47
48 CommandLineArguments::~CommandLineArguments()
49 {
50 }
51
52 void
53 CommandLineArguments::print_datadir()
54 {
55   // Print the datadir searchpath to stdout, one path per
56   // line. Then exit. Intended for use by the supertux-editor.
57   char **sp;
58   size_t sp_index;
59   sp = PHYSFS_getSearchPath();
60   if (sp)
61     for (sp_index = 0; sp[sp_index]; sp_index++)
62       std::cout << sp[sp_index] << std::endl;
63   PHYSFS_freeList(sp);
64 }
65
66 void
67 CommandLineArguments::print_help(const char* argv0)
68 {
69   std::string default_user_data_dir =
70       std::string(PHYSFS_getUserDir()) + WRITEDIR_NAME;
71
72   std::cerr << boost::format(_(
73                  "\n"
74                  "Usage: %s [OPTIONS] [LEVELFILE]\n\n"
75                  "CommandLineArguments:\n"
76                  "  -f, --fullscreen             Run in fullscreen mode\n"
77                  "  -w, --window                 Run in window mode\n"
78                  "  -g, --geometry WIDTHxHEIGHT  Run SuperTux in given resolution\n"
79                  "  -a, --aspect WIDTH:HEIGHT    Run SuperTux with given aspect ratio\n"
80                  "  -d, --default                Reset video settings to default values\n"
81                  "  --renderer RENDERER          Use sdl, opengl, or auto to render\n"
82                  "  --disable-sound              Disable sound effects\n"
83                  "  --disable-music              Disable music\n"
84                  "  -h, --help                   Show this help message and quit\n"
85                  "  -v, --version                Show SuperTux version and quit\n"
86                  "  --console                    Enable ingame scripting console\n"
87                  "  --noconsole                  Disable ingame scripting console\n"
88                  "  --show-fps                   Display framerate in levels\n"
89                  "  --no-show-fps                Do not display framerate in levels\n"
90                  "  --record-demo FILE LEVEL     Record a demo to FILE\n"
91                  "  --play-demo FILE LEVEL       Play a recorded demo\n"
92                  "  -s, --debug-scripts          Enable script debugger.\n"
93                  "  --print-datadir              Print supertux's primary data directory.\n"
94                  "\n"
95                  "Environment variables:\n"
96                  "  SUPERTUX2_USER_DIR           Directory for user data (savegames, etc.);\n"
97                  "                               default %s\n"
98                  "\n"
99                  ))
100             % argv0 % default_user_data_dir
101             << std::flush;
102 }
103
104 void
105 CommandLineArguments::print_version()
106 {
107   std::cout << PACKAGE_NAME << " " << PACKAGE_VERSION << std::endl;
108 }
109
110 void
111 CommandLineArguments::parse_args(int argc, char** argv)
112 {
113   for(int i = 1; i < argc; ++i)
114   {
115     std::string arg = argv[i];
116
117     if (arg == "--version" || arg == "-v")
118     {
119       m_action = PRINT_VERSION;
120
121     }
122     else if (arg == "--help" || arg == "-h")
123     {
124       m_action = PRINT_HELP;
125     }
126     else if (arg == "--print-datadir")
127     {
128       m_action = PRINT_DATADIR;
129     }
130     else if (arg == "--fullscreen" || arg == "-f")
131     {
132       use_fullscreen = true;
133     }
134     else if (arg == "--default" || arg == "-d")
135     {
136       use_fullscreen = false;
137
138       window_size = Size(800, 600);
139       fullscreen_size = Size(800, 600);
140       fullscreen_refresh_rate = 0;
141       aspect_size = Size(0, 0);  // auto detect
142     }
143     else if (arg == "--window" || arg == "-w")
144     {
145       use_fullscreen = false;
146     }
147     else if (arg == "--geometry" || arg == "-g")
148     {
149       i += 1;
150       if (i >= argc)
151       {
152         throw std::runtime_error("Need to specify a size (WIDTHxHEIGHT) for geometry argument");
153       }
154       else
155       {
156         int width, height;
157         if (sscanf(argv[i], "%dx%d", &width, &height) != 2)
158         {
159           throw std::runtime_error("Invalid geometry spec, should be WIDTHxHEIGHT");
160         }
161         else
162         {
163           window_size     = Size(width, height);
164           fullscreen_size = Size(width, height);
165           fullscreen_refresh_rate = 0;
166         }
167       }
168     }
169     else if (arg == "--aspect" || arg == "-a")
170     {
171       i += 1;
172       if (i >= argc)
173       {
174         throw std::runtime_error("Need to specify a ratio (WIDTH:HEIGHT) for aspect ratio");
175       }
176       else
177       {
178         int aspect_width  = 0;
179         int aspect_height = 0;
180         if (strcmp(argv[i], "auto") == 0)
181         {
182           aspect_width  = 0;
183           aspect_height = 0;
184         }
185         else if (sscanf(argv[i], "%d:%d", &aspect_width, &aspect_height) != 2)
186         {
187           throw std::runtime_error("Invalid aspect spec, should be WIDTH:HEIGHT or auto");
188         }
189         else
190         {
191           float aspect_ratio = static_cast<float>(aspect_width) / static_cast<float>(aspect_height);
192
193           // use aspect ratio to calculate logical resolution
194           if (aspect_ratio > 1) {
195             aspect_size = Size(static_cast<int>(600 * aspect_ratio + 0.5),
196                                          600);
197           } else {
198             aspect_size = Size(600,
199                                          static_cast<int>(600 * 1/aspect_ratio + 0.5));
200           }
201         }
202       }
203     }
204     else if (arg == "--renderer")
205     {
206       i += 1;
207       if (i >= argc)
208       {
209         throw std::runtime_error("Need to specify a renderer for renderer argument");
210       }
211       else
212       {
213         video = VideoSystem::get_video_system(argv[i]);
214       }
215     }
216     else if (arg == "--show-fps")
217     {
218       show_fps = true;
219     }
220     else if (arg == "--no-show-fps")
221     {
222       show_fps = false;
223     }
224     else if (arg == "--console")
225     {
226       console_enabled = true;
227     }
228     else if (arg == "--noconsole")
229     {
230       console_enabled = false;
231     }
232     else if (arg == "--disable-sound" || arg == "--disable-sfx")
233     {
234       sound_enabled = false;
235     }
236     else if (arg == "--disable-music")
237     {
238       music_enabled = false;
239     }
240     else if (arg == "--play-demo")
241     {
242       if (i+1 >= argc)
243       {
244         throw std::runtime_error("Need to specify a demo filename");
245       }
246       else
247       {
248         start_demo = argv[++i];
249       }
250     }
251     else if (arg == "--record-demo")
252     {
253       if (i+1 >= argc)
254       {
255         throw std::runtime_error("Need to specify a demo filename");
256       }
257       else
258       {
259         record_demo = argv[++i];
260       }
261     }
262     else if (arg == "--debug-scripts" || arg == "-s")
263     {
264       enable_script_debugger = true;
265     }
266     else if (arg[0] != '-')
267     {
268       start_level = arg;
269     }
270     else
271     {
272       throw std::runtime_error((boost::format("Unknown option '%1%''. Use --help to see a list of options") % arg).str());
273     }
274   }
275 }
276
277 void
278 CommandLineArguments::merge_into(Config& config)
279 {
280 #define merge_option(x) if (x) { config.x = *x; }
281
282   merge_option(fullscreen_size);
283   merge_option(fullscreen_refresh_rate);
284   merge_option(window_size);
285   merge_option(aspect_size);
286   merge_option(use_fullscreen);
287   merge_option(video);
288   merge_option(show_fps);
289   merge_option(sound_enabled);
290   merge_option(music_enabled);
291   merge_option(console_enabled);
292   merge_option(start_level);
293   merge_option(enable_script_debugger);
294   merge_option(start_demo);
295   merge_option(record_demo);
296
297 #undef merge_option
298 }
299
300 /* EOF */