Bug 1885602 - Part 4: Implement navigating to the settings from the menu header for...
[gecko.git] / toolkit / xre / AssembleCmdLine.h
blobd969fedfed40494830bf640a24b0d238981576e6
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_AssembleCmdLine_h
8 #define mozilla_AssembleCmdLine_h
10 #if defined(XP_WIN)
12 # include "mozilla/UniquePtr.h"
14 # include <stdlib.h>
15 # include <windows.h>
17 # ifdef MOZILLA_INTERNAL_API
18 # include "nsString.h"
19 # endif // MOZILLA_INTERNAL_API
21 namespace mozilla {
23 // Out param `aWideCmdLine` must be free()d by the caller.
24 inline int assembleCmdLine(const char* const* aArgv, wchar_t** aWideCmdLine,
25 UINT aCodePage) {
26 const char* const* arg;
27 char* p;
28 const char* q;
29 char* cmdLine;
30 int cmdLineSize;
31 int numBackslashes;
32 int i;
33 int argNeedQuotes;
36 * Find out how large the command line buffer should be.
38 cmdLineSize = 0;
39 for (arg = aArgv; *arg; ++arg) {
41 * \ and " need to be escaped by a \. In the worst case,
42 * every character is a \ or ", so the string of length
43 * may double. If we quote an argument, that needs two ".
44 * Finally, we need a space between arguments, and
45 * a null byte at the end of command line.
47 cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */
48 + 2 /* we quote every argument */
49 + 1; /* space in between, or final null */
51 p = cmdLine = (char*)malloc(cmdLineSize * sizeof(char));
52 if (!p) {
53 return -1;
56 for (arg = aArgv; *arg; ++arg) {
57 /* Add a space to separates the arguments */
58 if (arg != aArgv) {
59 *p++ = ' ';
61 q = *arg;
62 numBackslashes = 0;
63 argNeedQuotes = 0;
66 * If the argument is empty or contains white space, it needs to
67 * be quoted.
69 if (**arg == '\0' || strpbrk(*arg, " \f\n\r\t\v")) {
70 argNeedQuotes = 1;
73 if (argNeedQuotes) {
74 *p++ = '"';
76 while (*q) {
77 if (*q == '\\') {
78 numBackslashes++;
79 q++;
80 } else if (*q == '"') {
81 if (numBackslashes) {
83 * Double the backslashes since they are followed
84 * by a quote
86 for (i = 0; i < 2 * numBackslashes; i++) {
87 *p++ = '\\';
89 numBackslashes = 0;
91 /* To escape the quote */
92 *p++ = '\\';
93 *p++ = *q++;
94 } else {
95 if (numBackslashes) {
97 * Backslashes are not followed by a quote, so
98 * don't need to double the backslashes.
100 for (i = 0; i < numBackslashes; i++) {
101 *p++ = '\\';
103 numBackslashes = 0;
105 *p++ = *q++;
109 /* Now we are at the end of this argument */
110 if (numBackslashes) {
112 * Double the backslashes if we have a quote string
113 * delimiter at the end.
115 if (argNeedQuotes) {
116 numBackslashes *= 2;
118 for (i = 0; i < numBackslashes; i++) {
119 *p++ = '\\';
122 if (argNeedQuotes) {
123 *p++ = '"';
127 *p = '\0';
128 int numChars = MultiByteToWideChar(aCodePage, 0, cmdLine, -1, nullptr, 0);
129 *aWideCmdLine = (wchar_t*)malloc(numChars * sizeof(wchar_t));
130 MultiByteToWideChar(aCodePage, 0, cmdLine, -1, *aWideCmdLine, numChars);
131 free(cmdLine);
132 return 0;
135 } // namespace mozilla
137 #endif // defined(XP_WIN)
139 #endif // mozilla_AssembleCmdLine_h