Do not hardcode path to TERMINFO in termex
[centerim5.git] / cppconsui / CppConsUI.cpp
blob3886b1716d2c13a786c785ae0177ad5ec9b3654d
1 // Copyright (C) 2013-2015 Petr Pavlu <setup@dagobah.cz>
2 //
3 // This file is part of CenterIM.
4 //
5 // CenterIM 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 //
10 // CenterIM is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with CenterIM. If not, see <http://www.gnu.org/licenses/>.
18 #include "CppConsUI.h"
20 #include "ColorScheme.h"
21 #include "CoreManager.h"
22 #include "KeyConfig.h"
24 #include <algorithm>
25 #include <cassert>
26 #include <cstdarg>
27 #include <cstdio>
28 #include <cstdlib>
29 #include <cstring>
31 namespace CppConsUI {
33 ColorScheme *color_scheme = nullptr;
34 CoreManager *core_manager = nullptr;
35 KeyConfig *key_config = nullptr;
37 Error::Error(ErrorCode code, const char *string)
38 : error_code_(code), error_string_(nullptr)
40 setString(string);
43 Error::Error(const Error &other)
45 assert(other.error_string_ != nullptr);
47 error_code_ = other.error_code_;
49 std::size_t size = std::strlen(other.error_string_) + 1;
50 error_string_ = new char[size];
51 std::strcpy(error_string_, other.error_string_);
54 Error &Error::operator=(const Error &other)
56 assert(other.error_string_ != nullptr);
58 std::size_t size = std::strlen(other.error_string_) + 1;
59 auto new_string = new char[size];
60 std::strcpy(new_string, other.error_string_);
62 error_code_ = other.error_code_;
63 delete[] error_string_;
64 error_string_ = new_string;
66 return *this;
69 Error::~Error()
71 delete[] error_string_;
74 void Error::setCode(ErrorCode code)
76 error_code_ = code;
79 void Error::setString(const char *string)
81 std::size_t size = 1;
82 if (string != nullptr)
83 size += std::strlen(string);
84 auto new_string = new char[size];
85 if (string != nullptr)
86 std::strcpy(new_string, string);
87 else
88 new_string[0] = '\0';
90 delete[] error_string_;
91 error_string_ = new_string;
94 void Error::setFormattedString(const char *format, ...)
96 assert(format != nullptr);
98 va_list args;
100 va_start(args, format);
101 int size = std::vsnprintf(nullptr, 0, format, args) + 1;
102 va_end(args);
104 auto new_string = new char[size];
106 va_start(args, format);
107 std::vsprintf(new_string, format, args);
108 va_end(args);
110 delete[] error_string_;
111 error_string_ = new_string;
114 void Error::clear()
116 error_code_ = ERROR_NONE;
117 delete[] error_string_;
118 error_string_ = nullptr;
121 void initializeConsUI(AppInterface &interface)
123 assert(color_scheme == nullptr);
124 assert(core_manager == nullptr);
125 assert(key_config == nullptr);
127 // Initialize ColorScheme and KeyConfig. These cannot fail.
128 color_scheme = new ColorScheme;
129 key_config = new KeyConfig;
131 // CoreManager depends on KeyConfig so it has to be initialized after it.
132 core_manager = new CoreManager(interface);
135 void finalizeConsUI()
137 assert(color_scheme != nullptr);
138 assert(core_manager != nullptr);
139 assert(key_config != nullptr);
141 // Destroy CoreManager, KeyConfig and ColorScheme.
142 delete core_manager;
143 core_manager = nullptr;
144 delete key_config;
145 key_config = nullptr;
146 delete color_scheme;
147 color_scheme = nullptr;
150 ColorScheme *getColorSchemeInstance()
152 assert(color_scheme != nullptr);
153 return color_scheme;
156 CoreManager *getCoreManagerInstance()
158 assert(core_manager != nullptr);
159 return core_manager;
162 KeyConfig *getKeyConfigInstance()
164 assert(key_config != nullptr);
165 return key_config;
168 namespace UTF8 {
170 // Some code below is based on the GLib code.
172 // Bits Length Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
173 // 7 1 0xxxxxxx
174 // 11 2 110xxxxx 10xxxxxx
175 // 16 3 1110xxxx 10xxxxxx 10xxxxxx
176 // 21 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
177 // 26 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
178 // 31 6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
179 UniChar getUniChar(const char *p)
181 assert(p != nullptr);
183 UniChar res;
184 unsigned char c = *p++;
185 int rest;
187 if ((c & 0x80) == 0x00)
188 return c & 0x7f;
189 else if ((c & 0xe0) == 0xc0) {
190 rest = 1;
191 res = c & 0x1f;
193 else if ((c & 0xf0) == 0xe0) {
194 rest = 2;
195 res = c & 0x0f;
197 else if ((c & 0xf8) == 0xf0) {
198 rest = 3;
199 res = c & 0x07;
201 else if ((c & 0xfc) == 0xf8) {
202 rest = 4;
203 res = c & 0x03;
205 else if ((c & 0xfe) == 0xfc) {
206 rest = 5;
207 res = c & 0x01;
209 else
210 return -1;
212 while (rest-- > 0) {
213 c = *p++;
214 if ((c & 0xc0) != 0x80)
215 return -1;
216 res <<= 6;
217 res |= c & 0x3f;
220 return res;
223 namespace {
225 struct Interval {
226 UniChar start, end;
229 int interval_compare(const void *key, const void *elt)
231 const UniChar uc = *static_cast<const UniChar *>(key);
232 const Interval *interval = static_cast<const Interval *>(elt);
234 if (uc < interval->start)
235 return -1;
236 if (uc > interval->end)
237 return +1;
239 return 0;
242 } // anonymous namespace
244 bool isUniCharWide(UniChar uc)
246 static const Interval wide[] = {{0x1100, 0x115F}, {0x2329, 0x232A},
247 {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB},
248 {0x3000, 0x303E}, {0x3041, 0x3096}, {0x3099, 0x30FF}, {0x3105, 0x312D},
249 {0x3131, 0x318E}, {0x3190, 0x31BA}, {0x31C0, 0x31E3}, {0x31F0, 0x321E},
250 {0x3220, 0x3247}, {0x3250, 0x32FE}, {0x3300, 0x4DBF}, {0x4E00, 0xA48C},
251 {0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3}, {0xF900, 0xFAFF},
252 {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, {0xFE54, 0xFE66}, {0xFE68, 0xFE6B},
253 {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, {0x1B000, 0x1B001}, {0x1F200, 0x1F202},
254 {0x1F210, 0x1F23A}, {0x1F240, 0x1F248}, {0x1F250, 0x1F251},
255 {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD}};
257 if (std::bsearch(&uc, wide, sizeof(wide) / sizeof(wide[0]), sizeof(wide[0]),
258 interval_compare))
259 return true;
261 return false;
264 bool isUniCharDigit(UniChar uc)
266 // Note: this function does not behave according to the Unicode standard.
268 if (uc > '0' && uc < '9')
269 return true;
270 return false;
273 bool isUniCharSpace(UniChar uc)
275 // Note: this function does not behave according to the Unicode standard.
277 if (uc == '\t' || uc == '\n' || uc == '\r' || uc == '\f')
278 return true;
279 return false;
282 const char *getNextChar(const char *p)
284 static const char utf8_skip_data[256] = {
285 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00-0x0f
286 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10-0x1f
287 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20-0x2f
288 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30-0x3f
289 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40-0x4f
290 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50-0x5f
291 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60-0x6f
292 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70-0x7f
293 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80-0x8f
294 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90-0x9f
295 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0-0xaf
296 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0-0xbf
297 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0-0xcf
298 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0-0xdf
299 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0-0xef
300 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1 // 0xf0-0xff
303 return p + utf8_skip_data[static_cast<unsigned char>(*p)];
306 const char *getPrevChar(const char *p)
308 while (true) {
309 --p;
310 if ((*p & 0xc0) != 0x80)
311 return p;
315 const char *findNextChar(const char *p, const char *end)
317 if (end == nullptr)
318 return getNextChar(p);
320 while (p + 1 < end) {
321 ++p;
322 if ((*p & 0xc0) != 0x80)
323 return p;
325 return nullptr;
328 const char *findPrevChar(const char *start, const char *p)
330 while (p > start) {
331 --p;
332 if ((*p & 0xc0) != 0x80)
333 return p;
335 return nullptr;
338 } // namespace UTF8
340 } // namespace CppConsUI
342 // vim: set tabstop=2 shiftwidth=2 textwidth=80 expandtab: