The Battle for Wesnoth  1.17.0-dev
commandline_argv.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2020 - 2021
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "commandline_argv.hpp"
16 
17 #ifdef _WIN32
18 
20 
21 #include <windows.h>
22 
23 namespace {
24 
25 bool win32_parse_single_arg(const char*& next, const char* end, std::string& res)
26 {
27  // strip leading whitespace
28  while(next != end && *next == ' ') {
29  ++next;
30  }
31 
32  if(next == end) {
33  return false;
34  }
35 
36  bool is_escaped = false;
37 
38  for(; next != end; ++next) {
39  if(*next == ' ' && !is_escaped) {
40  break;
41  } else if(*next == '"' && !is_escaped) {
42  is_escaped = true;
43  continue;
44  } else if(*next == '"' && is_escaped && next + 1 != end && *(next + 1) == '"') {
45  res.push_back('"');
46  ++next;
47  continue;
48  } else if(*next == '"' && is_escaped) {
49  is_escaped = false;
50  continue;
51  } else {
52  res.push_back(*next);
53  }
54  }
55 
56  return true;
57 }
58 
59 std::vector<std::string> win32_read_argv(const std::string& input)
60 {
61  const char* start = &input[0];
62  const char* end = start + input.size();
63 
64  std::string buffer;
65  std::vector<std::string> res;
66 
67  while(win32_parse_single_arg(start, end, buffer)) {
68  res.emplace_back();
69  res.back().swap(buffer);
70  }
71 
72  return res;
73 }
74 
75 }
76 
77 #endif
78 
79 std::vector<std::string> read_argv([[maybe_unused]] int argc, [[maybe_unused]] char** argv)
80 {
81 #ifdef _WIN32
82  // On Windows, argv is ANSI-encoded by default. Wesnoth absolutely needs to
83  // work with UTF-8 values in order to avoid losing or corrupting
84  // information from the command line.
85  auto flat_cmdline = unicode_cast<std::string>(std::wstring{GetCommandLineW()});
86  return win32_read_argv(flat_cmdline);
87 #else
88  std::vector<std::string> args;
89  for(int i = 0; i < argc; ++i) {
90  args.push_back(std::string(argv[i]));
91  }
92  return args;
93 #endif
94 }
ucs4_convert_impl::enableif< TD, typename TS::value_type >::type unicode_cast(const TS &source)
std::size_t i
Definition: function.cpp:967
#define next(ls)
Definition: llex.cpp:32
std::vector< std::string > read_argv([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
EXIT_STATUS start(const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Definition: editor_main.cpp:30