Update list of wide characters
[centerim5.git] / cppconsui / CppConsUI.cpp
blobea924f59776354eb29c4ae808e74b1bd40d3cea6
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[] = {
247 {0x1100, 0x115F},
248 {0x231A, 0x231B},
249 {0x2329, 0x232A},
250 {0x23E9, 0x23EC},
251 {0x23F0, 0x23F0},
252 {0x23F3, 0x23F3},
253 {0x25FD, 0x25FE},
254 {0x2614, 0x2615},
255 {0x2648, 0x2653},
256 {0x267F, 0x267F},
257 {0x2693, 0x2693},
258 {0x26A1, 0x26A1},
259 {0x26AA, 0x26AB},
260 {0x26BD, 0x26BE},
261 {0x26C4, 0x26C5},
262 {0x26CE, 0x26CE},
263 {0x26D4, 0x26D4},
264 {0x26EA, 0x26EA},
265 {0x26F2, 0x26F3},
266 {0x26F5, 0x26F5},
267 {0x26FA, 0x26FA},
268 {0x26FD, 0x26FD},
269 {0x2705, 0x2705},
270 {0x270A, 0x270B},
271 {0x2728, 0x2728},
272 {0x274C, 0x274C},
273 {0x274E, 0x274E},
274 {0x2753, 0x2755},
275 {0x2757, 0x2757},
276 {0x2795, 0x2797},
277 {0x27B0, 0x27B0},
278 {0x27BF, 0x27BF},
279 {0x2B1B, 0x2B1C},
280 {0x2B50, 0x2B50},
281 {0x2B55, 0x2B55},
282 {0x2E80, 0x2E99},
283 {0x2E9B, 0x2EF3},
284 {0x2F00, 0x2FD5},
285 {0x2FF0, 0x2FFB},
286 {0x3000, 0x303E},
287 {0x3041, 0x3096},
288 {0x3099, 0x30FF},
289 {0x3105, 0x312F},
290 {0x3131, 0x318E},
291 {0x3190, 0x31BA},
292 {0x31C0, 0x31E3},
293 {0x31F0, 0x321E},
294 {0x3220, 0x3247},
295 {0x3250, 0x4DBF},
296 {0x4E00, 0xA48C},
297 {0xA490, 0xA4C6},
298 {0xA960, 0xA97C},
299 {0xAC00, 0xD7A3},
300 {0xF900, 0xFAFF},
301 {0xFE10, 0xFE19},
302 {0xFE30, 0xFE52},
303 {0xFE54, 0xFE66},
304 {0xFE68, 0xFE6B},
305 {0xFF01, 0xFF60},
306 {0xFFE0, 0xFFE6},
307 {0x16FE0, 0x16FE3},
308 {0x17000, 0x187F7},
309 {0x18800, 0x18AF2},
310 {0x1B000, 0x1B11E},
311 {0x1B150, 0x1B152},
312 {0x1B164, 0x1B167},
313 {0x1B170, 0x1B2FB},
314 {0x1F004, 0x1F004},
315 {0x1F0CF, 0x1F0CF},
316 {0x1F18E, 0x1F18E},
317 {0x1F191, 0x1F19A},
318 {0x1F200, 0x1F202},
319 {0x1F210, 0x1F23B},
320 {0x1F240, 0x1F248},
321 {0x1F250, 0x1F251},
322 {0x1F260, 0x1F265},
323 {0x1F300, 0x1F320},
324 {0x1F32D, 0x1F335},
325 {0x1F337, 0x1F37C},
326 {0x1F37E, 0x1F393},
327 {0x1F3A0, 0x1F3CA},
328 {0x1F3CF, 0x1F3D3},
329 {0x1F3E0, 0x1F3F0},
330 {0x1F3F4, 0x1F3F4},
331 {0x1F3F8, 0x1F43E},
332 {0x1F440, 0x1F440},
333 {0x1F442, 0x1F4FC},
334 {0x1F4FF, 0x1F53D},
335 {0x1F54B, 0x1F54E},
336 {0x1F550, 0x1F567},
337 {0x1F57A, 0x1F57A},
338 {0x1F595, 0x1F596},
339 {0x1F5A4, 0x1F5A4},
340 {0x1F5FB, 0x1F64F},
341 {0x1F680, 0x1F6C5},
342 {0x1F6CC, 0x1F6CC},
343 {0x1F6D0, 0x1F6D2},
344 {0x1F6D5, 0x1F6D5},
345 {0x1F6EB, 0x1F6EC},
346 {0x1F6F4, 0x1F6FA},
347 {0x1F7E0, 0x1F7EB},
348 {0x1F90D, 0x1F971},
349 {0x1F973, 0x1F976},
350 {0x1F97A, 0x1F9A2},
351 {0x1F9A5, 0x1F9AA},
352 {0x1F9AE, 0x1F9CA},
353 {0x1F9CD, 0x1F9FF},
354 {0x1FA70, 0x1FA73},
355 {0x1FA78, 0x1FA7A},
356 {0x1FA80, 0x1FA82},
357 {0x1FA90, 0x1FA95},
358 {0x20000, 0x2FFFD},
359 {0x30000, 0x3FFFD},
362 if (std::bsearch(&uc, wide, sizeof(wide) / sizeof(wide[0]), sizeof(wide[0]),
363 interval_compare))
364 return true;
366 return false;
369 bool isUniCharDigit(UniChar uc)
371 // Note: this function does not behave according to the Unicode standard.
373 if (uc > '0' && uc < '9')
374 return true;
375 return false;
378 bool isUniCharSpace(UniChar uc)
380 // Note: this function does not behave according to the Unicode standard.
382 if (uc == ' ' || uc == '\t' || uc == '\n' || uc == '\r' || uc == '\f')
383 return true;
384 return false;
387 const char *getNextChar(const char *p)
389 static const char utf8_skip_data[256] = {
390 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00-0x0f
391 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10-0x1f
392 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20-0x2f
393 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30-0x3f
394 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40-0x4f
395 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50-0x5f
396 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60-0x6f
397 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70-0x7f
398 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80-0x8f
399 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90-0x9f
400 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0-0xaf
401 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0-0xbf
402 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0-0xcf
403 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0-0xdf
404 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0-0xef
405 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1 // 0xf0-0xff
408 return p + utf8_skip_data[static_cast<unsigned char>(*p)];
411 const char *getPrevChar(const char *p)
413 while (true) {
414 --p;
415 if ((*p & 0xc0) != 0x80)
416 return p;
420 const char *findNextChar(const char *p, const char *end)
422 if (end == nullptr)
423 return getNextChar(p);
425 while (p + 1 < end) {
426 ++p;
427 if ((*p & 0xc0) != 0x80)
428 return p;
430 return nullptr;
433 const char *findPrevChar(const char *start, const char *p)
435 while (p > start) {
436 --p;
437 if ((*p & 0xc0) != 0x80)
438 return p;
440 return nullptr;
443 } // namespace UTF8
445 } // namespace CppConsUI
447 // vim: set tabstop=2 shiftwidth=2 textwidth=80 expandtab: