Branch data Line data Source code
1 : : #include "libcon.h"
2 : : #include "libstr.h"
3 : : #include "unicode.h"
4 : : #include <csignal>
5 : :
6 : : #ifdef windows
7 : : // for readconsole
8 : : #include <windows.h>
9 : : #endif
10 : :
11 : : static const char * progname;
12 : : static const char ** args;
13 : : static int argsleft;
14 : : bool libcon_interactive;
15 : : static const char * usage;
16 : :
17 : : static volatile bool confirmclose=true;
18 : 0 : void libcon_pause()
19 : : {
20 [ # # ]: 0 : if (confirmclose)
21 : : {
22 : 0 : confirmclose=false;
23 : : #if defined(_WIN32)
24 : 0 : system("pause");
25 : : #else
26 : 0 : printf("Press Enter to continue");
27 : 0 : getchar();
28 : : #endif
29 : 0 : confirmclose=true;
30 : : }
31 : 0 : }
32 : :
33 : 0 : void libcon_badusage()
34 : : {
35 : 0 : printf("usage: %s %s", progname, usage);
36 : 0 : exit(1);
37 : : }
38 : :
39 : 2070 : static const char * getarg(bool tellusage, const char * defval= nullptr)
40 : : {
41 [ - + ]: 2070 : if (!argsleft)
42 : : {
43 [ # # ]: 0 : if (tellusage) libcon_badusage();
44 : 0 : return defval;
45 : : }
46 : 2070 : args++;
47 : 2070 : argsleft--;
48 : 2070 : return args[0];
49 : : }
50 : :
51 : 0 : void u8_fgets(char* buffer, int buffer_size, FILE* handle)
52 : : {
53 : : #if defined(windows)
54 : : // RPG Hacker: Using buffer_size * 2 here to account for potential surrogate pairs.
55 : : // The idea is that our buffer here should be able to at least hold the same amount
56 : : // of characters as the old ANSI version would have supported.
57 : 0 : DWORD num_chars = buffer_size * 2;
58 : 0 : wchar_t* w_buf = (wchar_t*)malloc(num_chars * sizeof(wchar_t));
59 : : // this was originally using fgetws, but it was broken on mingw for some
60 : : // weird reason. (or, more specifically, msvcrt.dll is broken. msvc itself
61 : : // doesn't use that one.)
62 : 0 : BOOL res = ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), w_buf, num_chars-1, &num_chars, nullptr);
63 [ # # ]: 0 : if(!res) { free(w_buf); return; }
64 : 0 : w_buf[num_chars] = 0;
65 : : //(void)fgetws(w_buf, num_chars, stdin);
66 : 0 : string u8_str;
67 [ # # # # ]: 0 : if (utf16_to_utf8(&u8_str, w_buf))
68 : : {
69 : 0 : strncpy(buffer, u8_str, buffer_size);
70 : 0 : buffer[buffer_size-1] = '\0';
71 : : // no point doing more than 1 since the next function cuts off input at the first newline anyways
72 [ # # ]: 0 : if(strchr(buffer, '\r')) *(strchr(buffer, '\r')) = '\n';
73 : : }
74 : 0 : free(w_buf);
75 : : #else
76 : 0 : (void)fgets(buffer, buffer_size, handle);
77 : : #endif
78 : 0 : }
79 : :
80 : 0 : static const char * requirestrfromuser(const char * question, bool filename)
81 : : {
82 : 0 : confirmclose=false;
83 : 0 : char * rval=(char*)malloc(256);
84 : 0 : *rval=0;
85 [ # # # # ]: 0 : while (!strchr(rval, '\n') || *rval=='\n')
86 : : {
87 : 0 : *rval=0;
88 : 0 : printf("%s ", question);
89 : 0 : u8_fgets(rval, 250, stdin);
90 : : }
91 : 0 : *strchr(rval, '\n')=0;
92 : 0 : confirmclose=true;
93 : : #ifdef _WIN32
94 [ # # # # : 0 : if (filename && rval[0]=='"' && rval[2]==':')
# # ]
95 : : {
96 : 0 : char * rvalend=strchr(rval, '\0');
97 [ # # ]: 0 : if (rvalend[-1]=='"') rvalend[-1]='\0';
98 : 0 : return rval+1;
99 : : }
100 : : #endif
101 : 0 : return rval;
102 : : }
103 : :
104 : 0 : static const char * requeststrfromuser(const char * question, bool filename, const char * defval)
105 : : {
106 : 0 : confirmclose=false;
107 : 0 : char * rval=(char*)malloc(256);
108 : 0 : *rval=0;
109 : 0 : printf("%s ", question);
110 : 0 : u8_fgets(rval, 250, stdin);
111 : 0 : char *eol = strchr(rval, '\n');
112 [ # # ]: 0 : if(!eol)
113 : : {
114 : 0 : printf("Unexpected end of input");
115 : 0 : exit(-1);
116 : : }
117 : 0 : *eol = 0;
118 : 0 : confirmclose=true;
119 [ # # ]: 0 : if (!*rval) return defval;
120 : : #ifdef _WIN32
121 [ # # # # : 0 : if (filename && rval[0]=='"' && rval[2]==':')
# # ]
122 : : {
123 : 0 : char * rvalend=strchr(rval, '\0');
124 [ # # ]: 0 : if (rvalend[-1]=='"') rvalend[-1]='\0';
125 : 0 : return rval+1;
126 : : }
127 : : #endif
128 : 0 : return rval;
129 : : }
130 : :
131 : 230 : void libcon_init(int argc, const char ** argv, const char * usage_)
132 : : {
133 : 230 : progname=argv[0];
134 : 230 : args=argv;
135 : 230 : argsleft=argc-1;
136 : 230 : usage=usage_;
137 : 230 : libcon_interactive=(!argsleft);
138 : : #if defined(_WIN32)
139 [ - + ]: 115 : if (libcon_interactive) atexit(libcon_pause);
140 : : #endif
141 : 230 : }
142 : :
143 : 230 : const char * libcon_require_filename(const char * desc)
144 : : {
145 [ - + ]: 230 : if (libcon_interactive) return requirestrfromuser(desc, true);
146 : 230 : else return getarg(true);
147 : : }
148 : :
149 : 0 : const char * libcon_optional(const char * desc, const char * defval)
150 : : {
151 [ # # ]: 0 : if (libcon_interactive) return requeststrfromuser(desc, false, defval);
152 : 0 : else return getarg(false, defval);
153 : : }
154 : :
155 : 230 : const char * libcon_optional_filename(const char * desc, const char * defval)
156 : : {
157 [ - + ]: 230 : if (libcon_interactive) return requeststrfromuser(desc, true, defval);
158 : 230 : else return getarg(false, defval);
159 : : }
160 : :
161 : 1610 : const char * libcon_option()
162 : : {
163 [ + - + - : 1610 : if (!libcon_interactive && argsleft && args[1][0]=='-') return getarg(false);
+ + ]
164 : 115 : return nullptr;
165 : : }
166 : :
167 : 230 : const char * libcon_option_value()
168 : : {
169 [ + - ]: 230 : if (!libcon_interactive) return getarg(false);
170 : 0 : return nullptr;
171 : : }
172 : :
173 : 0 : bool libcon_question_bool(const char * desc, bool defval)
174 : : {
175 [ # # ]: 0 : if (!libcon_interactive) return defval;
176 : : while (true)
177 : : {
178 [ # # ]: 0 : const char * answer=requeststrfromuser(desc, false, defval?"y":"n");
179 [ # # # # : 0 : if (!stricmp(answer, "y") || !stricmp(answer, "yes")) return true;
# # ]
180 [ # # # # : 0 : if (!stricmp(answer, "n") || !stricmp(answer, "no")) return false;
# # ]
181 : 0 : }
182 : : }
183 : :
184 : 230 : void libcon_end()
185 : : {
186 [ + - - + ]: 230 : if (!libcon_interactive && argsleft) libcon_badusage();
187 : 230 : }
|