mirror of
https://github.com/brazilofmux/tinymux
synced 2026-08-13 00:23:11 -04:00
#1435 stopped an unimplemented conversion from aborting the process: the spec is echoed literally and formatting continues. Echoing is right; continuing is not. No va_arg is consumed for a spec the formatter cannot parse, so from that point the argument list is misaligned and every later conversion in the same format string reads the wrong argument. Measured on master, Linux x86-64: "%d|%d" 11, 22 -> "11|22" baseline "%s|%+d" "head", 11 -> "head|%+d" safe, nothing follows "%+d|%d" 11, 22 -> "%+d|11" silently the WRONG argument "%+d|%s" 11, "tail" -> SIGSEGV The last one hands an int to the %s path as a UTF8* and dereferences it. That trades a clean abort for a wild pointer, which is not the improvement #1429 was for -- a crash that used to name its own file and line is now an unattributed segfault somewhere else. There is no way to resynchronise without knowing what the unknown spec would have taken, and no way to learn that without implementing it. So recovery now stops at the first spec it cannot parse: the remainder of the format is echoed verbatim and interpretation ends. Conversions BEFORE the bad spec are still honoured -- "%s|%+d" still renders its %s -- so stopping is not the same as discarding the format. Echoing the whole remainder rather than just the offending spec keeps the evidence intact: the spec appears in full, with the text that followed it, while nothing further is interpreted. Bug-catch: with the formatter reverted to master's continue and these tests kept, the test binary SEGFAULTS rather than reporting a failure -- the same unambiguous signal astbench gave before #1385. tests/format 31744 passed, 0 failed smoke 1497/1497 on both routes, 0 crashes, 315/315 dispatched Closes #1445.
7201 lines
278 KiB
C++
7201 lines
278 KiB
C++
/*! \file stringutil.cpp
|
|
* \brief String utility functions.
|
|
*
|
|
*/
|
|
|
|
#include "copyright.h"
|
|
#include "autoconf.h"
|
|
#include "config.h"
|
|
#include "core.h"
|
|
|
|
extern "C" {
|
|
#include "color_ops.h"
|
|
}
|
|
|
|
#include <math.h>
|
|
|
|
bool g_no_flash = false;
|
|
bool g_space_compress = true;
|
|
|
|
UTF8 *DCL_CDECL tprintf(const UTF8 *fmt,...)
|
|
{
|
|
static UTF8 buff[LBUF_SIZE];
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
mux_vsnprintf(buff, LBUF_SIZE, fmt, ap);
|
|
va_end(ap);
|
|
return buff;
|
|
}
|
|
|
|
void DCL_CDECL safe_tprintf_str(UTF8 *str, UTF8 **bp, const UTF8 *fmt,...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
size_t nAvailable = LBUF_SIZE - (*bp - str);
|
|
size_t len = mux_vsnprintf(*bp, static_cast<int>(nAvailable), fmt, ap);
|
|
va_end(ap);
|
|
*bp += len;
|
|
}
|
|
|
|
#define PCRE2_CODE_UNIT_WIDTH 8
|
|
#include <pcre2.h>
|
|
using namespace std;
|
|
|
|
const bool mux_isprint_ascii[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
const bool mux_isprint_cp437[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, // 0
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 7
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
|
|
};
|
|
|
|
const bool mux_isprint_latin1[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 7
|
|
|
|
0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, // 8
|
|
0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, // 9
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
|
|
};
|
|
|
|
const bool mux_isprint_latin2[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
|
|
};
|
|
|
|
const bool mux_isdigit[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 3
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
const bool mux_isxdigit[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 3
|
|
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
|
|
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
const bool mux_isazAZ[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 5
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
const bool mux_isalnum[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 3
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 5
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
const bool mux_isupper_ascii[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 5
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
const bool mux_islower_ascii[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
const bool mux_isspace[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
// Characters which should be escaped for the secure()
|
|
// function: '%$\[](){},;'.
|
|
//
|
|
const bool mux_issecure[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, // 2
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, // 3
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, // 5
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
// Characters which should be escaped for the escape()
|
|
// function: '%\[]{};,()^$'.
|
|
//
|
|
const bool mux_isescape[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, // 2
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, // 3
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, // 5
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
const bool ANSI_TokenTerminatorTable[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 5
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
const unsigned char mux_hex2dec[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // 3
|
|
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
|
|
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
const unsigned char mux_toupper_ascii[UCHAR_MAX+1] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // 0
|
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, // 1
|
|
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, // 2
|
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, // 3
|
|
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, // 4
|
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, // 5
|
|
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, // 6
|
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, // 7
|
|
|
|
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, // 8
|
|
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, // 9
|
|
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, // A
|
|
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, // B
|
|
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, // C
|
|
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, // D
|
|
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, // E
|
|
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF // F
|
|
};
|
|
|
|
const unsigned char mux_tolower_ascii[UCHAR_MAX+1] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // 0
|
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, // 1
|
|
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, // 2
|
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, // 3
|
|
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, // 4
|
|
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, // 5
|
|
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, // 6
|
|
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, // 7
|
|
|
|
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, // 8
|
|
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, // 9
|
|
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, // A
|
|
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, // B
|
|
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, // C
|
|
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, // D
|
|
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, // E
|
|
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF // F
|
|
};
|
|
|
|
// This will help decode UTF-8 sequences.
|
|
//
|
|
// 0xxxxxxx ==> 00000000-01111111 ==> 00-7F 1 byte sequence.
|
|
// 10xxxxxx ==> 10000000-10111111 ==> 80-BF continue
|
|
// 110xxxxx ==> 11000000-11011111 ==> C0-DF 2 byte sequence.
|
|
// 1110xxxx ==> 11100000-11101111 ==> E0-EF 3 byte sequence.
|
|
// 11110xxx ==> 11110000-11110111 ==> F0-F7 4 byte sequence.
|
|
// 11111000-11111111 illegal
|
|
//
|
|
// Also, RFC 3629 specifies that 0xC0, 0xC1, and 0xF5-0xFF never
|
|
// appear in a valid sequence.
|
|
//
|
|
// The first byte gives the length of a sequence (UTF8_SIZE1 - UTF8_SIZE4).
|
|
// Bytes in the middle of a sequence map to UTF8_CONTINUE. Bytes which should
|
|
// not appear map to UTF8_ILLEGAL.
|
|
//
|
|
extern "C" const unsigned char utf8_FirstByte[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
|
|
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 8
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 9
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // A
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // B
|
|
6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // D
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // E
|
|
4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 // F
|
|
};
|
|
|
|
// Advance within a NUL-terminated UTF-8 string without stepping past '\0'.
|
|
// Invalid lead bytes are treated as single-byte units.
|
|
static size_t utf8_advance_nul(const UTF8 *p)
|
|
{
|
|
if (nullptr == p || '\0' == *p)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
size_t n = utf8_FirstByte[static_cast<unsigned char>(*p)];
|
|
if (n >= UTF8_CONTINUE)
|
|
{
|
|
n = UTF8_SIZE1;
|
|
}
|
|
for (size_t i = 1; i < n; i++)
|
|
{
|
|
if ('\0' == p[i] || UTF8_CONTINUE != utf8_FirstByte[p[i]])
|
|
{
|
|
return UTF8_SIZE1;
|
|
}
|
|
}
|
|
UTF32 cp = utf8_decode_raw(p, n);
|
|
if (!utf8_is_valid_scalar(cp, n))
|
|
{
|
|
return UTF8_SIZE1;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
// Advance within a UTF-8 byte span with explicit remaining length.
|
|
// Invalid/truncated/illegal scalars are treated as single-byte units.
|
|
static size_t utf8_advance_bounded(const UTF8 *p, size_t nAvail)
|
|
{
|
|
if (nullptr == p || 0 == nAvail)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
size_t n = utf8_FirstByte[static_cast<unsigned char>(*p)];
|
|
if (n < 1 || n >= UTF8_CONTINUE || n > nAvail)
|
|
{
|
|
return UTF8_SIZE1;
|
|
}
|
|
for (size_t i = 1; i < n; i++)
|
|
{
|
|
if (UTF8_CONTINUE != utf8_FirstByte[static_cast<unsigned char>(p[i])])
|
|
{
|
|
return UTF8_SIZE1;
|
|
}
|
|
}
|
|
|
|
UTF32 cp = utf8_decode_raw(p, n);
|
|
if (!utf8_is_valid_scalar(cp, n))
|
|
{
|
|
return UTF8_SIZE1;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
// The following table maps cp437 characters to their corresponding
|
|
// UTF8 sequences.
|
|
//
|
|
const UTF8 *cp437_utf8[256] =
|
|
{
|
|
T("\xE2\x80\x87"), T("\xE2\x98\xBA"), T("\xE2\x98\xBB"), T("\xE2\x99\xA5"),
|
|
T("\xE2\x99\xA6"), T("\xE2\x99\xA3"), T("\xE2\x99\xA0"), T("\xE2\x80\xA2"),
|
|
T("\xE2\x97\x98"), T("\xE2\x97\x8B"), T("\xE2\x97\x99"), T("\xE2\x99\x82"),
|
|
T("\xE2\x99\x80"), T("\xE2\x99\xAA"), T("\xE2\x99\xAB"), T("\xE2\x98\xBC"),
|
|
T("\xE2\x96\xBA"), T("\xE2\x97\x84"), T("\xE2\x86\x95"), T("\xE2\x80\xBC"),
|
|
T("\xC2\xB6"), T("\xC2\xA7"), T("\xE2\x96\xAC"), T("\xE2\x86\xA8"),
|
|
T("\xE2\x86\x91"), T("\xE2\x86\x93"), T("\xE2\x86\x92"), T("\xE2\x86\x90"),
|
|
T("\xE2\x88\x9F"), T("\xE2\x86\x94"), T("\xE2\x96\xB2"), T("\xE2\x96\xBC"),
|
|
T("\x20"), T("\x21"), T("\x22"), T("\x23"),
|
|
T("\x24"), T("\x25"), T("\x26"), T("\x27"),
|
|
T("\x28"), T("\x29"), T("\x2A"), T("\x2B"),
|
|
T("\x2C"), T("\x2D"), T("\x2E"), T("\x2F"),
|
|
T("\x30"), T("\x31"), T("\x32"), T("\x33"),
|
|
T("\x34"), T("\x35"), T("\x36"), T("\x37"),
|
|
T("\x38"), T("\x39"), T("\x3A"), T("\x3B"),
|
|
T("\x3C"), T("\x3D"), T("\x3E"), T("\x3F"),
|
|
T("\x40"), T("\x41"), T("\x42"), T("\x43"),
|
|
T("\x44"), T("\x45"), T("\x46"), T("\x47"),
|
|
T("\x48"), T("\x49"), T("\x4A"), T("\x4B"),
|
|
T("\x4C"), T("\x4D"), T("\x4E"), T("\x4F"),
|
|
T("\x50"), T("\x51"), T("\x52"), T("\x53"),
|
|
T("\x54"), T("\x55"), T("\x56"), T("\x57"),
|
|
T("\x58"), T("\x59"), T("\x5A"), T("\x5B"),
|
|
T("\x5C"), T("\x5D"), T("\x5E"), T("\x5F"),
|
|
T("\x60"), T("\x61"), T("\x62"), T("\x63"),
|
|
T("\x64"), T("\x65"), T("\x66"), T("\x67"),
|
|
T("\x68"), T("\x69"), T("\x6A"), T("\x6B"),
|
|
T("\x6C"), T("\x6D"), T("\x6E"), T("\x6F"),
|
|
T("\x70"), T("\x71"), T("\x72"), T("\x73"),
|
|
T("\x74"), T("\x75"), T("\x76"), T("\x77"),
|
|
T("\x78"), T("\x79"), T("\x7A"), T("\x7B"),
|
|
T("\x7C"), T("\x7D"), T("\x7E"), T("\x7F"),
|
|
T("\xC3\x87"), T("\xC3\xBC"), T("\xC3\xA9"), T("\xC3\xA2"),
|
|
T("\xC3\xA4"), T("\xC3\xA0"), T("\xC3\xA5"), T("\xC3\xA7"),
|
|
T("\xC3\xAA"), T("\xC3\xAB"), T("\xC3\xA8"), T("\xC3\xAF"),
|
|
T("\xC3\xAE"), T("\xC3\xAC"), T("\xC3\x84"), T("\xC3\x85"),
|
|
T("\xC3\x89"), T("\xC3\xA6"), T("\xC3\x86"), T("\xC3\xB4"),
|
|
T("\xC3\xB6"), T("\xC3\xB2"), T("\xC3\xBB"), T("\xC3\xB9"),
|
|
T("\xC3\xBF"), T("\xC3\x96"), T("\xC3\x9C"), T("\xC2\xA2"),
|
|
T("\xC2\xA3"), T("\xC2\xA5"), T("\xE2\x82\xA7"), T("\xC6\x92"),
|
|
T("\xC3\xA1"), T("\xC3\xAD"), T("\xC3\xB3"), T("\xC3\xBA"),
|
|
T("\xC3\xB1"), T("\xC3\x91"), T("\xC2\xAA"), T("\xC2\xBA"),
|
|
T("\xC2\xBF"), T("\xE2\x8C\x90"), T("\xC2\xAC"), T("\xC2\xBD"),
|
|
T("\xC2\xBC"), T("\xC2\xA1"), T("\xC2\xAB"), T("\xC2\xBB"),
|
|
T("\xE2\x96\x91"), T("\xE2\x96\x92"), T("\xE2\x96\x93"), T("\xE2\x94\x82"),
|
|
T("\xE2\x94\xA4"), T("\xE2\x95\xA1"), T("\xE2\x95\xA2"), T("\xE2\x95\x96"),
|
|
T("\xE2\x95\x95"), T("\xE2\x95\xA3"), T("\xE2\x95\x91"), T("\xE2\x95\x97"),
|
|
T("\xE2\x95\x9D"), T("\xE2\x95\x9C"), T("\xE2\x95\x9B"), T("\xE2\x94\x90"),
|
|
T("\xE2\x94\x94"), T("\xE2\x94\xB4"), T("\xE2\x94\xAC"), T("\xE2\x94\x9C"),
|
|
T("\xE2\x94\x80"), T("\xE2\x94\xBC"), T("\xE2\x95\x9E"), T("\xE2\x95\x9F"),
|
|
T("\xE2\x95\x9A"), T("\xE2\x95\x94"), T("\xE2\x95\xA9"), T("\xE2\x95\xA6"),
|
|
T("\xE2\x95\xA0"), T("\xE2\x95\x90"), T("\xE2\x95\xAC"), T("\xE2\x95\xA7"),
|
|
T("\xE2\x95\xA8"), T("\xE2\x95\xA4"), T("\xE2\x95\xA5"), T("\xE2\x95\x99"),
|
|
T("\xE2\x95\x98"), T("\xE2\x95\x92"), T("\xE2\x95\x93"), T("\xE2\x95\xAB"),
|
|
T("\xE2\x95\xAA"), T("\xE2\x94\x98"), T("\xE2\x94\x8C"), T("\xE2\x96\x88"),
|
|
T("\xE2\x96\x84"), T("\xE2\x96\x8C"), T("\xE2\x96\x90"), T("\xE2\x96\x80"),
|
|
T("\xCE\xB1"), T("\xC3\x9F"), T("\xCE\x93"), T("\xCF\x80"),
|
|
T("\xCE\xA3"), T("\xCF\x83"), T("\xC2\xB5"), T("\xCF\x84"),
|
|
T("\xCE\xA6"), T("\xCE\x98"), T("\xCE\xA9"), T("\xCE\xB4"),
|
|
T("\xE2\x88\x9E"), T("\xCF\x86"), T("\xCE\xB5"), T("\xE2\x88\xA9"),
|
|
T("\xE2\x89\xA1"), T("\xC2\xB1"), T("\xE2\x89\xA5"), T("\xE2\x89\xA4"),
|
|
T("\xE2\x8C\xA0"), T("\xE2\x8C\xA1"), T("\xC3\xB7"), T("\xE2\x89\x88"),
|
|
T("\xC2\xB0"), T("\xE2\x88\x99"), T("\xC2\xB7"), T("\xE2\x88\x9A"),
|
|
T("\xE2\x81\xBF"), T("\xC2\xB2"), T("\xE2\x96\xA0"), T("\xC2\xA0"),
|
|
};
|
|
|
|
// The following table maps existing 8-bit characters to their corresponding
|
|
// UTF8 sequences.
|
|
//
|
|
const UTF8 *latin1_utf8[256] =
|
|
{
|
|
T(""), T("\x01"), T("\x02"), T("\x03"),
|
|
T("\x04"), T("\x05"), T("\x06"), T("\x07"),
|
|
T("\x08"), T("\x09"), T("\x0A"), T("\x0B"),
|
|
T("\x0C"), T("\x0D"), T("\x0E"), T("\x0F"),
|
|
T("\x10"), T("\x11"), T("\x12"), T("\x13"),
|
|
T("\x14"), T("\x15"), T("\x16"), T("\x17"),
|
|
T("\x18"), T("\x19"), T("\x1A"), T("\x1B"),
|
|
T("\x1C"), T("\x1D"), T("\x1E"), T("\x1F"),
|
|
T("\x20"), T("\x21"), T("\x22"), T("\x23"),
|
|
T("\x24"), T("\x25"), T("\x26"), T("\x27"),
|
|
T("\x28"), T("\x29"), T("\x2A"), T("\x2B"),
|
|
T("\x2C"), T("\x2D"), T("\x2E"), T("\x2F"),
|
|
T("\x30"), T("\x31"), T("\x32"), T("\x33"),
|
|
T("\x34"), T("\x35"), T("\x36"), T("\x37"),
|
|
T("\x38"), T("\x39"), T("\x3A"), T("\x3B"),
|
|
T("\x3C"), T("\x3D"), T("\x3E"), T("\x3F"),
|
|
T("\x40"), T("\x41"), T("\x42"), T("\x43"),
|
|
T("\x44"), T("\x45"), T("\x46"), T("\x47"),
|
|
T("\x48"), T("\x49"), T("\x4A"), T("\x4B"),
|
|
T("\x4C"), T("\x4D"), T("\x4E"), T("\x4F"),
|
|
T("\x50"), T("\x51"), T("\x52"), T("\x53"),
|
|
T("\x54"), T("\x55"), T("\x56"), T("\x57"),
|
|
T("\x58"), T("\x59"), T("\x5A"), T("\x5B"),
|
|
T("\x5C"), T("\x5D"), T("\x5E"), T("\x5F"),
|
|
T("\x60"), T("\x61"), T("\x62"), T("\x63"),
|
|
T("\x64"), T("\x65"), T("\x66"), T("\x67"),
|
|
T("\x68"), T("\x69"), T("\x6A"), T("\x6B"),
|
|
T("\x6C"), T("\x6D"), T("\x6E"), T("\x6F"),
|
|
T("\x70"), T("\x71"), T("\x72"), T("\x73"),
|
|
T("\x74"), T("\x75"), T("\x76"), T("\x77"),
|
|
T("\x78"), T("\x79"), T("\x7A"), T("\x7B"),
|
|
T("\x7C"), T("\x7D"), T("\x7E"), T("\x7F"),
|
|
T("\xE2\x82\xAC"), T("\xEF\xBF\xBD"), T("\xE2\x80\x9A"), T("\xC6\x92"),
|
|
T("\xE2\x80\x9E"), T("\xE2\x80\xA6"), T("\xE2\x80\xA0"), T("\xE2\x80\xA1"),
|
|
T("\xCB\x86"), T("\xE2\x80\xB0"), T("\xC5\xA0"), T("\xE2\x80\xB9"),
|
|
T("\xC5\x92"), T("\xEF\xBF\xBD"), T("\xC5\xBD"), T("\xEF\xBF\xBD"),
|
|
T("\xEF\xBF\xBD"), T("\xE2\x80\x98"), T("\xE2\x80\x99"), T("\xE2\x80\x9C"),
|
|
T("\xE2\x80\x9D"), T("\xE2\x80\xA2"), T("\xE2\x80\x93"), T("\xE2\x80\x94"),
|
|
T("\xCB\x9C"), T("\xE2\x84\xA2"), T("\xC5\xA1"), T("\xE2\x80\xBA"),
|
|
T("\xC5\x93"), T("\xEF\xBF\xBD"), T("\xC5\xBE"), T("\xC5\xB8"),
|
|
T("\xC2\xA0"), T("\xC2\xA1"), T("\xC2\xA2"), T("\xC2\xA3"),
|
|
T("\xC2\xA4"), T("\xC2\xA5"), T("\xC2\xA6"), T("\xC2\xA7"),
|
|
T("\xC2\xA8"), T("\xC2\xA9"), T("\xC2\xAA"), T("\xC2\xAB"),
|
|
T("\xC2\xAC"), T("\xC2\xAD"), T("\xC2\xAE"), T("\xC2\xAF"),
|
|
T("\xC2\xB0"), T("\xC2\xB1"), T("\xC2\xB2"), T("\xC2\xB3"),
|
|
T("\xC2\xB4"), T("\xC2\xB5"), T("\xC2\xB6"), T("\xC2\xB7"),
|
|
T("\xC2\xB8"), T("\xC2\xB9"), T("\xC2\xBA"), T("\xC2\xBB"),
|
|
T("\xC2\xBC"), T("\xC2\xBD"), T("\xC2\xBE"), T("\xC2\xBF"),
|
|
T("\xC3\x80"), T("\xC3\x81"), T("\xC3\x82"), T("\xC3\x83"),
|
|
T("\xC3\x84"), T("\xC3\x85"), T("\xC3\x86"), T("\xC3\x87"),
|
|
T("\xC3\x88"), T("\xC3\x89"), T("\xC3\x8A"), T("\xC3\x8B"),
|
|
T("\xC3\x8C"), T("\xC3\x8D"), T("\xC3\x8E"), T("\xC3\x8F"),
|
|
T("\xC3\x90"), T("\xC3\x91"), T("\xC3\x92"), T("\xC3\x93"),
|
|
T("\xC3\x94"), T("\xC3\x95"), T("\xC3\x96"), T("\xC3\x97"),
|
|
T("\xC3\x98"), T("\xC3\x99"), T("\xC3\x9A"), T("\xC3\x9B"),
|
|
T("\xC3\x9C"), T("\xC3\x9D"), T("\xC3\x9E"), T("\xC3\x9F"),
|
|
T("\xC3\xA0"), T("\xC3\xA1"), T("\xC3\xA2"), T("\xC3\xA3"),
|
|
T("\xC3\xA4"), T("\xC3\xA5"), T("\xC3\xA6"), T("\xC3\xA7"),
|
|
T("\xC3\xA8"), T("\xC3\xA9"), T("\xC3\xAA"), T("\xC3\xAB"),
|
|
T("\xC3\xAC"), T("\xC3\xAD"), T("\xC3\xAE"), T("\xC3\xAF"),
|
|
T("\xC3\xB0"), T("\xC3\xB1"), T("\xC3\xB2"), T("\xC3\xB3"),
|
|
T("\xC3\xB4"), T("\xC3\xB5"), T("\xC3\xB6"), T("\xC3\xB7"),
|
|
T("\xC3\xB8"), T("\xC3\xB9"), T("\xC3\xBA"), T("\xC3\xBB"),
|
|
T("\xC3\xBC"), T("\xC3\xBD"), T("\xC3\xBE"), T("\xC3\xBF"),
|
|
};
|
|
|
|
// The following table maps latin2 characters to their corresponding
|
|
// UTF8 sequences.
|
|
//
|
|
const UTF8 *latin2_utf8[256] =
|
|
{
|
|
T(""), T("\x01"), T("\x02"), T("\x03"),
|
|
T("\x04"), T("\x05"), T("\x06"), T("\x07"),
|
|
T("\x08"), T("\x09"), T("\x0A"), T("\x0B"),
|
|
T("\x0C"), T("\x0D"), T("\x0E"), T("\x0F"),
|
|
T("\x10"), T("\x11"), T("\x12"), T("\x13"),
|
|
T("\x14"), T("\x15"), T("\x16"), T("\x17"),
|
|
T("\x18"), T("\x19"), T("\x1A"), T("\x1B"),
|
|
T("\x1C"), T("\x1D"), T("\x1E"), T("\x1F"),
|
|
T("\x20"), T("\x21"), T("\x22"), T("\x23"),
|
|
T("\x24"), T("\x25"), T("\x26"), T("\x27"),
|
|
T("\x28"), T("\x29"), T("\x2A"), T("\x2B"),
|
|
T("\x2C"), T("\x2D"), T("\x2E"), T("\x2F"),
|
|
T("\x30"), T("\x31"), T("\x32"), T("\x33"),
|
|
T("\x34"), T("\x35"), T("\x36"), T("\x37"),
|
|
T("\x38"), T("\x39"), T("\x3A"), T("\x3B"),
|
|
T("\x3C"), T("\x3D"), T("\x3E"), T("\x3F"),
|
|
T("\x40"), T("\x41"), T("\x42"), T("\x43"),
|
|
T("\x44"), T("\x45"), T("\x46"), T("\x47"),
|
|
T("\x48"), T("\x49"), T("\x4A"), T("\x4B"),
|
|
T("\x4C"), T("\x4D"), T("\x4E"), T("\x4F"),
|
|
T("\x50"), T("\x51"), T("\x52"), T("\x53"),
|
|
T("\x54"), T("\x55"), T("\x56"), T("\x57"),
|
|
T("\x58"), T("\x59"), T("\x5A"), T("\x5B"),
|
|
T("\x5C"), T("\x5D"), T("\x5E"), T("\x5F"),
|
|
T("\x60"), T("\x61"), T("\x62"), T("\x63"),
|
|
T("\x64"), T("\x65"), T("\x66"), T("\x67"),
|
|
T("\x68"), T("\x69"), T("\x6A"), T("\x6B"),
|
|
T("\x6C"), T("\x6D"), T("\x6E"), T("\x6F"),
|
|
T("\x70"), T("\x71"), T("\x72"), T("\x73"),
|
|
T("\x74"), T("\x75"), T("\x76"), T("\x77"),
|
|
T("\x78"), T("\x79"), T("\x7A"), T("\x7B"),
|
|
T("\x7C"), T("\x7D"), T("\x7E"), T("\x7F"),
|
|
T("\xC2\x80"), T("\xC2\x81"), T("\xC2\x82"), T("\xC2\x83"),
|
|
T("\xC2\x84"), T("\xC2\x85"), T("\xC2\x86"), T("\xC2\x87"),
|
|
T("\xC2\x88"), T("\xC2\x89"), T("\xC2\x8A"), T("\xC2\x8B"),
|
|
T("\xC2\x8C"), T("\xC2\x8D"), T("\xC2\x8E"), T("\xC2\x8F"),
|
|
T("\xC2\x90"), T("\xC2\x91"), T("\xC2\x92"), T("\xC2\x93"),
|
|
T("\xC2\x94"), T("\xC2\x95"), T("\xC2\x96"), T("\xC2\x97"),
|
|
T("\xC2\x98"), T("\xC2\x99"), T("\xC2\x9A"), T("\xC2\x9B"),
|
|
T("\xC2\x9C"), T("\xC2\x9D"), T("\xC2\x9E"), T("\xC2\x9F"),
|
|
T("\xC2\xA0"), T("\xC4\x84"), T("\xCB\x98"), T("\xC5\x81"),
|
|
T("\xC2\xA4"), T("\xC4\xBD"), T("\xC5\x9A"), T("\xC2\xA7"),
|
|
T("\xC2\xA8"), T("\xC5\xA0"), T("\xC5\x9E"), T("\xC5\xA4"),
|
|
T("\xC5\xB9"), T("\xC2\xAD"), T("\xC5\xBD"), T("\xC5\xBB"),
|
|
T("\xC2\xB0"), T("\xC4\x85"), T("\xCB\x9B"), T("\xC5\x82"),
|
|
T("\xC2\xB4"), T("\xC4\xBE"), T("\xC5\x9B"), T("\xCB\x87"),
|
|
T("\xC2\xB8"), T("\xC5\xA1"), T("\xC5\x9F"), T("\xC5\xA5"),
|
|
T("\xC5\xBA"), T("\xCB\x9D"), T("\xC5\xBE"), T("\xC5\xBC"),
|
|
T("\xC5\x94"), T("\xC3\x81"), T("\xC3\x82"), T("\xC4\x82"),
|
|
T("\xC3\x84"), T("\xC4\xB9"), T("\xC4\x86"), T("\xC3\x87"),
|
|
T("\xC4\x8C"), T("\xC3\x89"), T("\xC4\x98"), T("\xC3\x8B"),
|
|
T("\xC4\x9A"), T("\xC3\x8D"), T("\xC3\x8E"), T("\xC4\x8E"),
|
|
T("\xC4\x90"), T("\xC5\x83"), T("\xC5\x87"), T("\xC3\x93"),
|
|
T("\xC3\x94"), T("\xC5\x90"), T("\xC3\x96"), T("\xC3\x97"),
|
|
T("\xC5\x98"), T("\xC5\xAE"), T("\xC3\x9A"), T("\xC5\xB0"),
|
|
T("\xC3\x9C"), T("\xC3\x9D"), T("\xC5\xA2"), T("\xC3\x9F"),
|
|
T("\xC5\x95"), T("\xC3\xA1"), T("\xC3\xA2"), T("\xC4\x83"),
|
|
T("\xC3\xA4"), T("\xC4\xBA"), T("\xC4\x87"), T("\xC3\xA7"),
|
|
T("\xC4\x8D"), T("\xC3\xA9"), T("\xC4\x99"), T("\xC3\xAB"),
|
|
T("\xC4\x9B"), T("\xC3\xAD"), T("\xC3\xAE"), T("\xC4\x8F"),
|
|
T("\xC4\x91"), T("\xC5\x84"), T("\xC5\x88"), T("\xC3\xB3"),
|
|
T("\xC3\xB4"), T("\xC5\x91"), T("\xC3\xB6"), T("\xC3\xB7"),
|
|
T("\xC5\x99"), T("\xC5\xAF"), T("\xC3\xBA"), T("\xC5\xB1"),
|
|
T("\xC3\xBC"), T("\xC3\xBD"), T("\xC5\xA3"), T("\xCB\x99"),
|
|
};
|
|
|
|
/*! \brief Validates UTF8 string and returns number of code points contained therein.
|
|
*
|
|
* \param pString UTF8 string.
|
|
* \param nString Resulting number of code points in pString.
|
|
* \return true for valid, false for invalid.
|
|
*/
|
|
|
|
bool utf8_strlen(const UTF8 *pString, size_t &nString)
|
|
{
|
|
nString = 0;
|
|
int i = 0;
|
|
while ('\0' != pString[i])
|
|
{
|
|
unsigned char t = utf8_FirstByte[pString[i]];
|
|
if (UTF8_CONTINUE <= t)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int j;
|
|
for (j = i + 1; j < i + t; j++)
|
|
{
|
|
if ( '\0' == pString[j]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[pString[j]])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
UTF32 cp = utf8_decode_raw(pString + i, t);
|
|
if (!utf8_is_valid_scalar(cp, t))
|
|
{
|
|
return false;
|
|
}
|
|
nString++;
|
|
i = i + t;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool utf8_strlen(const UTF8 *pString, mux_cursor &nString)
|
|
{
|
|
LBUF_OFFSET nPoints = 0;
|
|
LBUF_OFFSET nBytes = 0;
|
|
while ('\0' != pString[nBytes])
|
|
{
|
|
unsigned char t = utf8_FirstByte[pString[nBytes]];
|
|
if (UTF8_CONTINUE <= t)
|
|
{
|
|
nString(nBytes, nPoints);
|
|
return false;
|
|
}
|
|
|
|
int j;
|
|
for (j = nBytes + 1; j < nBytes + t; j++)
|
|
{
|
|
if ( '\0' == pString[j]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[pString[j]])
|
|
{
|
|
nString(nBytes, nPoints);
|
|
return false;
|
|
}
|
|
}
|
|
UTF32 cp = utf8_decode_raw(pString + nBytes, t);
|
|
if (!utf8_is_valid_scalar(cp, t))
|
|
{
|
|
nString(nBytes, nPoints);
|
|
return false;
|
|
}
|
|
nPoints++;
|
|
nBytes = nBytes + t;
|
|
}
|
|
nString(nBytes, nPoints);
|
|
return true;
|
|
}
|
|
|
|
/*! \brief Convert UTF8 to ASCII with '?' for all unsupported characters.
|
|
*
|
|
* \param pString UTF8 string.
|
|
* \return Equivalent string in ASCII codeset.
|
|
*/
|
|
|
|
const UTF8 *ConvertToAscii(const UTF8 *pString)
|
|
{
|
|
static UTF8 buffer[2*LBUF_SIZE];
|
|
UTF8 *q = buffer;
|
|
|
|
while ('\0' != *pString)
|
|
{
|
|
*q++ = static_cast<UTF8>(co_dfa_ascii(pString));
|
|
pString += utf8_advance_nul(pString);
|
|
}
|
|
*q = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
/*! \brief Convert UTF8 to cp437 with '?' for all unsupported characters.
|
|
*
|
|
* \param pString UTF8 string.
|
|
* \return Equivalent string in latin1 codeset.
|
|
*/
|
|
|
|
const UTF8 *ConvertToCp437(const UTF8 *pString)
|
|
{
|
|
static UTF8 buffer[2*LBUF_SIZE];
|
|
UTF8 *q = buffer;
|
|
|
|
while ( '\0' != *pString
|
|
&& q < buffer + sizeof(buffer) - 1)
|
|
{
|
|
const UTF8 *p = pString;
|
|
int iState = TR_CP437_START_STATE;
|
|
do
|
|
{
|
|
UTF8 ch = *p++;
|
|
unsigned char iColumn = tr_cp437_itt[static_cast<unsigned char>(ch)];
|
|
unsigned short iOffset = tr_cp437_sot[iState];
|
|
for (;;)
|
|
{
|
|
int y = tr_cp437_sbt[iOffset];
|
|
if (y < 128)
|
|
{
|
|
// RUN phrase.
|
|
//
|
|
if (iColumn < y)
|
|
{
|
|
iState = tr_cp437_sbt[iOffset+1];
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iColumn = static_cast<unsigned char>(iColumn - y);
|
|
iOffset += 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// COPY phrase.
|
|
//
|
|
y = 256-y;
|
|
if (iColumn < y)
|
|
{
|
|
iState = tr_cp437_sbt[iOffset+iColumn+1];
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iColumn = static_cast<unsigned char>(iColumn - y);
|
|
iOffset = static_cast<unsigned short>(iOffset + y + 1);
|
|
}
|
|
}
|
|
}
|
|
} while (iState < TR_CP437_ACCEPTING_STATES_START);
|
|
*q++ = static_cast<char>(iState - TR_CP437_ACCEPTING_STATES_START);
|
|
pString += utf8_advance_nul(pString);
|
|
}
|
|
*q = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
/*! \brief Convert UTF8 to latin1 with '?' for all unsupported characters.
|
|
*
|
|
* \param pString UTF8 string.
|
|
* \return Equivalent string in latin1 codeset.
|
|
*/
|
|
|
|
const UTF8 *ConvertToLatin1(const UTF8 *pString)
|
|
{
|
|
static UTF8 buffer[2*LBUF_SIZE];
|
|
UTF8 *q = buffer;
|
|
|
|
while ( '\0' != *pString
|
|
&& q < buffer + sizeof(buffer) - 1)
|
|
{
|
|
const UTF8 *p = pString;
|
|
int iState = TR_LATIN1_START_STATE;
|
|
do
|
|
{
|
|
UTF8 ch = *p++;
|
|
unsigned char iColumn = tr_latin1_itt[static_cast<unsigned char>(ch)];
|
|
unsigned short iOffset = tr_latin1_sot[iState];
|
|
for (;;)
|
|
{
|
|
int y = tr_latin1_sbt[iOffset];
|
|
if (y < 128)
|
|
{
|
|
// RUN phrase.
|
|
//
|
|
if (iColumn < y)
|
|
{
|
|
iState = tr_latin1_sbt[iOffset+1];
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iColumn = static_cast<unsigned char>(iColumn - y);
|
|
iOffset += 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// COPY phrase.
|
|
//
|
|
y = 256-y;
|
|
if (iColumn < y)
|
|
{
|
|
iState = tr_latin1_sbt[iOffset+iColumn+1];
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iColumn = static_cast<unsigned char>(iColumn - y);
|
|
iOffset = static_cast<unsigned short>(iOffset + y + 1);
|
|
}
|
|
}
|
|
}
|
|
} while (iState < TR_LATIN1_ACCEPTING_STATES_START);
|
|
*q++ = static_cast<char>(iState - TR_LATIN1_ACCEPTING_STATES_START);
|
|
pString += utf8_advance_nul(pString);
|
|
}
|
|
*q = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
/*! \brief Convert UTF8 to latin2 with '?' for all unsupported characters.
|
|
*
|
|
* \param pString UTF8 string.
|
|
* \return Equivalent string in latin1 codeset.
|
|
*/
|
|
|
|
const UTF8 *ConvertToLatin2(const UTF8 *pString)
|
|
{
|
|
static UTF8 buffer[2*LBUF_SIZE];
|
|
UTF8 *q = buffer;
|
|
|
|
while ( '\0' != *pString
|
|
&& q < buffer + sizeof(buffer) - 1)
|
|
{
|
|
const UTF8 *p = pString;
|
|
int iState = TR_LATIN2_START_STATE;
|
|
do
|
|
{
|
|
UTF8 ch = *p++;
|
|
unsigned char iColumn = tr_latin2_itt[static_cast<unsigned char>(ch)];
|
|
unsigned short iOffset = tr_latin2_sot[iState];
|
|
for (;;)
|
|
{
|
|
int y = tr_latin2_sbt[iOffset];
|
|
if (y < 128)
|
|
{
|
|
// RUN phrase.
|
|
//
|
|
if (iColumn < y)
|
|
{
|
|
iState = tr_latin2_sbt[iOffset+1];
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iColumn = static_cast<unsigned char>(iColumn - y);
|
|
iOffset += 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// COPY phrase.
|
|
//
|
|
y = 256-y;
|
|
if (iColumn < y)
|
|
{
|
|
iState = tr_latin2_sbt[iOffset+iColumn+1];
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iColumn = static_cast<unsigned char>(iColumn - y);
|
|
iOffset = static_cast<unsigned short>(iOffset + y + 1);
|
|
}
|
|
}
|
|
}
|
|
} while (iState < TR_LATIN2_ACCEPTING_STATES_START);
|
|
*q++ = static_cast<char>(iState - TR_LATIN2_ACCEPTING_STATES_START);
|
|
pString += utf8_advance_nul(pString);
|
|
}
|
|
*q = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
/*! \brief Return ConsoleWidth property for single code point.
|
|
*
|
|
* \param pCodePoint UTF8 string.
|
|
* \return Width to allow in formatting.
|
|
*/
|
|
|
|
int ConsoleWidth(const UTF8 *pCodePoint)
|
|
{
|
|
const UTF8 *p = pCodePoint;
|
|
int iState = TR_WIDTHS_START_STATE;
|
|
do
|
|
{
|
|
unsigned char ch = *p++;
|
|
unsigned char iColumn = tr_widths_itt[static_cast<unsigned char>(ch)];
|
|
unsigned short iOffset = tr_widths_sot[iState];
|
|
for (;;)
|
|
{
|
|
int y = tr_widths_sbt[iOffset];
|
|
if (y < 128)
|
|
{
|
|
// RUN phrase.
|
|
//
|
|
if (iColumn < y)
|
|
{
|
|
iState = tr_widths_sbt[iOffset+1];
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iColumn = static_cast<unsigned char>(iColumn - y);
|
|
iOffset += 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// COPY phrase.
|
|
//
|
|
y = 256-y;
|
|
if (iColumn < y)
|
|
{
|
|
iState = tr_widths_sbt[iOffset+iColumn+1];
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iColumn = static_cast<unsigned char>(iColumn - y);
|
|
iOffset = static_cast<unsigned short>(iOffset + y + 1);
|
|
}
|
|
}
|
|
}
|
|
} while (iState < TR_WIDTHS_ACCEPTING_STATES_START);
|
|
return (iState - TR_WIDTHS_ACCEPTING_STATES_START);
|
|
}
|
|
|
|
// C-callable wrapper for use from color_ops.c (libmux.so internal).
|
|
//
|
|
extern "C" LIBMUX_API int co_console_width(const unsigned char *pCodePoint)
|
|
{
|
|
return ConsoleWidth(pCodePoint);
|
|
}
|
|
|
|
// ColorTable — maps ASCII characters to color index flags.
|
|
//
|
|
const unsigned int ColorTable[256] =
|
|
{
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00-0x0F
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10-0x1F
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20-0x2F
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x30-0x3F
|
|
|
|
// 0x40-0x47
|
|
0,
|
|
0,
|
|
COLOR_INDEX_BG + COLOR_INDEX_BLUE,
|
|
COLOR_INDEX_BG + COLOR_INDEX_CYAN,
|
|
0,
|
|
0,
|
|
0,
|
|
COLOR_INDEX_BG + COLOR_INDEX_GREEN,
|
|
|
|
// 0x48-0x4F
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
COLOR_INDEX_BG + COLOR_INDEX_MAGENTA,
|
|
0,
|
|
0,
|
|
|
|
// 0x50-0x57
|
|
//
|
|
0,
|
|
0,
|
|
COLOR_INDEX_BG + COLOR_INDEX_RED,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
COLOR_INDEX_BG + COLOR_INDEX_WHITE,
|
|
|
|
// 0x58-0x5F
|
|
//
|
|
COLOR_INDEX_BG + COLOR_INDEX_BLACK,
|
|
COLOR_INDEX_BG + COLOR_INDEX_YELLOW,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
|
|
// 0x60-0x67
|
|
0,
|
|
0,
|
|
COLOR_INDEX_FG + COLOR_INDEX_BLUE,
|
|
COLOR_INDEX_FG + COLOR_INDEX_CYAN,
|
|
0,
|
|
0,
|
|
COLOR_INDEX_BLINK,
|
|
COLOR_INDEX_FG + COLOR_INDEX_GREEN,
|
|
|
|
// 0x68-0x6F
|
|
//
|
|
COLOR_INDEX_INTENSE,
|
|
COLOR_INDEX_INVERSE,
|
|
0,
|
|
0,
|
|
0,
|
|
COLOR_INDEX_FG + COLOR_INDEX_MAGENTA,
|
|
COLOR_INDEX_RESET,
|
|
0,
|
|
|
|
// 0x70-0x77
|
|
//
|
|
0,
|
|
0,
|
|
COLOR_INDEX_FG + COLOR_INDEX_RED,
|
|
0,
|
|
0,
|
|
COLOR_INDEX_UNDERLINE,
|
|
0,
|
|
COLOR_INDEX_FG + COLOR_INDEX_WHITE,
|
|
|
|
// 0x78-0x7F
|
|
//
|
|
COLOR_INDEX_FG + COLOR_INDEX_BLACK,
|
|
COLOR_INDEX_FG + COLOR_INDEX_YELLOW,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80-0x8F
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90-0x9F
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0-0xAF
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xB0-0xBF
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0-0xCF
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xD0-0xDF
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0-0xEF
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xF0-0xFF
|
|
};
|
|
|
|
bool parse_rgb(size_t n, const UTF8 *p, RGB &rgb)
|
|
{
|
|
UTF8 ch;
|
|
if ( 7 == n
|
|
&& '#' == p[0])
|
|
{
|
|
// Look for RRGGBB in hexidecimal.
|
|
//
|
|
for (int i = 1; i < 7; i++)
|
|
{
|
|
ch = p[i];
|
|
if ( !('0' <= ch && ch <= '9')
|
|
&& !('a' <= ch && ch <= 'f')
|
|
&& !('A' <= ch && ch <= 'F'))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
rgb.r = (mux_hex2dec(p[1]) << 4) | mux_hex2dec(p[2]);
|
|
rgb.g = (mux_hex2dec(p[3]) << 4) | mux_hex2dec(p[4]);
|
|
rgb.b = (mux_hex2dec(p[5]) << 4) | mux_hex2dec(p[6]);
|
|
return true;
|
|
}
|
|
|
|
int nSpaces = 0;
|
|
int nDigits = 0;
|
|
for (size_t i = 0; i < n; i++)
|
|
{
|
|
ch = p[i];
|
|
if (mux_isspace(ch))
|
|
{
|
|
if ( 3 < nDigits
|
|
|| 0 == nDigits
|
|
|| 1 < nSpaces)
|
|
{
|
|
return false;
|
|
}
|
|
if (0 == nSpaces)
|
|
{
|
|
rgb.r = mux_atoi64(p+i-nDigits);
|
|
if (rgb.r < 0 || 255 < rgb.r)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rgb.g = mux_atoi64(p+i-nDigits);
|
|
if (rgb.g < 0 || 255 < rgb.g)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
nDigits = 0;
|
|
nSpaces++;
|
|
}
|
|
else if (!mux_isdigit(ch))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
nDigits++;
|
|
}
|
|
}
|
|
if ( 3 < nDigits
|
|
|| 0 == nDigits
|
|
|| 2 != nSpaces)
|
|
{
|
|
return false;
|
|
}
|
|
rgb.b = mux_atoi64(p+n-nDigits-1);
|
|
if (rgb.b < 0 || 255 < rgb.b)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// sRGB to CIELAB conversion (D65 illuminant)
|
|
//
|
|
// Pipeline: sRGB (0-255) -> linear RGB (0-1) -> XYZ (D65) -> CIELAB
|
|
// Output is integer-scaled: L*100, a*100, b*100
|
|
//
|
|
static inline double srgb_to_linear(int c)
|
|
{
|
|
double v = c / 255.0;
|
|
return (v <= 0.04045) ? v / 12.92 : pow((v + 0.055) / 1.055, 2.4);
|
|
}
|
|
|
|
static inline double cie_f(double t)
|
|
{
|
|
return (t > 0.008856) ? cbrt(t) : 7.787 * t + 16.0 / 116.0;
|
|
}
|
|
|
|
inline void rgb2lab(RGB *rgb, LABi *labi)
|
|
{
|
|
double lr = srgb_to_linear(rgb->r);
|
|
double lg = srgb_to_linear(rgb->g);
|
|
double lb = srgb_to_linear(rgb->b);
|
|
|
|
double x = (lr * 0.4124564 + lg * 0.3575761 + lb * 0.1804375) / 0.95047;
|
|
double y = (lr * 0.2126729 + lg * 0.7151522 + lb * 0.0721750) / 1.00000;
|
|
double z = (lr * 0.0193339 + lg * 0.1191920 + lb * 0.9503041) / 1.08883;
|
|
|
|
double fx = cie_f(x), fy = cie_f(y), fz = cie_f(z);
|
|
|
|
double L = 116.0 * fy - 16.0;
|
|
double a = 500.0 * (fx - fy);
|
|
double b = 200.0 * (fy - fz);
|
|
|
|
labi->L = static_cast<int>(L * 100.0 + 0.5);
|
|
labi->a = static_cast<int>(a * 100.0 + (a >= 0 ? 0.5 : -0.5));
|
|
labi->b = static_cast<int>(b * 100.0 + (b >= 0 ? 0.5 : -0.5));
|
|
}
|
|
|
|
inline void cs2rgb(ColorState cs, RGB *rgb)
|
|
{
|
|
rgb->r = static_cast<int>((cs & 0xFF0000) >> 16);
|
|
rgb->g = static_cast<int>((cs & 0x00FF00) >> 8);
|
|
rgb->b = static_cast<int>((cs & 0x0000FF));
|
|
}
|
|
|
|
inline ColorState rgb2cs(RGB *rgb)
|
|
{
|
|
ColorState cs;
|
|
cs = (static_cast<ColorState>(rgb->r) << 16)
|
|
| (static_cast<ColorState>(rgb->g) << 8)
|
|
| (static_cast<ColorState>(rgb->b));
|
|
return cs;
|
|
}
|
|
|
|
// All 256 entries of the palette are included in this table, but the palette
|
|
// is divided into two non-overlapping trees -- one for when xterm is supported,
|
|
// and one for when it is not.
|
|
//
|
|
// Since elements 0 through 15 do not have dependable RGB vales, we usually
|
|
// avoid using them when we have xterm support. xterm uses the values below,
|
|
// but other clients do not, and these values are usually user-configurable.
|
|
// However, if we are forced to map to the 16-color palette, the 16-color tree
|
|
// is used.
|
|
//
|
|
#define PALETTE16_ROOT 2
|
|
#define PALETTE256_ROOT 72
|
|
#define PALETTE_SIZE (sizeof(palette)/sizeof(palette[0]))
|
|
PALETTE_ENTRY palette[] =
|
|
{
|
|
{ { 0, 0, 0 }, { 0, 0, 0 }, { 12, 8 }, 0, 0},
|
|
{ { 187, 0, 0 }, { 3884, 6344, 5323 }, { 0, 5 }, 1, 1},
|
|
{ { 0, 187, 0 }, { 6617, -6826, 6588 }, { 1, 11 }, 2, 2},
|
|
{ { 187, 187, 0 }, { 7361, -1707, 7483 }, { -1, -1 }, 3, 3},
|
|
{ { 0, 0, 187 }, { 2225, 6272, -8543 }, { -1, -1 }, 4, 4},
|
|
{ { 187, 0, 187 }, { 4445, 7781, -4818 }, { 13, 9 }, 5, 5},
|
|
{ { 0, 187, 187 }, { 6884, -3809, -1119 }, { 14, 10 }, 6, 6},
|
|
{ { 187, 187, 187 }, { 7588, 0, 0 }, { -1, -1 }, 7, 7},
|
|
{ { 85, 85, 85 }, { 3615, 0, 0 }, { -1, -1 }, 0, 8},
|
|
{ { 255, 85, 85 }, { 6027, 6421, 3655 }, { -1, -1 }, 1, 9},
|
|
{ { 85, 255, 85 }, { 8897, -7423, 6593 }, { -1, -1 }, 2, 10},
|
|
{ { 255, 255, 85 }, { 9741, -1942, 7731 }, { 6, 15 }, 3, 11},
|
|
{ { 85, 85, 255 }, { 4651, 5110, -8420 }, { 4, -1 }, 4, 12},
|
|
{ { 255, 85, 255 }, { 6573, 8258, -5221 }, { -1, -1 }, 5, 13},
|
|
{ { 85, 255, 255 }, { 9198, -4245, -1274 }, { -1, -1 }, 6, 14},
|
|
{ { 255, 255, 255 }, { 10000, 0, 0 }, { 7, 3 }, 7, 15},
|
|
{ { 0, 0, 0 }, { 0, 0, 0 }, { -1, -1 }, 0, 0},
|
|
{ { 0, 0, 95 }, { 746, 3839, -5234 }, { -1, -1 }, 4, 4},
|
|
{ { 0, 0, 135 }, { 1411, 4937, -6724 }, { 20, 54 }, 4, 4},
|
|
{ { 0, 0, 175 }, { 2042, 5971, -8133 }, { -1, -1 }, 4, 4},
|
|
{ { 0, 0, 215 }, { 2646, 6962, -9483 }, { 19, 55 }, 4, 4},
|
|
{ { 0, 0, 255 }, { 3230, 7919, -10786 }, { -1, -1 }, 4, 4},
|
|
{ { 0, 95, 0 }, { 3436, -4184, 4038 }, { -1, -1 }, 2, 2},
|
|
{ { 0, 95, 95 }, { 3600, -2335, -686 }, { 16, 24 }, 6, 8},
|
|
{ { 0, 95, 135 }, { 3772, -828, -2884 }, { -1, -1 }, 6, 8},
|
|
{ { 0, 95, 175 }, { 4004, 805, -4908 }, { -1, -1 }, 7, 8},
|
|
{ { 0, 95, 215 }, { 4290, 2423, -6767 }, { -1, -1 }, 4, 12},
|
|
{ { 0, 95, 255 }, { 4618, 3961, -8484 }, { 56, 170 }, 4, 12},
|
|
{ { 0, 135, 0 }, { 4867, -5373, 5185 }, { -1, -1 }, 2, 2},
|
|
{ { 0, 135, 95 }, { 4968, -4147, 1287 }, { 22, 65 }, 6, 6},
|
|
{ { 0, 135, 135 }, { 5078, -2998, -881 }, { -1, -1 }, 6, 6},
|
|
{ { 0, 135, 175 }, { 5231, -1609, -2967 }, { -1, -1 }, 6, 6},
|
|
{ { 0, 135, 215 }, { 5427, -98, -4935 }, { 31, 67 }, 7, 8},
|
|
{ { 0, 135, 255 }, { 5663, 1444, -6783 }, { -1, -1 }, 4, 12},
|
|
{ { 0, 175, 0 }, { 6222, -6498, 6272 }, { -1, -1 }, 2, 2},
|
|
{ { 0, 175, 95 }, { 6291, -5627, 3055 }, { 245, 70 }, 2, 2},
|
|
{ { 0, 175, 135 }, { 6368, -4753, 999 }, { -1, -1 }, 6, 6},
|
|
{ { 0, 175, 175 }, { 6477, -3626, -1066 }, { -1, -1 }, 6, 6},
|
|
{ { 0, 175, 215 }, { 6618, -2318, -3066 }, { -1, -1 }, 6, 6},
|
|
{ { 0, 175, 255 }, { 6793, -902, -4979 }, { -1, -1 }, 6, 6},
|
|
{ { 0, 215, 0 }, { 7520, -7577, 7313 }, { 77, 112 }, 2, 2},
|
|
{ { 0, 215, 95 }, { 7571, -6924, 4642 }, { -1, -1 }, 2, 2},
|
|
{ { 0, 215, 135 }, { 7628, -6244, 2736 }, { -1, -1 }, 2, 2},
|
|
{ { 0, 215, 175 }, { 7710, -5332, 741 }, { -1, -1 }, 6, 6},
|
|
{ { 0, 215, 215 }, { 7817, -4228, -1242 }, { 43, 80 }, 6, 6},
|
|
{ { 0, 215, 255 }, { 7951, -2980, -3174 }, { 38, 81 }, 6, 6},
|
|
{ { 0, 255, 0 }, { 8773, -8618, 8318 }, { -1, -1 }, 2, 10},
|
|
{ { 0, 255, 95 }, { 8813, -8108, 6078 }, { -1, -1 }, 2, 10},
|
|
{ { 0, 255, 135 }, { 8857, -7565, 4337 }, { 113, 155 }, 2, 10},
|
|
{ { 0, 255, 175 }, { 8921, -6819, 2441 }, { -1, -1 }, 2, 10},
|
|
{ { 0, 255, 215 }, { 9005, -5890, 505 }, { -1, -1 }, 6, 14},
|
|
{ { 0, 255, 255 }, { 9111, -4809, -1413 }, { 50, 86 }, 6, 14},
|
|
{ { 95, 0, 0 }, { 1762, 3888, 2721 }, { -1, -1 }, 1, 1},
|
|
{ { 95, 0, 95 }, { 2106, 4769, -2953 }, { -1, -1 }, 5, 5},
|
|
{ { 95, 0, 135 }, { 2427, 5511, -5011 }, { 17, 91 }, 5, 5},
|
|
{ { 95, 0, 175 }, { 2819, 6350, -6819 }, { -1, -1 }, 4, 4},
|
|
{ { 95, 0, 215 }, { 3257, 7228, -8450 }, { 18, 92 }, 4, 4},
|
|
{ { 95, 0, 255 }, { 3721, 8116, -9954 }, { 21, 93 }, 4, 4},
|
|
{ { 95, 95, 0 }, { 3893, -1046, 4587 }, { 29, 64 }, 3, 3},
|
|
{ { 95, 95, 95 }, { 4032, 0, 0 }, { 61, 101 }, 7, 8},
|
|
{ { 95, 95, 135 }, { 4179, 972, -2218 }, { 25, 26 }, 7, 8},
|
|
{ { 95, 95, 175 }, { 4382, 2136, -4283 }, { 236, 68 }, 5, 8},
|
|
{ { 95, 95, 215 }, { 4634, 3391, -6192 }, { 99, 134 }, 4, 12},
|
|
{ { 95, 95, 255 }, { 4930, 4665, -7961 }, { -1, -1 }, 4, 12},
|
|
{ { 95, 135, 0 }, { 5157, -3111, 5536 }, { 28, 100 }, 3, 3},
|
|
{ { 95, 135, 95 }, { 5249, -2237, 1719 }, { -1, -1 }, 6, 8},
|
|
{ { 95, 135, 135 }, { 5350, -1376, -446 }, { 30, 37 }, 7, 8},
|
|
{ { 95, 135, 175 }, { 5492, -286, -2541 }, { -1, -1 }, 7, 8},
|
|
{ { 95, 135, 215 }, { 5675, 952, -4526 }, { 103, 104 }, 7, 7},
|
|
{ { 95, 135, 255 }, { 5895, 2267, -6396 }, { 33, 105 }, 4, 12},
|
|
{ { 95, 175, 0 }, { 6424, -4820, 6517 }, { 34, 71 }, 2, 2},
|
|
{ { 95, 175, 95 }, { 6490, -4117, 3349 }, { -1, -1 }, 2, 2},
|
|
{ { 95, 175, 135 }, { 6562, -3396, 1301 }, { 140, 228 }, 6, 6},
|
|
{ { 95, 175, 175 }, { 6666, -2446, -763 }, { -1, -1 }, 6, 6},
|
|
{ { 95, 175, 215 }, { 6802, -1319, -2768 }, { 39, 75 }, 6, 6},
|
|
{ { 95, 175, 255 }, { 6969, -71, -4690 }, { -1, -1 }, 7, 7},
|
|
{ { 95, 215, 0 }, { 7670, -6288, 7495 }, { -1, -1 }, 2, 2},
|
|
{ { 95, 215, 95 }, { 7720, -5722, 4854 }, { 41, 47 }, 2, 2},
|
|
{ { 95, 215, 135 }, { 7774, -5127, 2957 }, { 42, 114 }, 2, 2},
|
|
{ { 95, 215, 175 }, { 7853, -4321, 966 }, { 44, 78 }, 6, 6},
|
|
{ { 95, 215, 215 }, { 7958, -3332, -1018 }, { -1, -1 }, 6, 6},
|
|
{ { 95, 215, 255 }, { 8088, -2201, -2952 }, { -1, -1 }, 6, 6},
|
|
{ { 95, 255, 0 }, { 8890, -7597, 8460 }, { -1, -1 }, 2, 10},
|
|
{ { 95, 255, 95 }, { 8929, -7135, 6239 }, { -1, -1 }, 2, 10},
|
|
{ { 95, 255, 135 }, { 8972, -6642, 4506 }, { 83, 120 }, 2, 10},
|
|
{ { 95, 255, 175 }, { 9034, -5961, 2614 }, { 49, 121 }, 2, 10},
|
|
{ { 95, 255, 215 }, { 9117, -5106, 680 }, { -1, -1 }, 6, 14},
|
|
{ { 95, 255, 255 }, { 9221, -4104, -1238 }, { 122, 194 }, 6, 14},
|
|
{ { 135, 0, 0 }, { 2717, 4993, 4014 }, { 52, 131 }, 1, 1},
|
|
{ { 135, 0, 95 }, { 2936, 5573, -1590 }, { 53, 97 }, 5, 5},
|
|
{ { 135, 0, 135 }, { 3158, 6124, -3792 }, { 27, 133 }, 5, 5},
|
|
{ { 135, 0, 175 }, { 3449, 6804, -5761 }, { -1, -1 }, 5, 5},
|
|
{ { 135, 0, 215 }, { 3795, 7565, -7543 }, { 57, 128 }, 4, 4},
|
|
{ { 135, 0, 255 }, { 4180, 8371, -9179 }, { -1, -1 }, 4, 4},
|
|
{ { 135, 95, 0 }, { 4327, 913, 5093 }, { -1, -1 }, 3, 3},
|
|
{ { 135, 95, 95 }, { 4447, 1631, 651 }, { 243, 130 }, 7, 8},
|
|
{ { 135, 95, 135 }, { 4575, 2337, -1577 }, { -1, -1 }, 7, 8},
|
|
{ { 135, 95, 175 }, { 4753, 3230, -3670 }, { -1, -1 }, 5, 5},
|
|
{ { 135, 95, 215 }, { 4979, 4244, -5618 }, { -1, -1 }, 5, 12},
|
|
{ { 135, 95, 255 }, { 5246, 5322, -7432 }, { 63, 135 }, 4, 12},
|
|
{ { 135, 135, 0 }, { 5453, -1344, 5890 }, { -1, -1 }, 3, 3},
|
|
{ { 135, 135, 95 }, { 5539, -677, 2158 }, { 241, 246 }, 7, 8},
|
|
{ { 135, 135, 135 }, { 5632, 0, 0 }, { -1, -1 }, 7, 7},
|
|
{ { 135, 135, 175 }, { 5763, 883, -2102 }, { 32, 66 }, 7, 7},
|
|
{ { 135, 135, 215 }, { 5933, 1918, -4102 }, { 69, 139 }, 7, 7},
|
|
{ { 135, 135, 255 }, { 6139, 3051, -5992 }, { -1, -1 }, 5, 12},
|
|
{ { 135, 175, 0 }, { 6637, -3334, 6775 }, { -1, -1 }, 3, 3},
|
|
{ { 135, 175, 95 }, { 6700, -2753, 3658 }, { 106, 149 }, 3, 3},
|
|
{ { 135, 175, 135 }, { 6769, -2148, 1621 }, { 73, -1 }, 7, 7},
|
|
{ { 135, 175, 175 }, { 6868, -1338, -441 }, { -1, -1 }, 7, 7},
|
|
{ { 135, 175, 215 }, { 6998, -359, -2451 }, { 74, 248 }, 7, 7},
|
|
{ { 135, 175, 255 }, { 7157, 745, -4381 }, { 110, 212 }, 7, 7},
|
|
{ { 135, 215, 0 }, { 7832, -5059, 7691 }, { 76, 46 }, 2, 2},
|
|
{ { 135, 215, 95 }, { 7880, -4565, 5082 }, { 40, 142 }, 2, 2},
|
|
{ { 135, 215, 135 }, { 7933, -4042, 3195 }, { -1, -1 }, 6, 6},
|
|
{ { 135, 215, 175 }, { 8009, -3327, 1209 }, { 79, 116 }, 6, 6},
|
|
{ { 135, 215, 215 }, { 8110, -2441, -775 }, { 45, 108 }, 6, 6},
|
|
{ { 135, 215, 255 }, { 8236, -1415, -2712 }, { 146, 153 }, 7, 7},
|
|
{ { 135, 255, 0 }, { 9017, -6577, 8614 }, { 82, 154 }, 2, 10},
|
|
{ { 135, 255, 95 }, { 9055, -6160, 6414 }, { 84, 118 }, 2, 10},
|
|
{ { 135, 255, 135 }, { 9097, -5712, 4689 }, { -1, -1 }, 2, 10},
|
|
{ { 135, 255, 175 }, { 9158, -5090, 2803 }, { -1, -1 }, 6, 14},
|
|
{ { 135, 255, 215 }, { 9239, -4305, 871 }, { 51, 85 }, 6, 14},
|
|
{ { 135, 255, 255 }, { 9340, -3378, -1048 }, { -1, -1 }, 6, 14},
|
|
{ { 175, 0, 0 }, { 3621, 6039, 5057 }, { 132, 125 }, 1, 1},
|
|
{ { 175, 0, 95 }, { 3774, 6450, -244 }, { 162, 161 }, 5, 9},
|
|
{ { 175, 0, 135 }, { 3935, 6865, -2513 }, { -1, -1 }, 5, 5},
|
|
{ { 175, 0, 175 }, { 4155, 7407, -4586 }, { -1, -1 }, 5, 5},
|
|
{ { 175, 0, 215 }, { 4426, 8046, -6485 }, { 127, -1 }, 5, 5},
|
|
{ { 175, 0, 255 }, { 4741, 8752, -8236 }, { -1, -1 }, 4, 4},
|
|
{ { 175, 95, 0 }, { 4864, 2733, 5703 }, { 94, -1 }, 1, 1},
|
|
{ { 175, 95, 95 }, { 4965, 3235, 1454 }, { -1, -1 }, 7, 8},
|
|
{ { 175, 95, 135 }, { 5075, 3748, -774 }, { 89, 88 }, 7, 8},
|
|
{ { 175, 95, 175 }, { 5228, 4425, -2893 }, { 124, 204 }, 5, 5},
|
|
{ { 175, 95, 215 }, { 5424, 5228, -4881 }, { 98, 141 }, 5, 5},
|
|
{ { 175, 95, 255 }, { 5660, 6118, -6741 }, { -1, -1 }, 5, 12},
|
|
{ { 175, 135, 0 }, { 5846, 507, 6350 }, { -1, -1 }, 3, 3},
|
|
{ { 175, 135, 95 }, { 5922, 1007, 2735 }, { -1, -1 }, 7, 7},
|
|
{ { 175, 135, 135 }, { 6006, 1527, 589 }, { 137, 247 }, 7, 7},
|
|
{ { 175, 135, 175 }, { 6125, 2223, -1518 }, { 96, -1 }, 7, 7},
|
|
{ { 175, 135, 215 }, { 6280, 3063, -3534 }, { 59, 90 }, 7, 7},
|
|
{ { 175, 135, 255 }, { 6469, 4011, -5447 }, { -1, -1 }, 5, 12},
|
|
{ { 175, 175, 0 }, { 6931, -1625, 7124 }, { 107, 184 }, 3, 3},
|
|
{ { 175, 175, 95 }, { 6990, -1160, 4080 }, { -1, -1 }, 3, 3},
|
|
{ { 175, 175, 135 }, { 7054, -669, 2058 }, { -1, -1 }, 7, 7},
|
|
{ { 175, 175, 175 }, { 7147, 0, 0 }, { -1, -1 }, 7, 7},
|
|
{ { 175, 175, 215 }, { 7268, 824, -2014 }, { -1, -1 }, 7, 7},
|
|
{ { 175, 175, 255 }, { 7418, 1772, -3954 }, { 189, 182 }, 7, 7},
|
|
{ { 175, 215, 0 }, { 8058, -3551, 7963 }, { -1, -1 }, 3, 3},
|
|
{ { 175, 215, 95 }, { 8104, -3135, 5399 }, { -1, -1 }, 3, 3},
|
|
{ { 175, 215, 135 }, { 8155, -2689, 3528 }, { 151, 48 }, 3, 3},
|
|
{ { 175, 215, 175 }, { 8228, -2074, 1548 }, { 115, 87 }, 7, 7},
|
|
{ { 175, 215, 215 }, { 8324, -1303, -434 }, { 250, 195 }, 7, 7},
|
|
{ { 175, 215, 255 }, { 8445, -399, -2375 }, { -1, -1 }, 7, 7},
|
|
{ { 175, 255, 0 }, { 9197, -5270, 8831 }, { -1, -1 }, 2, 10},
|
|
{ { 175, 255, 95 }, { 9234, -4904, 6661 }, { 119, 227 }, 2, 10},
|
|
{ { 175, 255, 135 }, { 9274, -4508, 4948 }, { -1, -1 }, 2, 10},
|
|
{ { 175, 255, 175 }, { 9333, -3956, 3070 }, { -1, -1 }, 6, 14},
|
|
{ { 175, 255, 215 }, { 9411, -3254, 1142 }, { 123, 159 }, 6, 14},
|
|
{ { 175, 255, 255 }, { 9510, -2417, -777 }, { -1, -1 }, 6, 14},
|
|
{ { 215, 0, 0 }, { 4487, 7041, 5908 }, { -1, -1 }, 1, 1},
|
|
{ { 215, 0, 95 }, { 4601, 7349, 1053 }, { 160, -1 }, 1, 9},
|
|
{ { 215, 0, 135 }, { 4724, 7671, -1235 }, { 126, 163 }, 5, 5},
|
|
{ { 215, 0, 175 }, { 4894, 8105, -3368 }, { -1, -1 }, 5, 5},
|
|
{ { 215, 0, 215 }, { 5110, 8636, -5348 }, { -1, -1 }, 5, 5},
|
|
{ { 215, 0, 255 }, { 5367, 9245, -7188 }, { 129, 201 }, 5, 13},
|
|
{ { 215, 95, 0 }, { 5470, 4355, 6373 }, { -1, -1 }, 1, 1},
|
|
{ { 215, 95, 95 }, { 5554, 4720, 2349 }, { 169, 202 }, 1, 9},
|
|
{ { 215, 95, 135 }, { 5647, 5103, 135 }, { -1, -1 }, 7, 9},
|
|
{ { 215, 95, 175 }, { 5778, 5623, -2000 }, { 168, 174 }, 5, 5},
|
|
{ { 215, 95, 215 }, { 5947, 6260, -4020 }, { 62, 171 }, 5, 5},
|
|
{ { 215, 95, 255 }, { 6153, 6990, -5924 }, { 165, 200 }, 5, 13},
|
|
{ { 215, 135, 0 }, { 6316, 2286, 6890 }, { 136, -1 }, 3, 3},
|
|
{ { 215, 135, 95 }, { 6384, 2663, 3419 }, { 138, 172 }, 7, 9},
|
|
{ { 215, 135, 135 }, { 6459, 3063, 1294 }, { -1, -1 }, 7, 7},
|
|
{ { 215, 135, 175 }, { 6565, 3610, -813 }, { -1, -1 }, 7, 7},
|
|
{ { 215, 135, 215 }, { 6704, 4286, -2843 }, { 207, 177 }, 5, 5},
|
|
{ { 215, 135, 255 }, { 6875, 5069, -4779 }, { -1, -1 }, 5, 13},
|
|
{ { 215, 175, 0 }, { 7296, 143, 7553 }, { 143, 179 }, 3, 3},
|
|
{ { 215, 175, 95 }, { 7350, 512, 4600 }, { -1, -1 }, 3, 3},
|
|
{ { 215, 175, 135 }, { 7410, 906, 2601 }, { 181, 178 }, 7, 7},
|
|
{ { 215, 175, 175 }, { 7495, 1450, 549 }, { 144, 252 }, 7, 7},
|
|
{ { 215, 175, 215 }, { 7608, 2132, -1468 }, { 183, 225 }, 7, 7},
|
|
{ { 215, 175, 255 }, { 7748, 2932, -3418 }, { 213, 219 }, 7, 7},
|
|
{ { 215, 215, 0 }, { 8347, -1895, 8306 }, { 148, -1 }, 3, 3},
|
|
{ { 215, 215, 95 }, { 8390, -1549, 5801 }, { 214, 254 }, 3, 3},
|
|
{ { 215, 215, 135 }, { 8438, -1177, 3949 }, { -1, -1 }, 3, 3},
|
|
{ { 215, 215, 175 }, { 8507, -658, 1980 }, { 253, 220 }, 7, 7},
|
|
{ { 215, 215, 215 }, { 8598, 0, 0 }, { -1, -1 }, 7, 7},
|
|
{ { 215, 215, 255 }, { 8713, 781, -1944 }, { 117, 152 }, 7, 7},
|
|
{ { 215, 255, 0 }, { 9430, -3767, 9110 }, { -1, -1 }, 3, 11},
|
|
{ { 215, 255, 95 }, { 9465, -3451, 6978 }, { 156, 192 }, 3, 11},
|
|
{ { 215, 255, 135 }, { 9504, -3109, 5283 }, { -1, -1 }, 3, 11},
|
|
{ { 215, 255, 175 }, { 9561, -2628, 3414 }, { 157, -1 }, 3, 15},
|
|
{ { 215, 255, 215 }, { 9636, -2012, 1491 }, { 158, 193 }, 7, 15},
|
|
{ { 215, 255, 255 }, { 9730, -1272, -427 }, { -1, -1 }, 7, 15},
|
|
{ { 255, 0, 0 }, { 5324, 8009, 6720 }, { -1, -1 }, 1, 1},
|
|
{ { 255, 0, 95 }, { 5413, 8249, 2291 }, { 196, -1 }, 1, 9},
|
|
{ { 255, 0, 135 }, { 5509, 8505, 17 }, { 205, 197 }, 5, 9},
|
|
{ { 255, 0, 175 }, { 5645, 8859, -2145 }, { -1, -1 }, 5, 5},
|
|
{ { 255, 0, 215 }, { 5820, 9303, -4177 }, { 164, -1 }, 5, 13},
|
|
{ { 255, 0, 255 }, { 6032, 9823, -6082 }, { -1, -1 }, 5, 13},
|
|
{ { 255, 95, 0 }, { 6118, 5801, 7073 }, { 166, 203 }, 1, 1},
|
|
{ { 255, 95, 95 }, { 6189, 6077, 3294 }, { -1, -1 }, 1, 9},
|
|
{ { 255, 95, 135 }, { 6268, 6372, 1106 }, { 167, 198 }, 1, 9},
|
|
{ { 255, 95, 175 }, { 6379, 6781, -1033 }, { 199, 206 }, 5, 5},
|
|
{ { 255, 95, 215 }, { 6524, 7293, -3077 }, { -1, -1 }, 5, 13},
|
|
{ { 255, 95, 255 }, { 6703, 7895, -5017 }, { -1, -1 }, 5, 13},
|
|
{ { 255, 135, 0 }, { 6846, 3935, 7486 }, { -1, -1 }, 1, 1},
|
|
{ { 255, 135, 95 }, { 6905, 4226, 4178 }, { 216, 215 }, 1, 9},
|
|
{ { 255, 135, 135 }, { 6971, 4538, 2083 }, { -1, -1 }, 1, 9},
|
|
{ { 255, 135, 175 }, { 7066, 4971, -18 }, { 175, -1 }, 7, 9},
|
|
{ { 255, 135, 215 }, { 7189, 5518, -2058 }, { 176, 211 }, 5, 13},
|
|
{ { 255, 135, 255 }, { 7342, 6164, -4013 }, { -1, -1 }, 5, 13},
|
|
{ { 255, 175, 0 }, { 7724, 1872, 8047 }, { 180, 209 }, 3, 3},
|
|
{ { 255, 175, 95 }, { 7773, 2165, 5200 }, { 208, -1 }, 3, 3},
|
|
{ { 255, 175, 135 }, { 7827, 2482, 3230 }, { 210, 217 }, 7, 7},
|
|
{ { 255, 175, 175 }, { 7905, 2924, 1190 }, { -1, -1 }, 7, 7},
|
|
{ { 255, 175, 215 }, { 8008, 3486, -827 }, { -1, -1 }, 7, 7},
|
|
{ { 255, 175, 255 }, { 8137, 4155, -2786 }, { -1, -1 }, 7, 13},
|
|
{ { 255, 215, 0 }, { 8693, -192, 8713 }, { 186, 229 }, 3, 11},
|
|
{ { 255, 215, 95 }, { 8733, 93, 6278 }, { -1, -1 }, 3, 3},
|
|
{ { 255, 215, 135 }, { 8778, 402, 4451 }, { 221, -1 }, 3, 3},
|
|
{ { 255, 215, 175 }, { 8843, 836, 2496 }, { 255, 222 }, 7, 15},
|
|
{ { 255, 215, 215 }, { 8928, 1392, 520 }, { -1, -1 }, 7, 15},
|
|
{ { 255, 215, 255 }, { 9036, 2059, -1425 }, { 218, -1 }, 7, 15},
|
|
{ { 255, 255, 0 }, { 9714, -2155, 9448 }, { 190, -1 }, 3, 11},
|
|
{ { 255, 255, 95 }, { 9747, -1887, 7362 }, { 191, 226 }, 3, 11},
|
|
{ { 255, 255, 135 }, { 9785, -1594, 5688 }, { 150, 251 }, 3, 11},
|
|
{ { 255, 255, 175 }, { 9838, -1180, 3833 }, { -1, -1 }, 3, 11},
|
|
{ { 255, 255, 215 }, { 9910, -647, 1916 }, { -1, -1 }, 7, 15},
|
|
{ { 255, 255, 255 }, { 10000, 0, 0 }, { -1, -1 }, 7, 15},
|
|
{ { 8, 8, 8 }, { 219, 0, 0 }, { 23, 234 }, 0, 0},
|
|
{ { 18, 18, 18 }, { 546, 0, 0 }, { -1, -1 }, 0, 0},
|
|
{ { 28, 28, 28 }, { 1027, 0, 0 }, { 233, 235 }, 0, 0},
|
|
{ { 38, 38, 38 }, { 1516, 0, 0 }, { -1, -1 }, 0, 0},
|
|
{ { 48, 48, 48 }, { 1987, 0, 0 }, { 232, 237 }, 0, 8},
|
|
{ { 58, 58, 58 }, { 2442, 0, 0 }, { 60, 239 }, 0, 8},
|
|
{ { 68, 68, 68 }, { 2885, 0, 0 }, { -1, -1 }, 0, 8},
|
|
{ { 78, 78, 78 }, { 3318, 0, 0 }, { 238, 240 }, 0, 8},
|
|
{ { 88, 88, 88 }, { 3741, 0, 0 }, { -1, -1 }, 0, 8},
|
|
{ { 98, 98, 98 }, { 4155, 0, 0 }, { 58, 95 }, 7, 8},
|
|
{ { 108, 108, 108 }, { 4563, 0, 0 }, { -1, -1 }, 7, 8},
|
|
{ { 118, 118, 118 }, { 4964, 0, 0 }, { 242, 244 }, 7, 8},
|
|
{ { 128, 128, 128 }, { 5359, 0, 0 }, { -1, -1 }, 7, 8},
|
|
{ { 138, 138, 138 }, { 5748, 0, 0 }, { 102, 36 }, 7, 7},
|
|
{ { 148, 148, 148 }, { 6132, 0, 0 }, { 35, 173 }, 7, 7},
|
|
{ { 158, 158, 158 }, { 6511, 0, 0 }, { -1, -1 }, 7, 7},
|
|
{ { 168, 168, 168 }, { 6887, 0, 0 }, { 109, 145 }, 7, 7},
|
|
{ { 178, 178, 178 }, { 7257, 0, 0 }, { 111, 147 }, 7, 7},
|
|
{ { 188, 188, 188 }, { 7625, 0, 0 }, { -1, -1 }, 7, 7},
|
|
{ { 198, 198, 198 }, { 7988, 0, 0 }, { 249, 185 }, 7, 7},
|
|
{ { 208, 208, 208 }, { 8348, 0, 0 }, { -1, -1 }, 7, 7},
|
|
{ { 218, 218, 218 }, { 8705, 0, 0 }, { 188, 230 }, 7, 7},
|
|
{ { 228, 228, 228 }, { 9059, 0, 0 }, { 187, 223 }, 7, 15},
|
|
{ { 238, 238, 238 }, { 9410, 0, 0 }, { 224, 231 }, 7, 15},
|
|
};
|
|
|
|
// CIE76 color difference: squared Euclidean distance in CIELAB.
|
|
//
|
|
int64_t diff(const LABi &lab1, const LABi &lab2)
|
|
{
|
|
int64_t dL = static_cast<int64_t>(lab1.L - lab2.L);
|
|
int64_t da = static_cast<int64_t>(lab1.a - lab2.a);
|
|
int64_t db = static_cast<int64_t>(lab1.b - lab2.b);
|
|
|
|
int64_t r = dL*dL + da*da + db*db;
|
|
return r;
|
|
}
|
|
|
|
void NearestIndex_tree_a(int iHere, const LABi &labi, int &iBest, int64_t &rBest);
|
|
void NearestIndex_tree_b(int iHere, const LABi &labi, int &iBest, int64_t &rBest);
|
|
|
|
void NearestIndex_tree_L(int iHere, const LABi &labi, int &iBest, int64_t &rBest)
|
|
{
|
|
if (-1 == iHere)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (-1 == iBest)
|
|
{
|
|
iBest = iHere;
|
|
rBest = diff(labi, palette[iBest].labi);
|
|
}
|
|
|
|
int64_t rHere = diff(labi, palette[iHere].labi);
|
|
if (rHere < rBest)
|
|
{
|
|
iBest = iHere;
|
|
rBest = rHere;
|
|
}
|
|
|
|
int64_t d = static_cast<int64_t>(labi.L - palette[iHere].labi.L);
|
|
int iNearChild = (d < 0)?0:1;
|
|
NearestIndex_tree_a(palette[iHere].child[iNearChild], labi, iBest, rBest);
|
|
|
|
int64_t rAxis = d*d;
|
|
if (rAxis < rBest)
|
|
{
|
|
NearestIndex_tree_a(palette[iHere].child[1-iNearChild], labi, iBest, rBest);
|
|
}
|
|
}
|
|
|
|
void NearestIndex_tree_a(int iHere, const LABi &labi, int &iBest, int64_t &rBest)
|
|
{
|
|
if (-1 == iHere)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (-1 == iBest)
|
|
{
|
|
iBest = iHere;
|
|
rBest = diff(labi, palette[iBest].labi);
|
|
}
|
|
|
|
int64_t rHere = diff(labi, palette[iHere].labi);
|
|
if (rHere < rBest)
|
|
{
|
|
iBest = iHere;
|
|
rBest = rHere;
|
|
}
|
|
|
|
int64_t d = static_cast<int64_t>(labi.a - palette[iHere].labi.a);
|
|
int iNearChild = (d < 0)?0:1;
|
|
NearestIndex_tree_b(palette[iHere].child[iNearChild], labi, iBest, rBest);
|
|
|
|
int64_t rAxis = d*d;
|
|
if (rAxis < rBest)
|
|
{
|
|
NearestIndex_tree_b(palette[iHere].child[1-iNearChild], labi, iBest, rBest);
|
|
}
|
|
}
|
|
|
|
void NearestIndex_tree_b(int iHere, const LABi &labi, int &iBest, int64_t &rBest)
|
|
{
|
|
if (-1 == iHere)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (-1 == iBest)
|
|
{
|
|
iBest = iHere;
|
|
rBest = diff(labi, palette[iBest].labi);
|
|
}
|
|
|
|
int64_t rHere = diff(labi, palette[iHere].labi);
|
|
if (rHere < rBest)
|
|
{
|
|
iBest = iHere;
|
|
rBest = rHere;
|
|
}
|
|
|
|
int64_t d = static_cast<int64_t>(labi.b - palette[iHere].labi.b);
|
|
int iNearChild = (d < 0)?0:1;
|
|
NearestIndex_tree_L(palette[iHere].child[iNearChild], labi, iBest, rBest);
|
|
|
|
int64_t rAxis = d*d;
|
|
if (rAxis < rBest)
|
|
{
|
|
NearestIndex_tree_L(palette[iHere].child[1-iNearChild], labi, iBest, rBest);
|
|
}
|
|
}
|
|
|
|
int FindNearestPaletteEntry(RGB &rgb, bool fColor256)
|
|
{
|
|
LABi labi;
|
|
rgb2lab(&rgb, &labi);
|
|
|
|
int64_t d;
|
|
int j = -1;
|
|
NearestIndex_tree_L(fColor256 ? PALETTE256_ROOT : PALETTE16_ROOT, labi, j, d);
|
|
return j;
|
|
}
|
|
|
|
int FindNearestPalette8Entry(RGB &rgb)
|
|
{
|
|
LABi labi;
|
|
rgb2lab(&rgb, &labi);
|
|
|
|
int iNearest = 0;
|
|
int64_t rNearest = diff(labi, palette[0].labi);
|
|
|
|
for (int i = 1; i < 8; i++)
|
|
{
|
|
int64_t r = diff(labi, palette[i].labi);
|
|
if (r < rNearest)
|
|
{
|
|
rNearest = r;
|
|
iNearest = i;
|
|
}
|
|
}
|
|
return iNearest;
|
|
}
|
|
|
|
// C-callable wrappers for CIE97 + K-d tree nearest-color search.
|
|
//
|
|
extern "C" LIBMUX_API int co_nearest_xterm256(const unsigned char *rgb)
|
|
{
|
|
RGB c;
|
|
c.r = rgb[0];
|
|
c.g = rgb[1];
|
|
c.b = rgb[2];
|
|
return FindNearestPaletteEntry(c, true);
|
|
}
|
|
|
|
extern "C" LIBMUX_API int co_nearest_xterm16(const unsigned char *rgb)
|
|
{
|
|
RGB c;
|
|
c.r = rgb[0];
|
|
c.g = rgb[1];
|
|
c.b = rgb[2];
|
|
return FindNearestPaletteEntry(c, false);
|
|
}
|
|
|
|
#define CS_FOREGROUND UINT64_C(0x0000000001FFFFFF)
|
|
#define CS_FOREGROUND_RED UINT64_C(0x0000000000FF0000)
|
|
#define CS_FOREGROUND_GREEN UINT64_C(0x000000000000FF00)
|
|
#define CS_FOREGROUND_BLUE UINT64_C(0x00000000000000FF)
|
|
#define CS_FG_BLACK UINT64_C(0x0000000001000000) // FOREGROUND BLACK (0,0,0)
|
|
#define CS_FG_RED UINT64_C(0x0000000001000001) // FOREGROUND RED (187,0,0)
|
|
#define CS_FG_GREEN UINT64_C(0x0000000001000002) // FOREGROUND GREEN (0,187,0)
|
|
#define CS_FG_YELLOW UINT64_C(0x0000000001000003) // FOREGROUND YELLOW (187,187,0)
|
|
#define CS_FG_BLUE UINT64_C(0x0000000001000004) // FOREGROUND BLUE (0,0,187)
|
|
#define CS_FG_MAGENTA UINT64_C(0x0000000001000005) // FOREGROUND MAGENTA (187,0,187)
|
|
#define CS_FG_CYAN UINT64_C(0x0000000001000006) // FOREGROUND CYAN (0,187,187)
|
|
#define CS_FG_WHITE UINT64_C(0x0000000001000007) // FOREGROUND WHITE (187,187,187)
|
|
#define CS_FG_INDEXED UINT64_C(0x0000000001000000)
|
|
#define CS_FG(x) (CS_FG_INDEXED | static_cast<uint64_t>(x))
|
|
#define CS_FG_FIELD(x) ((x) & UINT64_C(0x0000000000FFFFFF))
|
|
#define CS_FG_FIELD_INDEXED(x) ((x) & UINT64_C(0x00000000000000FF))
|
|
#define CS_FG_DEFAULT CS_FG(NUM_FG)
|
|
#define CS_BACKGROUND UINT64_C(0x01FFFFFF00000000)
|
|
#define CS_BACKGROUND_RED UINT64_C(0x00FF000000000000)
|
|
#define CS_BACKGROUND_GREEN UINT64_C(0x0000FF0000000000)
|
|
#define CS_BACKGROUND_BLUE UINT64_C(0x000000FF00000000)
|
|
#define CS_BG_BLACK UINT64_C(0x0100000000000000) // BACKGROUND BLACK (0,0,0)
|
|
#define CS_BG_RED UINT64_C(0x0100000100000000) // BACKGROUND RED (187,0,0)
|
|
#define CS_BG_GREEN UINT64_C(0x0100000200000000) // BACKGROUND GREEN (0,187,0)
|
|
#define CS_BG_YELLOW UINT64_C(0x0100000300000000) // BACKGROUND YELLOW (187,187,0)
|
|
#define CS_BG_BLUE UINT64_C(0x0100000400000000) // BACKGROUND BLUE (0,0,187)
|
|
#define CS_BG_MAGENTA UINT64_C(0x0100000500000000) // BACKGROUND MAGENTA (187,0,187)
|
|
#define CS_BG_CYAN UINT64_C(0x0100000600000000) // BACKGROUND CYAN (0,187,187)
|
|
#define CS_BG_WHITE UINT64_C(0x0100000700000000) // BACKGROUND WHITE (187,187,187)
|
|
#define CS_BG_INDEXED UINT64_C(0x0100000000000000)
|
|
#define CS_BG(x) (CS_BG_INDEXED | (static_cast<uint64_t>(x) << 32))
|
|
#define CS_BG_FIELD(x) (((x) & UINT64_C(0x00FFFFFF00000000)) >> 32)
|
|
#define CS_BG_FIELD_INDEXED(x) (((x) & UINT64_C(0x000000FF00000000)) >> 32)
|
|
#define CS_BG_DEFAULT CS_BG(NUM_BG)
|
|
#define CS_INTENSE UINT64_C(0x0000000010000000)
|
|
#define CS_INVERSE UINT64_C(0x0000000020000000)
|
|
#define CS_UNDERLINE UINT64_C(0x0000000040000000)
|
|
#define CS_BLINK UINT64_C(0x0000000080000000)
|
|
#define CS_ATTRS UINT64_C(0x00000000F0000000)
|
|
#define CS_ALLBITS UINT64_C(0x01FFFFFFF1FFFFFF)
|
|
|
|
#define CS_NORMAL (CS_FG_DEFAULT|CS_BG_DEFAULT)
|
|
#define CS_NOBLEED (CS_FG_WHITE|CS_BG_DEFAULT)
|
|
|
|
// XTERM_FG(0) through XTERM_FG(7) is equivalent to ANSI_BLACK...ANSI_WHITE.
|
|
// Even for 256-color-capable clients, the latter are used instead of the former.
|
|
// Similiarly for XTERM_BG(0) through XTERM_BG(0).
|
|
//
|
|
const MUX_COLOR_SET aColors[] =
|
|
{
|
|
{ 0, 0, "", 0, T(""), 0, T(""), 0}, // COLOR_NOTCOLOR
|
|
{ CS_NORMAL, CS_ALLBITS, ANSI_NORMAL, sizeof(ANSI_NORMAL)-1, T(COLOR_RESET), 3, T("%xn"), 3}, // COLOR_INDEX_RESET
|
|
{ CS_INTENSE, CS_INTENSE, ANSI_HILITE, sizeof(ANSI_HILITE)-1, T(COLOR_INTENSE), 3, T("%xh"), 3}, // COLOR_INDEX_ATTR, COLOR_INDEX_INTENSE
|
|
{ CS_UNDERLINE, CS_UNDERLINE, ANSI_UNDER, sizeof(ANSI_UNDER)-1, T(COLOR_UNDERLINE), 3, T("%xu"), 3}, // COLOR_INDEX_UNDERLINE
|
|
{ CS_BLINK, CS_BLINK, ANSI_BLINK, sizeof(ANSI_BLINK)-1, T(COLOR_BLINK), 3, T("%xf"), 3}, // COLOR_INDEX_BLINK
|
|
{ CS_INVERSE, CS_INVERSE, ANSI_INVERSE, sizeof(ANSI_INVERSE)-1, T(COLOR_INVERSE), 3, T("%xi"), 3}, // COLOR_INDEX_INVERSE
|
|
{ CS_FG_BLACK, CS_FOREGROUND, ANSI_BLACK, sizeof(ANSI_BLACK)-1, T(COLOR_FG_BLACK), 3, T("%xx"), 3}, // COLOR_INDEX_FG
|
|
{ CS_FG_RED, CS_FOREGROUND, ANSI_RED, sizeof(ANSI_RED)-1, T(COLOR_FG_RED), 3, T("%xr"), 3},
|
|
{ CS_FG_GREEN, CS_FOREGROUND, ANSI_GREEN, sizeof(ANSI_GREEN)-1, T(COLOR_FG_GREEN), 3, T("%xg"), 3},
|
|
{ CS_FG_YELLOW, CS_FOREGROUND, ANSI_YELLOW, sizeof(ANSI_YELLOW)-1, T(COLOR_FG_YELLOW), 3, T("%xy"), 3},
|
|
{ CS_FG_BLUE, CS_FOREGROUND, ANSI_BLUE, sizeof(ANSI_BLUE)-1, T(COLOR_FG_BLUE), 3, T("%xb"), 3},
|
|
{ CS_FG_MAGENTA, CS_FOREGROUND, ANSI_MAGENTA, sizeof(ANSI_MAGENTA)-1, T(COLOR_FG_MAGENTA), 3, T("%xm"), 3},
|
|
{ CS_FG_CYAN, CS_FOREGROUND, ANSI_CYAN, sizeof(ANSI_CYAN)-1, T(COLOR_FG_CYAN), 3, T("%xc"), 3},
|
|
{ CS_FG_WHITE, CS_FOREGROUND, ANSI_WHITE, sizeof(ANSI_WHITE)-1, T(COLOR_FG_WHITE), 3, T("%xw"), 3}, // COLOR_INDEX_FG_WHITE
|
|
{ CS_FG( 8), CS_FOREGROUND, XTERM_FG( 8), sizeof(XTERM_FG( 8))-1, T(COLOR_FG_555555), 3, T("NU8"), 6}, // These eight are converted into something else.
|
|
{ CS_FG( 9), CS_FOREGROUND, XTERM_FG( 9), sizeof(XTERM_FG( 9))-1, T(COLOR_FG_FF5555), 3, T("NU9"), 6}, // .
|
|
{ CS_FG( 10), CS_FOREGROUND, XTERM_FG( 10), sizeof(XTERM_FG( 10))-1, T(COLOR_FG_55FF55), 3, T("NU10"), 6}, // .
|
|
{ CS_FG( 11), CS_FOREGROUND, XTERM_FG( 11), sizeof(XTERM_FG( 11))-1, T(COLOR_FG_FFFF55), 3, T("NU11"), 6}, // .
|
|
{ CS_FG( 12), CS_FOREGROUND, XTERM_FG( 12), sizeof(XTERM_FG( 12))-1, T(COLOR_FG_5555FF), 3, T("NU12"), 6}, // .
|
|
{ CS_FG( 13), CS_FOREGROUND, XTERM_FG( 13), sizeof(XTERM_FG( 13))-1, T(COLOR_FG_FF55FF), 3, T("NU13"), 6}, // .
|
|
{ CS_FG( 14), CS_FOREGROUND, XTERM_FG( 14), sizeof(XTERM_FG( 14))-1, T(COLOR_FG_55FFFF), 3, T("NU14"), 6}, // .
|
|
{ CS_FG( 15), CS_FOREGROUND, XTERM_FG( 15), sizeof(XTERM_FG( 15))-1, T(COLOR_FG_FFFFFF_1),3, T("NU15"), 6}, // -
|
|
{ CS_FG( 16), CS_FOREGROUND, XTERM_FG( 16), sizeof(XTERM_FG( 16))-1, T(COLOR_FG_000000), 3, T("%x<#000000>"), 11},
|
|
{ CS_FG( 17), CS_FOREGROUND, XTERM_FG( 17), sizeof(XTERM_FG( 17))-1, T(COLOR_FG_00005F), 3, T("%x<#00005F>"), 11},
|
|
{ CS_FG( 18), CS_FOREGROUND, XTERM_FG( 18), sizeof(XTERM_FG( 18))-1, T(COLOR_FG_000087), 3, T("%x<#000087>"), 11},
|
|
{ CS_FG( 19), CS_FOREGROUND, XTERM_FG( 19), sizeof(XTERM_FG( 19))-1, T(COLOR_FG_0000AF), 3, T("%x<#0000AF>"), 11},
|
|
{ CS_FG( 20), CS_FOREGROUND, XTERM_FG( 20), sizeof(XTERM_FG( 20))-1, T(COLOR_FG_0000D7), 3, T("%x<#0000D7>"), 11},
|
|
{ CS_FG( 21), CS_FOREGROUND, XTERM_FG( 21), sizeof(XTERM_FG( 21))-1, T(COLOR_FG_0000FF), 3, T("%x<#0000FF>"), 11},
|
|
{ CS_FG( 22), CS_FOREGROUND, XTERM_FG( 22), sizeof(XTERM_FG( 22))-1, T(COLOR_FG_005F00), 3, T("%x<#005F00>"), 11},
|
|
{ CS_FG( 23), CS_FOREGROUND, XTERM_FG( 23), sizeof(XTERM_FG( 23))-1, T(COLOR_FG_005F5F), 3, T("%x<#005F5F>"), 11},
|
|
{ CS_FG( 24), CS_FOREGROUND, XTERM_FG( 24), sizeof(XTERM_FG( 24))-1, T(COLOR_FG_005F87), 3, T("%x<#005F87>"), 11},
|
|
{ CS_FG( 25), CS_FOREGROUND, XTERM_FG( 25), sizeof(XTERM_FG( 25))-1, T(COLOR_FG_005FAF), 3, T("%x<#005FAF>"), 11},
|
|
{ CS_FG( 26), CS_FOREGROUND, XTERM_FG( 26), sizeof(XTERM_FG( 26))-1, T(COLOR_FG_005FD7), 3, T("%x<#005FD7>"), 11},
|
|
{ CS_FG( 27), CS_FOREGROUND, XTERM_FG( 27), sizeof(XTERM_FG( 27))-1, T(COLOR_FG_005FFF), 3, T("%x<#005FFF>"), 11},
|
|
{ CS_FG( 28), CS_FOREGROUND, XTERM_FG( 28), sizeof(XTERM_FG( 28))-1, T(COLOR_FG_008700), 3, T("%x<#008700>"), 11},
|
|
{ CS_FG( 29), CS_FOREGROUND, XTERM_FG( 29), sizeof(XTERM_FG( 29))-1, T(COLOR_FG_00875F), 3, T("%x<#00875F>"), 11},
|
|
{ CS_FG( 30), CS_FOREGROUND, XTERM_FG( 30), sizeof(XTERM_FG( 30))-1, T(COLOR_FG_008785), 3, T("%x<#008785>"), 11},
|
|
{ CS_FG( 31), CS_FOREGROUND, XTERM_FG( 31), sizeof(XTERM_FG( 31))-1, T(COLOR_FG_0087AF), 3, T("%x<#0087AF>"), 11},
|
|
{ CS_FG( 32), CS_FOREGROUND, XTERM_FG( 32), sizeof(XTERM_FG( 32))-1, T(COLOR_FG_0087D7), 3, T("%x<#0087D7>"), 11},
|
|
{ CS_FG( 33), CS_FOREGROUND, XTERM_FG( 33), sizeof(XTERM_FG( 33))-1, T(COLOR_FG_0087FF), 3, T("%x<#0087FF>"), 11},
|
|
{ CS_FG( 34), CS_FOREGROUND, XTERM_FG( 34), sizeof(XTERM_FG( 34))-1, T(COLOR_FG_00AF00), 3, T("%x<#00AF00>"), 11},
|
|
{ CS_FG( 35), CS_FOREGROUND, XTERM_FG( 35), sizeof(XTERM_FG( 35))-1, T(COLOR_FG_00AF5F), 3, T("%x<#00AF5F>"), 11},
|
|
{ CS_FG( 36), CS_FOREGROUND, XTERM_FG( 36), sizeof(XTERM_FG( 36))-1, T(COLOR_FG_00AF87), 3, T("%x<#00AF87>"), 11},
|
|
{ CS_FG( 37), CS_FOREGROUND, XTERM_FG( 37), sizeof(XTERM_FG( 37))-1, T(COLOR_FG_00AFAF), 3, T("%x<#00AFAF>"), 11},
|
|
{ CS_FG( 38), CS_FOREGROUND, XTERM_FG( 38), sizeof(XTERM_FG( 38))-1, T(COLOR_FG_00AFD7), 3, T("%x<#00AFD7>"), 11},
|
|
{ CS_FG( 39), CS_FOREGROUND, XTERM_FG( 39), sizeof(XTERM_FG( 39))-1, T(COLOR_FG_00AFFF), 3, T("%x<#00AFFF>"), 11},
|
|
{ CS_FG( 40), CS_FOREGROUND, XTERM_FG( 40), sizeof(XTERM_FG( 40))-1, T(COLOR_FG_00D700), 3, T("%x<#00D700>"), 11},
|
|
{ CS_FG( 41), CS_FOREGROUND, XTERM_FG( 41), sizeof(XTERM_FG( 41))-1, T(COLOR_FG_00D75F), 3, T("%x<#00D75F>"), 11},
|
|
{ CS_FG( 42), CS_FOREGROUND, XTERM_FG( 42), sizeof(XTERM_FG( 42))-1, T(COLOR_FG_00D787), 3, T("%x<#00D787>"), 11},
|
|
{ CS_FG( 43), CS_FOREGROUND, XTERM_FG( 43), sizeof(XTERM_FG( 43))-1, T(COLOR_FG_00D7AF), 3, T("%x<#00D7AF>"), 11},
|
|
{ CS_FG( 44), CS_FOREGROUND, XTERM_FG( 44), sizeof(XTERM_FG( 44))-1, T(COLOR_FG_00D7D7), 3, T("%x<#00D7D7>"), 11},
|
|
{ CS_FG( 45), CS_FOREGROUND, XTERM_FG( 45), sizeof(XTERM_FG( 45))-1, T(COLOR_FG_00D7FF), 3, T("%x<#00D7FF>"), 11},
|
|
{ CS_FG( 46), CS_FOREGROUND, XTERM_FG( 46), sizeof(XTERM_FG( 46))-1, T(COLOR_FG_00FF00), 3, T("%x<#00FF00>"), 11},
|
|
{ CS_FG( 47), CS_FOREGROUND, XTERM_FG( 47), sizeof(XTERM_FG( 47))-1, T(COLOR_FG_00FF5A), 3, T("%x<#00FF5A>"), 11},
|
|
{ CS_FG( 48), CS_FOREGROUND, XTERM_FG( 48), sizeof(XTERM_FG( 48))-1, T(COLOR_FG_00FF87), 3, T("%x<#00FF87>"), 11},
|
|
{ CS_FG( 49), CS_FOREGROUND, XTERM_FG( 49), sizeof(XTERM_FG( 49))-1, T(COLOR_FG_00FFAF), 3, T("%x<#00FFAF>"), 11},
|
|
{ CS_FG( 50), CS_FOREGROUND, XTERM_FG( 50), sizeof(XTERM_FG( 50))-1, T(COLOR_FG_00FFD7), 3, T("%x<#00FFD7>"), 11},
|
|
{ CS_FG( 51), CS_FOREGROUND, XTERM_FG( 51), sizeof(XTERM_FG( 51))-1, T(COLOR_FG_00FFFF), 3, T("%x<#00FFFF>"), 11},
|
|
{ CS_FG( 52), CS_FOREGROUND, XTERM_FG( 52), sizeof(XTERM_FG( 52))-1, T(COLOR_FG_5F0000), 3, T("%x<#5F0000>"), 11},
|
|
{ CS_FG( 53), CS_FOREGROUND, XTERM_FG( 53), sizeof(XTERM_FG( 53))-1, T(COLOR_FG_5F005F), 3, T("%x<#5F005F>"), 11},
|
|
{ CS_FG( 54), CS_FOREGROUND, XTERM_FG( 54), sizeof(XTERM_FG( 54))-1, T(COLOR_FG_5F0087), 3, T("%x<#5F0087>"), 11},
|
|
{ CS_FG( 55), CS_FOREGROUND, XTERM_FG( 55), sizeof(XTERM_FG( 55))-1, T(COLOR_FG_5F00AF), 3, T("%x<#5F00AF>"), 11},
|
|
{ CS_FG( 56), CS_FOREGROUND, XTERM_FG( 56), sizeof(XTERM_FG( 56))-1, T(COLOR_FG_5F00D7), 3, T("%x<#5F00D7>"), 11},
|
|
{ CS_FG( 57), CS_FOREGROUND, XTERM_FG( 57), sizeof(XTERM_FG( 57))-1, T(COLOR_FG_5F00FF), 3, T("%x<#5F00FF>"), 11},
|
|
{ CS_FG( 58), CS_FOREGROUND, XTERM_FG( 58), sizeof(XTERM_FG( 58))-1, T(COLOR_FG_5F5F00), 3, T("%x<#5F5F00>"), 11},
|
|
{ CS_FG( 59), CS_FOREGROUND, XTERM_FG( 59), sizeof(XTERM_FG( 59))-1, T(COLOR_FG_5F5F5F), 3, T("%x<#5F5F5F>"), 11},
|
|
{ CS_FG( 60), CS_FOREGROUND, XTERM_FG( 60), sizeof(XTERM_FG( 60))-1, T(COLOR_FG_5F5F87), 3, T("%x<#5F5F87>"), 11},
|
|
{ CS_FG( 61), CS_FOREGROUND, XTERM_FG( 61), sizeof(XTERM_FG( 61))-1, T(COLOR_FG_5F5FAF), 3, T("%x<#5F5FAF>"), 11},
|
|
{ CS_FG( 62), CS_FOREGROUND, XTERM_FG( 62), sizeof(XTERM_FG( 62))-1, T(COLOR_FG_5F5FD7), 3, T("%x<#5F5FD7>"), 11},
|
|
{ CS_FG( 63), CS_FOREGROUND, XTERM_FG( 63), sizeof(XTERM_FG( 63))-1, T(COLOR_FG_5F5FFF), 3, T("%x<#5F5FFF>"), 11},
|
|
{ CS_FG( 64), CS_FOREGROUND, XTERM_FG( 64), sizeof(XTERM_FG( 64))-1, T(COLOR_FG_5F8700), 3, T("%x<#5F8700>"), 11},
|
|
{ CS_FG( 65), CS_FOREGROUND, XTERM_FG( 65), sizeof(XTERM_FG( 65))-1, T(COLOR_FG_5F875F), 3, T("%x<#5F875F>"), 11},
|
|
{ CS_FG( 66), CS_FOREGROUND, XTERM_FG( 66), sizeof(XTERM_FG( 66))-1, T(COLOR_FG_5F8787), 3, T("%x<#5F8787>"), 11},
|
|
{ CS_FG( 67), CS_FOREGROUND, XTERM_FG( 67), sizeof(XTERM_FG( 67))-1, T(COLOR_FG_5F87AF), 3, T("%x<#5F87AF>"), 11},
|
|
{ CS_FG( 68), CS_FOREGROUND, XTERM_FG( 68), sizeof(XTERM_FG( 68))-1, T(COLOR_FG_5F87D7), 3, T("%x<#5F87D7>"), 11},
|
|
{ CS_FG( 69), CS_FOREGROUND, XTERM_FG( 69), sizeof(XTERM_FG( 69))-1, T(COLOR_FG_5F87FF), 3, T("%x<#5F87FF>"), 11},
|
|
{ CS_FG( 70), CS_FOREGROUND, XTERM_FG( 70), sizeof(XTERM_FG( 70))-1, T(COLOR_FG_5FAF00), 3, T("%x<#5FAF00>"), 11},
|
|
{ CS_FG( 71), CS_FOREGROUND, XTERM_FG( 71), sizeof(XTERM_FG( 71))-1, T(COLOR_FG_5FAF5F), 3, T("%x<#5FAF5F>"), 11},
|
|
{ CS_FG( 72), CS_FOREGROUND, XTERM_FG( 72), sizeof(XTERM_FG( 72))-1, T(COLOR_FG_5FAF87), 3, T("%x<#5FAF87>"), 11},
|
|
{ CS_FG( 73), CS_FOREGROUND, XTERM_FG( 73), sizeof(XTERM_FG( 73))-1, T(COLOR_FG_5FAFAF), 3, T("%x<#5FAFAF>"), 11},
|
|
{ CS_FG( 74), CS_FOREGROUND, XTERM_FG( 74), sizeof(XTERM_FG( 74))-1, T(COLOR_FG_5FAFD7), 3, T("%x<#5FAFD7>"), 11},
|
|
{ CS_FG( 75), CS_FOREGROUND, XTERM_FG( 75), sizeof(XTERM_FG( 75))-1, T(COLOR_FG_5FAFFF), 3, T("%x<#5FAFFF>"), 11},
|
|
{ CS_FG( 76), CS_FOREGROUND, XTERM_FG( 76), sizeof(XTERM_FG( 76))-1, T(COLOR_FG_5FD700), 3, T("%x<#5FD700>"), 11},
|
|
{ CS_FG( 77), CS_FOREGROUND, XTERM_FG( 77), sizeof(XTERM_FG( 77))-1, T(COLOR_FG_5FD75F), 3, T("%x<#5FD75F>"), 11},
|
|
{ CS_FG( 78), CS_FOREGROUND, XTERM_FG( 78), sizeof(XTERM_FG( 78))-1, T(COLOR_FG_5FD787), 3, T("%x<#5FD787>"), 11},
|
|
{ CS_FG( 79), CS_FOREGROUND, XTERM_FG( 79), sizeof(XTERM_FG( 79))-1, T(COLOR_FG_5FD7AF), 3, T("%x<#5FD7AF>"), 11},
|
|
{ CS_FG( 80), CS_FOREGROUND, XTERM_FG( 80), sizeof(XTERM_FG( 80))-1, T(COLOR_FG_5FD7D7), 3, T("%x<#5FD7D7>"), 11},
|
|
{ CS_FG( 81), CS_FOREGROUND, XTERM_FG( 81), sizeof(XTERM_FG( 81))-1, T(COLOR_FG_5FD7FF), 3, T("%x<#5FD7FF>"), 11},
|
|
{ CS_FG( 82), CS_FOREGROUND, XTERM_FG( 82), sizeof(XTERM_FG( 82))-1, T(COLOR_FG_5FFF00), 3, T("%x<#5FFF00>"), 11},
|
|
{ CS_FG( 83), CS_FOREGROUND, XTERM_FG( 83), sizeof(XTERM_FG( 83))-1, T(COLOR_FG_5FFF5F), 3, T("%x<#5FFF5F>"), 11},
|
|
{ CS_FG( 84), CS_FOREGROUND, XTERM_FG( 84), sizeof(XTERM_FG( 84))-1, T(COLOR_FG_5FFF87), 3, T("%x<#5FFF87>"), 11},
|
|
{ CS_FG( 85), CS_FOREGROUND, XTERM_FG( 85), sizeof(XTERM_FG( 85))-1, T(COLOR_FG_5FFFAF), 3, T("%x<#5FFFAF>"), 11},
|
|
{ CS_FG( 86), CS_FOREGROUND, XTERM_FG( 86), sizeof(XTERM_FG( 86))-1, T(COLOR_FG_5FFFD7), 3, T("%x<#5FFFD7>"), 11},
|
|
{ CS_FG( 87), CS_FOREGROUND, XTERM_FG( 87), sizeof(XTERM_FG( 87))-1, T(COLOR_FG_5FFFFF), 3, T("%x<#5FFFFF>"), 11},
|
|
{ CS_FG( 88), CS_FOREGROUND, XTERM_FG( 88), sizeof(XTERM_FG( 88))-1, T(COLOR_FG_870000), 3, T("%x<#870000>"), 11},
|
|
{ CS_FG( 89), CS_FOREGROUND, XTERM_FG( 89), sizeof(XTERM_FG( 89))-1, T(COLOR_FG_87005F), 3, T("%x<#87005F>"), 11},
|
|
{ CS_FG( 90), CS_FOREGROUND, XTERM_FG( 90), sizeof(XTERM_FG( 90))-1, T(COLOR_FG_870087), 3, T("%x<#870087>"), 11},
|
|
{ CS_FG( 91), CS_FOREGROUND, XTERM_FG( 91), sizeof(XTERM_FG( 91))-1, T(COLOR_FG_8700AF), 3, T("%x<#8700AF>"), 11},
|
|
{ CS_FG( 92), CS_FOREGROUND, XTERM_FG( 92), sizeof(XTERM_FG( 92))-1, T(COLOR_FG_8700D7), 3, T("%x<#8700D7>"), 11},
|
|
{ CS_FG( 93), CS_FOREGROUND, XTERM_FG( 93), sizeof(XTERM_FG( 93))-1, T(COLOR_FG_8700FF), 3, T("%x<#8700FF>"), 11},
|
|
{ CS_FG( 94), CS_FOREGROUND, XTERM_FG( 94), sizeof(XTERM_FG( 94))-1, T(COLOR_FG_875F00), 3, T("%x<#875F00>"), 11},
|
|
{ CS_FG( 95), CS_FOREGROUND, XTERM_FG( 95), sizeof(XTERM_FG( 95))-1, T(COLOR_FG_875F5F), 3, T("%x<#875F5F>"), 11},
|
|
{ CS_FG( 96), CS_FOREGROUND, XTERM_FG( 96), sizeof(XTERM_FG( 96))-1, T(COLOR_FG_875F87), 3, T("%x<#875F87>"), 11},
|
|
{ CS_FG( 97), CS_FOREGROUND, XTERM_FG( 97), sizeof(XTERM_FG( 97))-1, T(COLOR_FG_875FAF), 3, T("%x<#875FAF>"), 11},
|
|
{ CS_FG( 98), CS_FOREGROUND, XTERM_FG( 98), sizeof(XTERM_FG( 98))-1, T(COLOR_FG_875FD7), 3, T("%x<#875FD7>"), 11},
|
|
{ CS_FG( 99), CS_FOREGROUND, XTERM_FG( 99), sizeof(XTERM_FG( 99))-1, T(COLOR_FG_875FFF), 3, T("%x<#875FFF>"), 11},
|
|
{ CS_FG(100), CS_FOREGROUND, XTERM_FG(100), sizeof(XTERM_FG(100))-1, T(COLOR_FG_878700), 3, T("%x<#878700>"), 11},
|
|
{ CS_FG(101), CS_FOREGROUND, XTERM_FG(101), sizeof(XTERM_FG(101))-1, T(COLOR_FG_87875F), 3, T("%x<#87875F>"), 11},
|
|
{ CS_FG(102), CS_FOREGROUND, XTERM_FG(102), sizeof(XTERM_FG(102))-1, T(COLOR_FG_878787), 3, T("%x<#878787>"), 11},
|
|
{ CS_FG(103), CS_FOREGROUND, XTERM_FG(103), sizeof(XTERM_FG(103))-1, T(COLOR_FG_8787AF), 3, T("%x<#8787AF>"), 11},
|
|
{ CS_FG(104), CS_FOREGROUND, XTERM_FG(104), sizeof(XTERM_FG(104))-1, T(COLOR_FG_8787D7), 3, T("%x<#8787D7>"), 11},
|
|
{ CS_FG(105), CS_FOREGROUND, XTERM_FG(105), sizeof(XTERM_FG(105))-1, T(COLOR_FG_8787FF), 3, T("%x<#8787FF>"), 11},
|
|
{ CS_FG(106), CS_FOREGROUND, XTERM_FG(106), sizeof(XTERM_FG(106))-1, T(COLOR_FG_87AF00), 3, T("%x<#87AF00>"), 11},
|
|
{ CS_FG(107), CS_FOREGROUND, XTERM_FG(107), sizeof(XTERM_FG(107))-1, T(COLOR_FG_87AF5F), 3, T("%x<#87AF5F>"), 11},
|
|
{ CS_FG(108), CS_FOREGROUND, XTERM_FG(108), sizeof(XTERM_FG(108))-1, T(COLOR_FG_87AF87), 3, T("%x<#87AF87>"), 11},
|
|
{ CS_FG(109), CS_FOREGROUND, XTERM_FG(109), sizeof(XTERM_FG(109))-1, T(COLOR_FG_87AFAF), 3, T("%x<#87AFAF>"), 11},
|
|
{ CS_FG(110), CS_FOREGROUND, XTERM_FG(110), sizeof(XTERM_FG(110))-1, T(COLOR_FG_87AFD7), 3, T("%x<#87AFD7>"), 11},
|
|
{ CS_FG(111), CS_FOREGROUND, XTERM_FG(111), sizeof(XTERM_FG(111))-1, T(COLOR_FG_87AFFF), 3, T("%x<#87AFFF>"), 11},
|
|
{ CS_FG(112), CS_FOREGROUND, XTERM_FG(112), sizeof(XTERM_FG(112))-1, T(COLOR_FG_87D700), 3, T("%x<#87D700>"), 11},
|
|
{ CS_FG(113), CS_FOREGROUND, XTERM_FG(113), sizeof(XTERM_FG(113))-1, T(COLOR_FG_87D75A), 3, T("%x<#87D75A>"), 11},
|
|
{ CS_FG(114), CS_FOREGROUND, XTERM_FG(114), sizeof(XTERM_FG(114))-1, T(COLOR_FG_87D787), 3, T("%x<#87D787>"), 11},
|
|
{ CS_FG(115), CS_FOREGROUND, XTERM_FG(115), sizeof(XTERM_FG(115))-1, T(COLOR_FG_87D7AF), 3, T("%x<#87D7AF>"), 11},
|
|
{ CS_FG(116), CS_FOREGROUND, XTERM_FG(116), sizeof(XTERM_FG(116))-1, T(COLOR_FG_87D7D7), 3, T("%x<#87D7D7>"), 11},
|
|
{ CS_FG(117), CS_FOREGROUND, XTERM_FG(117), sizeof(XTERM_FG(117))-1, T(COLOR_FG_87D7FF), 3, T("%x<#87D7FF>"), 11},
|
|
{ CS_FG(118), CS_FOREGROUND, XTERM_FG(118), sizeof(XTERM_FG(118))-1, T(COLOR_FG_87FF00), 3, T("%x<#87FF00>"), 11},
|
|
{ CS_FG(119), CS_FOREGROUND, XTERM_FG(119), sizeof(XTERM_FG(119))-1, T(COLOR_FG_87FF5F), 3, T("%x<#87FF5F>"), 11},
|
|
{ CS_FG(120), CS_FOREGROUND, XTERM_FG(120), sizeof(XTERM_FG(120))-1, T(COLOR_FG_87FF87), 3, T("%x<#87FF87>"), 11},
|
|
{ CS_FG(121), CS_FOREGROUND, XTERM_FG(121), sizeof(XTERM_FG(121))-1, T(COLOR_FG_87FFAF), 3, T("%x<#87FFAF>"), 11},
|
|
{ CS_FG(122), CS_FOREGROUND, XTERM_FG(122), sizeof(XTERM_FG(122))-1, T(COLOR_FG_87FFD7), 3, T("%x<#87FFD7>"), 11},
|
|
{ CS_FG(123), CS_FOREGROUND, XTERM_FG(123), sizeof(XTERM_FG(123))-1, T(COLOR_FG_87FFFF), 3, T("%x<#87FFFF>"), 11},
|
|
{ CS_FG(124), CS_FOREGROUND, XTERM_FG(124), sizeof(XTERM_FG(124))-1, T(COLOR_FG_AF0000), 3, T("%x<#AF0000>"), 11},
|
|
{ CS_FG(125), CS_FOREGROUND, XTERM_FG(125), sizeof(XTERM_FG(125))-1, T(COLOR_FG_AF005F), 3, T("%x<#AF005F>"), 11},
|
|
{ CS_FG(126), CS_FOREGROUND, XTERM_FG(126), sizeof(XTERM_FG(126))-1, T(COLOR_FG_AF0087), 3, T("%x<#AF0087>"), 11},
|
|
{ CS_FG(127), CS_FOREGROUND, XTERM_FG(127), sizeof(XTERM_FG(127))-1, T(COLOR_FG_AF00AF), 3, T("%x<#AF00AF>"), 11},
|
|
{ CS_FG(128), CS_FOREGROUND, XTERM_FG(128), sizeof(XTERM_FG(128))-1, T(COLOR_FG_AF00D7), 3, T("%x<#AF00D7>"), 11},
|
|
{ CS_FG(129), CS_FOREGROUND, XTERM_FG(129), sizeof(XTERM_FG(129))-1, T(COLOR_FG_AF00FF), 3, T("%x<#AF00FF>"), 11},
|
|
{ CS_FG(130), CS_FOREGROUND, XTERM_FG(130), sizeof(XTERM_FG(130))-1, T(COLOR_FG_AF5F00), 3, T("%x<#AF5F00>"), 11},
|
|
{ CS_FG(131), CS_FOREGROUND, XTERM_FG(131), sizeof(XTERM_FG(131))-1, T(COLOR_FG_AF5F5F), 3, T("%x<#AF5F5F>"), 11},
|
|
{ CS_FG(132), CS_FOREGROUND, XTERM_FG(132), sizeof(XTERM_FG(132))-1, T(COLOR_FG_AF5F87), 3, T("%x<#AF5F87>"), 11},
|
|
{ CS_FG(133), CS_FOREGROUND, XTERM_FG(133), sizeof(XTERM_FG(133))-1, T(COLOR_FG_AF5FAF), 3, T("%x<#AF5FAF>"), 11},
|
|
{ CS_FG(134), CS_FOREGROUND, XTERM_FG(134), sizeof(XTERM_FG(134))-1, T(COLOR_FG_AF5FD7), 3, T("%x<#AF5FD7>"), 11},
|
|
{ CS_FG(135), CS_FOREGROUND, XTERM_FG(135), sizeof(XTERM_FG(135))-1, T(COLOR_FG_AF5FFF), 3, T("%x<#AF5FFF>"), 11},
|
|
{ CS_FG(136), CS_FOREGROUND, XTERM_FG(136), sizeof(XTERM_FG(136))-1, T(COLOR_FG_AF8700), 3, T("%x<#AF8700>"), 11},
|
|
{ CS_FG(137), CS_FOREGROUND, XTERM_FG(137), sizeof(XTERM_FG(137))-1, T(COLOR_FG_AF875F), 3, T("%x<#AF875F>"), 11},
|
|
{ CS_FG(138), CS_FOREGROUND, XTERM_FG(138), sizeof(XTERM_FG(138))-1, T(COLOR_FG_AF8787), 3, T("%x<#AF8787>"), 11},
|
|
{ CS_FG(139), CS_FOREGROUND, XTERM_FG(139), sizeof(XTERM_FG(139))-1, T(COLOR_FG_AF87AF), 3, T("%x<#AF87AF>"), 11},
|
|
{ CS_FG(140), CS_FOREGROUND, XTERM_FG(140), sizeof(XTERM_FG(140))-1, T(COLOR_FG_AF87D7), 3, T("%x<#AF87D7>"), 11},
|
|
{ CS_FG(141), CS_FOREGROUND, XTERM_FG(141), sizeof(XTERM_FG(141))-1, T(COLOR_FG_AF87FF), 3, T("%x<#AF87FF>"), 11},
|
|
{ CS_FG(142), CS_FOREGROUND, XTERM_FG(142), sizeof(XTERM_FG(142))-1, T(COLOR_FG_AFAF00), 3, T("%x<#AFAF00>"), 11},
|
|
{ CS_FG(143), CS_FOREGROUND, XTERM_FG(143), sizeof(XTERM_FG(143))-1, T(COLOR_FG_AFAF5F), 3, T("%x<#AFAF5F>"), 11},
|
|
{ CS_FG(144), CS_FOREGROUND, XTERM_FG(144), sizeof(XTERM_FG(144))-1, T(COLOR_FG_AFAF87), 3, T("%x<#AFAF87>"), 11},
|
|
{ CS_FG(145), CS_FOREGROUND, XTERM_FG(145), sizeof(XTERM_FG(145))-1, T(COLOR_FG_AFAFAF), 3, T("%x<#AFAFAF>"), 11},
|
|
{ CS_FG(146), CS_FOREGROUND, XTERM_FG(146), sizeof(XTERM_FG(146))-1, T(COLOR_FG_AFAFD7), 3, T("%x<#AFAFD7>"), 11},
|
|
{ CS_FG(147), CS_FOREGROUND, XTERM_FG(147), sizeof(XTERM_FG(147))-1, T(COLOR_FG_AFAFFF), 3, T("%x<#AFAFFF>"), 11},
|
|
{ CS_FG(148), CS_FOREGROUND, XTERM_FG(148), sizeof(XTERM_FG(148))-1, T(COLOR_FG_AFD700), 3, T("%x<#AFD700>"), 11},
|
|
{ CS_FG(149), CS_FOREGROUND, XTERM_FG(149), sizeof(XTERM_FG(149))-1, T(COLOR_FG_AFD75F), 3, T("%x<#AFD75F>"), 11},
|
|
{ CS_FG(150), CS_FOREGROUND, XTERM_FG(150), sizeof(XTERM_FG(150))-1, T(COLOR_FG_AFD787), 3, T("%x<#AFD787>"), 11},
|
|
{ CS_FG(151), CS_FOREGROUND, XTERM_FG(151), sizeof(XTERM_FG(151))-1, T(COLOR_FG_AFD7AF), 3, T("%x<#AFD7AF>"), 11},
|
|
{ CS_FG(152), CS_FOREGROUND, XTERM_FG(152), sizeof(XTERM_FG(152))-1, T(COLOR_FG_AFD7D7), 3, T("%x<#AFD7D7>"), 11},
|
|
{ CS_FG(153), CS_FOREGROUND, XTERM_FG(153), sizeof(XTERM_FG(153))-1, T(COLOR_FG_AFD7FF), 3, T("%x<#AFD7FF>"), 11},
|
|
{ CS_FG(154), CS_FOREGROUND, XTERM_FG(154), sizeof(XTERM_FG(154))-1, T(COLOR_FG_AFFF00), 3, T("%x<#AFFF00>"), 11},
|
|
{ CS_FG(155), CS_FOREGROUND, XTERM_FG(155), sizeof(XTERM_FG(155))-1, T(COLOR_FG_AFFF5F), 3, T("%x<#AFFF5F>"), 11},
|
|
{ CS_FG(156), CS_FOREGROUND, XTERM_FG(156), sizeof(XTERM_FG(156))-1, T(COLOR_FG_AFFF87), 3, T("%x<#AFFF87>"), 11},
|
|
{ CS_FG(157), CS_FOREGROUND, XTERM_FG(157), sizeof(XTERM_FG(157))-1, T(COLOR_FG_AFFFAF), 3, T("%x<#AFFFAF>"), 11},
|
|
{ CS_FG(158), CS_FOREGROUND, XTERM_FG(158), sizeof(XTERM_FG(158))-1, T(COLOR_FG_AFFFD7), 3, T("%x<#AFFFD7>"), 11},
|
|
{ CS_FG(159), CS_FOREGROUND, XTERM_FG(159), sizeof(XTERM_FG(159))-1, T(COLOR_FG_AFFFFF), 3, T("%x<#AFFFFF>"), 11},
|
|
{ CS_FG(160), CS_FOREGROUND, XTERM_FG(160), sizeof(XTERM_FG(160))-1, T(COLOR_FG_D70000), 3, T("%x<#D70000>"), 11},
|
|
{ CS_FG(161), CS_FOREGROUND, XTERM_FG(161), sizeof(XTERM_FG(161))-1, T(COLOR_FG_D7005F), 3, T("%x<#D7005F>"), 11},
|
|
{ CS_FG(162), CS_FOREGROUND, XTERM_FG(162), sizeof(XTERM_FG(162))-1, T(COLOR_FG_D70087), 3, T("%x<#D70087>"), 11},
|
|
{ CS_FG(163), CS_FOREGROUND, XTERM_FG(163), sizeof(XTERM_FG(163))-1, T(COLOR_FG_D700AF), 3, T("%x<#D700AF>"), 11},
|
|
{ CS_FG(164), CS_FOREGROUND, XTERM_FG(164), sizeof(XTERM_FG(164))-1, T(COLOR_FG_D700D7), 3, T("%x<#D700D7>"), 11},
|
|
{ CS_FG(165), CS_FOREGROUND, XTERM_FG(165), sizeof(XTERM_FG(165))-1, T(COLOR_FG_D700FF), 3, T("%x<#D700FF>"), 11},
|
|
{ CS_FG(166), CS_FOREGROUND, XTERM_FG(166), sizeof(XTERM_FG(166))-1, T(COLOR_FG_D75F00), 3, T("%x<#D75F00>"), 11},
|
|
{ CS_FG(167), CS_FOREGROUND, XTERM_FG(167), sizeof(XTERM_FG(167))-1, T(COLOR_FG_D75F5F), 3, T("%x<#D75F5F>"), 11},
|
|
{ CS_FG(168), CS_FOREGROUND, XTERM_FG(168), sizeof(XTERM_FG(168))-1, T(COLOR_FG_D75F87), 3, T("%x<#D75F87>"), 11},
|
|
{ CS_FG(169), CS_FOREGROUND, XTERM_FG(169), sizeof(XTERM_FG(169))-1, T(COLOR_FG_D75FAF), 3, T("%x<#D75FAF>"), 11},
|
|
{ CS_FG(170), CS_FOREGROUND, XTERM_FG(170), sizeof(XTERM_FG(170))-1, T(COLOR_FG_D75FD7), 3, T("%x<#D75FD7>"), 11},
|
|
{ CS_FG(171), CS_FOREGROUND, XTERM_FG(171), sizeof(XTERM_FG(171))-1, T(COLOR_FG_D75FFF), 3, T("%x<#D75FFF>"), 11},
|
|
{ CS_FG(172), CS_FOREGROUND, XTERM_FG(172), sizeof(XTERM_FG(172))-1, T(COLOR_FG_D78700), 3, T("%x<#D78700>"), 11},
|
|
{ CS_FG(173), CS_FOREGROUND, XTERM_FG(173), sizeof(XTERM_FG(173))-1, T(COLOR_FG_D7875A), 3, T("%x<#D7875A>"), 11},
|
|
{ CS_FG(174), CS_FOREGROUND, XTERM_FG(174), sizeof(XTERM_FG(174))-1, T(COLOR_FG_D78787), 3, T("%x<#D78787>"), 11},
|
|
{ CS_FG(175), CS_FOREGROUND, XTERM_FG(175), sizeof(XTERM_FG(175))-1, T(COLOR_FG_D787AF), 3, T("%x<#D787AF>"), 11},
|
|
{ CS_FG(176), CS_FOREGROUND, XTERM_FG(176), sizeof(XTERM_FG(176))-1, T(COLOR_FG_D787D7), 3, T("%x<#D787D7>"), 11},
|
|
{ CS_FG(177), CS_FOREGROUND, XTERM_FG(177), sizeof(XTERM_FG(177))-1, T(COLOR_FG_D787FF), 3, T("%x<#D787FF>"), 11},
|
|
{ CS_FG(178), CS_FOREGROUND, XTERM_FG(178), sizeof(XTERM_FG(178))-1, T(COLOR_FG_D7AF00), 3, T("%x<#D7AF00>"), 11},
|
|
{ CS_FG(179), CS_FOREGROUND, XTERM_FG(179), sizeof(XTERM_FG(179))-1, T(COLOR_FG_D7AF5A), 3, T("%x<#D7AF5A>"), 11},
|
|
{ CS_FG(180), CS_FOREGROUND, XTERM_FG(180), sizeof(XTERM_FG(180))-1, T(COLOR_FG_D7AF87), 3, T("%x<#D7AF87>"), 11},
|
|
{ CS_FG(181), CS_FOREGROUND, XTERM_FG(181), sizeof(XTERM_FG(181))-1, T(COLOR_FG_D7AFAF), 3, T("%x<#D7AFAF>"), 11},
|
|
{ CS_FG(182), CS_FOREGROUND, XTERM_FG(182), sizeof(XTERM_FG(182))-1, T(COLOR_FG_D7AFD7), 3, T("%x<#D7AFD7>"), 11},
|
|
{ CS_FG(183), CS_FOREGROUND, XTERM_FG(183), sizeof(XTERM_FG(183))-1, T(COLOR_FG_D7AFFF), 3, T("%x<#D7AFFF>"), 11},
|
|
{ CS_FG(184), CS_FOREGROUND, XTERM_FG(184), sizeof(XTERM_FG(184))-1, T(COLOR_FG_D7D700), 3, T("%x<#D7D700>"), 11},
|
|
{ CS_FG(185), CS_FOREGROUND, XTERM_FG(185), sizeof(XTERM_FG(185))-1, T(COLOR_FG_D7D75F), 3, T("%x<#D7D75F>"), 11},
|
|
{ CS_FG(186), CS_FOREGROUND, XTERM_FG(186), sizeof(XTERM_FG(186))-1, T(COLOR_FG_D7D787), 3, T("%x<#D7D787>"), 11},
|
|
{ CS_FG(187), CS_FOREGROUND, XTERM_FG(187), sizeof(XTERM_FG(187))-1, T(COLOR_FG_D7D7AF), 3, T("%x<#D7D7AF>"), 11},
|
|
{ CS_FG(188), CS_FOREGROUND, XTERM_FG(188), sizeof(XTERM_FG(188))-1, T(COLOR_FG_D7D7D7), 3, T("%x<#D7D7D7>"), 11},
|
|
{ CS_FG(189), CS_FOREGROUND, XTERM_FG(189), sizeof(XTERM_FG(189))-1, T(COLOR_FG_D7D7FF), 3, T("%x<#D7D7FF>"), 11},
|
|
{ CS_FG(190), CS_FOREGROUND, XTERM_FG(190), sizeof(XTERM_FG(190))-1, T(COLOR_FG_D7FF00), 3, T("%x<#D7FF00>"), 11},
|
|
{ CS_FG(191), CS_FOREGROUND, XTERM_FG(191), sizeof(XTERM_FG(191))-1, T(COLOR_FG_D7FF5F), 3, T("%x<#D7FF5F>"), 11},
|
|
{ CS_FG(192), CS_FOREGROUND, XTERM_FG(192), sizeof(XTERM_FG(192))-1, T(COLOR_FG_D7FF87), 3, T("%x<#D7FF87>"), 11},
|
|
{ CS_FG(193), CS_FOREGROUND, XTERM_FG(193), sizeof(XTERM_FG(193))-1, T(COLOR_FG_D7FFAF), 3, T("%x<#D7FFAF>"), 11},
|
|
{ CS_FG(194), CS_FOREGROUND, XTERM_FG(194), sizeof(XTERM_FG(194))-1, T(COLOR_FG_D7FFD7), 3, T("%x<#D7FFD7>"), 11},
|
|
{ CS_FG(195), CS_FOREGROUND, XTERM_FG(195), sizeof(XTERM_FG(195))-1, T(COLOR_FG_D7FFFF), 3, T("%x<#D7FFFF>"), 11},
|
|
{ CS_FG(196), CS_FOREGROUND, XTERM_FG(196), sizeof(XTERM_FG(196))-1, T(COLOR_FG_FF0000), 3, T("%x<#FF0000>"), 11},
|
|
{ CS_FG(197), CS_FOREGROUND, XTERM_FG(197), sizeof(XTERM_FG(197))-1, T(COLOR_FG_FF005F), 3, T("%x<#FF005F>"), 11},
|
|
{ CS_FG(198), CS_FOREGROUND, XTERM_FG(198), sizeof(XTERM_FG(198))-1, T(COLOR_FG_FF0087), 3, T("%x<#FF0087>"), 11},
|
|
{ CS_FG(199), CS_FOREGROUND, XTERM_FG(199), sizeof(XTERM_FG(199))-1, T(COLOR_FG_FF00AF), 3, T("%x<#FF00AF>"), 11},
|
|
{ CS_FG(200), CS_FOREGROUND, XTERM_FG(200), sizeof(XTERM_FG(200))-1, T(COLOR_FG_FF00D7), 3, T("%x<#FF00D7>"), 11},
|
|
{ CS_FG(201), CS_FOREGROUND, XTERM_FG(201), sizeof(XTERM_FG(201))-1, T(COLOR_FG_FF00FF), 3, T("%x<#FF00FF>"), 11},
|
|
{ CS_FG(202), CS_FOREGROUND, XTERM_FG(202), sizeof(XTERM_FG(202))-1, T(COLOR_FG_FF5F00), 3, T("%x<#FF5F00>"), 11},
|
|
{ CS_FG(203), CS_FOREGROUND, XTERM_FG(203), sizeof(XTERM_FG(203))-1, T(COLOR_FG_FF5F5F), 3, T("%x<#FF5F5F>"), 11},
|
|
{ CS_FG(204), CS_FOREGROUND, XTERM_FG(204), sizeof(XTERM_FG(204))-1, T(COLOR_FG_FF5F87), 3, T("%x<#FF5F87>"), 11},
|
|
{ CS_FG(205), CS_FOREGROUND, XTERM_FG(205), sizeof(XTERM_FG(205))-1, T(COLOR_FG_FF5FAF), 3, T("%x<#FF5FAF>"), 11},
|
|
{ CS_FG(206), CS_FOREGROUND, XTERM_FG(206), sizeof(XTERM_FG(206))-1, T(COLOR_FG_FF5FD7), 3, T("%x<#FF5FD7>"), 11},
|
|
{ CS_FG(207), CS_FOREGROUND, XTERM_FG(207), sizeof(XTERM_FG(207))-1, T(COLOR_FG_FF5FFF), 3, T("%x<#FF5FFF>"), 11},
|
|
{ CS_FG(208), CS_FOREGROUND, XTERM_FG(208), sizeof(XTERM_FG(208))-1, T(COLOR_FG_FF8700), 3, T("%x<#FF8700>"), 11},
|
|
{ CS_FG(209), CS_FOREGROUND, XTERM_FG(209), sizeof(XTERM_FG(209))-1, T(COLOR_FG_FF875F), 3, T("%x<#FF875F>"), 11},
|
|
{ CS_FG(210), CS_FOREGROUND, XTERM_FG(210), sizeof(XTERM_FG(210))-1, T(COLOR_FG_FF8787), 3, T("%x<#FF8787>"), 11},
|
|
{ CS_FG(211), CS_FOREGROUND, XTERM_FG(211), sizeof(XTERM_FG(211))-1, T(COLOR_FG_FF87AF), 3, T("%x<#FF87AF>"), 11},
|
|
{ CS_FG(212), CS_FOREGROUND, XTERM_FG(212), sizeof(XTERM_FG(212))-1, T(COLOR_FG_FF87D7), 3, T("%x<#FF87D7>"), 11},
|
|
{ CS_FG(213), CS_FOREGROUND, XTERM_FG(213), sizeof(XTERM_FG(213))-1, T(COLOR_FG_FF87FF), 3, T("%x<#FF87FF>"), 11},
|
|
{ CS_FG(214), CS_FOREGROUND, XTERM_FG(214), sizeof(XTERM_FG(214))-1, T(COLOR_FG_FFAF00), 3, T("%x<#FFAF00>"), 11},
|
|
{ CS_FG(215), CS_FOREGROUND, XTERM_FG(215), sizeof(XTERM_FG(215))-1, T(COLOR_FG_FFAF5F), 3, T("%x<#FFAF5F>"), 11},
|
|
{ CS_FG(216), CS_FOREGROUND, XTERM_FG(216), sizeof(XTERM_FG(216))-1, T(COLOR_FG_FFAF87), 3, T("%x<#FFAF87>"), 11},
|
|
{ CS_FG(217), CS_FOREGROUND, XTERM_FG(217), sizeof(XTERM_FG(217))-1, T(COLOR_FG_FFAFAF), 3, T("%x<#FFAFAF>"), 11},
|
|
{ CS_FG(218), CS_FOREGROUND, XTERM_FG(218), sizeof(XTERM_FG(218))-1, T(COLOR_FG_FFAFD7), 3, T("%x<#FFAFD7>"), 11},
|
|
{ CS_FG(219), CS_FOREGROUND, XTERM_FG(219), sizeof(XTERM_FG(219))-1, T(COLOR_FG_FFAFFF), 3, T("%x<#FFAFFF>"), 11},
|
|
{ CS_FG(220), CS_FOREGROUND, XTERM_FG(220), sizeof(XTERM_FG(220))-1, T(COLOR_FG_FFD700), 3, T("%x<#FFD700>"), 11},
|
|
{ CS_FG(221), CS_FOREGROUND, XTERM_FG(221), sizeof(XTERM_FG(221))-1, T(COLOR_FG_FFD75F), 3, T("%x<#FFD75F>"), 11},
|
|
{ CS_FG(222), CS_FOREGROUND, XTERM_FG(222), sizeof(XTERM_FG(222))-1, T(COLOR_FG_FFD787), 3, T("%x<#FFD787>"), 11},
|
|
{ CS_FG(223), CS_FOREGROUND, XTERM_FG(223), sizeof(XTERM_FG(223))-1, T(COLOR_FG_FFD7AF), 3, T("%x<#FFD7AF>"), 11},
|
|
{ CS_FG(224), CS_FOREGROUND, XTERM_FG(224), sizeof(XTERM_FG(224))-1, T(COLOR_FG_FFD7D7), 3, T("%x<#FFD7D7>"), 11},
|
|
{ CS_FG(225), CS_FOREGROUND, XTERM_FG(225), sizeof(XTERM_FG(225))-1, T(COLOR_FG_FFD7FF), 3, T("%x<#FFD7FF>"), 11},
|
|
{ CS_FG(226), CS_FOREGROUND, XTERM_FG(226), sizeof(XTERM_FG(226))-1, T(COLOR_FG_FFFF00), 3, T("%x<#FFFF00>"), 11},
|
|
{ CS_FG(227), CS_FOREGROUND, XTERM_FG(227), sizeof(XTERM_FG(227))-1, T(COLOR_FG_FFFF5F), 3, T("%x<#FFFF5F>"), 11},
|
|
{ CS_FG(228), CS_FOREGROUND, XTERM_FG(228), sizeof(XTERM_FG(228))-1, T(COLOR_FG_FFFF87), 3, T("%x<#FFFF87>"), 11},
|
|
{ CS_FG(229), CS_FOREGROUND, XTERM_FG(229), sizeof(XTERM_FG(229))-1, T(COLOR_FG_FFFFAF), 3, T("%x<#FFFFAF>"), 11},
|
|
{ CS_FG(230), CS_FOREGROUND, XTERM_FG(230), sizeof(XTERM_FG(230))-1, T(COLOR_FG_FFFFD7), 3, T("%x<#FFFFD7>"), 11},
|
|
{ CS_FG(231), CS_FOREGROUND, XTERM_FG(231), sizeof(XTERM_FG(231))-1, T(COLOR_FG_FFFFFF_2),3, T("%x<#FFFFFF>"), 11},
|
|
{ CS_FG(232), CS_FOREGROUND, XTERM_FG(232), sizeof(XTERM_FG(232))-1, T(COLOR_FG_080808), 3, T("%x<#080808>"), 11},
|
|
{ CS_FG(233), CS_FOREGROUND, XTERM_FG(233), sizeof(XTERM_FG(233))-1, T(COLOR_FG_121212), 3, T("%x<#121212>"), 11},
|
|
{ CS_FG(234), CS_FOREGROUND, XTERM_FG(234), sizeof(XTERM_FG(234))-1, T(COLOR_FG_1C1C1C), 3, T("%x<#1C1C1C>"), 11},
|
|
{ CS_FG(235), CS_FOREGROUND, XTERM_FG(235), sizeof(XTERM_FG(235))-1, T(COLOR_FG_262626), 3, T("%x<#262626>"), 11},
|
|
{ CS_FG(236), CS_FOREGROUND, XTERM_FG(236), sizeof(XTERM_FG(236))-1, T(COLOR_FG_303030), 3, T("%x<#303030>"), 11},
|
|
{ CS_FG(237), CS_FOREGROUND, XTERM_FG(237), sizeof(XTERM_FG(237))-1, T(COLOR_FG_3A3A3A), 3, T("%x<#3A3A3A>"), 11},
|
|
{ CS_FG(238), CS_FOREGROUND, XTERM_FG(238), sizeof(XTERM_FG(238))-1, T(COLOR_FG_444444), 3, T("%x<#444444>"), 11},
|
|
{ CS_FG(239), CS_FOREGROUND, XTERM_FG(239), sizeof(XTERM_FG(239))-1, T(COLOR_FG_4E4E4E), 3, T("%x<#4E4E4E>"), 11},
|
|
{ CS_FG(240), CS_FOREGROUND, XTERM_FG(240), sizeof(XTERM_FG(240))-1, T(COLOR_FG_585858), 3, T("%x<#585858>"), 11},
|
|
{ CS_FG(241), CS_FOREGROUND, XTERM_FG(241), sizeof(XTERM_FG(241))-1, T(COLOR_FG_626262), 3, T("%x<#626262>"), 11},
|
|
{ CS_FG(242), CS_FOREGROUND, XTERM_FG(242), sizeof(XTERM_FG(242))-1, T(COLOR_FG_6C6C6C), 3, T("%x<#6C6C6C>"), 11},
|
|
{ CS_FG(243), CS_FOREGROUND, XTERM_FG(243), sizeof(XTERM_FG(243))-1, T(COLOR_FG_767676), 3, T("%x<#767676>"), 11},
|
|
{ CS_FG(244), CS_FOREGROUND, XTERM_FG(244), sizeof(XTERM_FG(244))-1, T(COLOR_FG_808080), 3, T("%x<#808080>"), 11},
|
|
{ CS_FG(245), CS_FOREGROUND, XTERM_FG(245), sizeof(XTERM_FG(245))-1, T(COLOR_FG_8A8A8A), 3, T("%x<#8A8A8A>"), 11},
|
|
{ CS_FG(246), CS_FOREGROUND, XTERM_FG(246), sizeof(XTERM_FG(246))-1, T(COLOR_FG_949494), 3, T("%x<#949494>"), 11},
|
|
{ CS_FG(247), CS_FOREGROUND, XTERM_FG(247), sizeof(XTERM_FG(247))-1, T(COLOR_FG_9E9E9E), 3, T("%x<#9E9E9E>"), 11},
|
|
{ CS_FG(248), CS_FOREGROUND, XTERM_FG(248), sizeof(XTERM_FG(248))-1, T(COLOR_FG_A8A8A8), 3, T("%x<#A8A8A8>"), 11},
|
|
{ CS_FG(249), CS_FOREGROUND, XTERM_FG(249), sizeof(XTERM_FG(249))-1, T(COLOR_FG_B2B2B2), 3, T("%x<#B2B2B2>"), 11},
|
|
{ CS_FG(250), CS_FOREGROUND, XTERM_FG(250), sizeof(XTERM_FG(250))-1, T(COLOR_FG_BCBCBC), 3, T("%x<#BCBCBC>"), 11},
|
|
{ CS_FG(251), CS_FOREGROUND, XTERM_FG(251), sizeof(XTERM_FG(251))-1, T(COLOR_FG_C6C6C6), 3, T("%x<#C6C6C6>"), 11},
|
|
{ CS_FG(252), CS_FOREGROUND, XTERM_FG(252), sizeof(XTERM_FG(252))-1, T(COLOR_FG_D0D0D0), 3, T("%x<#D0D0D0>"), 11},
|
|
{ CS_FG(253), CS_FOREGROUND, XTERM_FG(253), sizeof(XTERM_FG(253))-1, T(COLOR_FG_DADADA), 3, T("%x<#DADADA>"), 11},
|
|
{ CS_FG(254), CS_FOREGROUND, XTERM_FG(254), sizeof(XTERM_FG(254))-1, T(COLOR_FG_E4E4E4), 3, T("%x<#E4E4E4>"), 11},
|
|
{ CS_FG(255), CS_FOREGROUND, XTERM_FG(255), sizeof(XTERM_FG(255))-1, T(COLOR_FG_EEEEEE), 3, T("%x<#EEEEEE>"), 11},
|
|
{ CS_BG_BLACK, CS_BACKGROUND, ANSI_BBLACK, sizeof(ANSI_BBLACK)-1, T(COLOR_BG_BLACK), 3, T("%xX"), 3}, // COLOR_INDEX_BG
|
|
{ CS_BG_RED, CS_BACKGROUND, ANSI_BRED, sizeof(ANSI_BRED)-1, T(COLOR_BG_RED), 3, T("%xR"), 3},
|
|
{ CS_BG_GREEN, CS_BACKGROUND, ANSI_BGREEN, sizeof(ANSI_BGREEN)-1, T(COLOR_BG_GREEN), 3, T("%xG"), 3},
|
|
{ CS_BG_YELLOW, CS_BACKGROUND, ANSI_BYELLOW, sizeof(ANSI_BYELLOW)-1, T(COLOR_BG_YELLOW), 3, T("%xY"), 3},
|
|
{ CS_BG_BLUE, CS_BACKGROUND, ANSI_BBLUE, sizeof(ANSI_BBLUE)-1, T(COLOR_BG_BLUE), 3, T("%xB"), 3},
|
|
{ CS_BG_MAGENTA, CS_BACKGROUND, ANSI_BMAGENTA, sizeof(ANSI_BMAGENTA)-1, T(COLOR_BG_MAGENTA), 3, T("%xM"), 3},
|
|
{ CS_BG_CYAN, CS_BACKGROUND, ANSI_BCYAN, sizeof(ANSI_BCYAN)-1, T(COLOR_BG_CYAN), 3, T("%xC"), 3},
|
|
{ CS_BG_WHITE, CS_BACKGROUND, ANSI_BWHITE, sizeof(ANSI_BWHITE)-1, T(COLOR_BG_WHITE), 3, T("%xW"), 3},
|
|
{ CS_BG( 8), CS_BACKGROUND, ANSI_BBLACK, sizeof(ANSI_BBLACK)-1, T(COLOR_BG_555555), 3, T("%xX"), 3}, // These eight are never used.
|
|
{ CS_BG( 9), CS_BACKGROUND, ANSI_BRED, sizeof(ANSI_BRED)-1, T(COLOR_BG_FF5555), 3, T("%xR"), 3}, // .
|
|
{ CS_BG( 10), CS_BACKGROUND, ANSI_BGREEN, sizeof(ANSI_BGREEN)-1, T(COLOR_BG_55FF55), 3, T("%xG"), 3}, // .
|
|
{ CS_BG( 11), CS_BACKGROUND, ANSI_BYELLOW, sizeof(ANSI_BYELLOW)-1, T(COLOR_BG_FFFF55), 3, T("%xY"), 3}, // .
|
|
{ CS_BG( 12), CS_BACKGROUND, ANSI_BBLUE, sizeof(ANSI_BBLUE)-1, T(COLOR_BG_5555FF), 3, T("%xB"), 3}, // .
|
|
{ CS_BG( 13), CS_BACKGROUND, ANSI_BMAGENTA, sizeof(ANSI_BMAGENTA)-1, T(COLOR_BG_FF55FF), 3, T("%xM"), 3}, // .
|
|
{ CS_BG( 14), CS_BACKGROUND, ANSI_BCYAN, sizeof(ANSI_BCYAN)-1, T(COLOR_BG_55FFFF), 3, T("%xC"), 3}, // .
|
|
{ CS_BG( 15), CS_BACKGROUND, ANSI_BWHITE, sizeof(ANSI_BWHITE)-1, T(COLOR_BG_FFFFFF_1),3, T("%xW"), 3}, // -
|
|
{ CS_BG( 16), CS_BACKGROUND, XTERM_BG( 16), sizeof(XTERM_BG( 16))-1, T(COLOR_BG_000000), 3, T("%X<#000000>"), 11},
|
|
{ CS_BG( 17), CS_BACKGROUND, XTERM_BG( 17), sizeof(XTERM_BG( 17))-1, T(COLOR_BG_00005F), 3, T("%X<#00005F>"), 11},
|
|
{ CS_BG( 18), CS_BACKGROUND, XTERM_BG( 18), sizeof(XTERM_BG( 18))-1, T(COLOR_BG_000087), 3, T("%X<#000087>"), 11},
|
|
{ CS_BG( 19), CS_BACKGROUND, XTERM_BG( 19), sizeof(XTERM_BG( 19))-1, T(COLOR_BG_0000AF), 3, T("%X<#0000AF>"), 11},
|
|
{ CS_BG( 20), CS_BACKGROUND, XTERM_BG( 20), sizeof(XTERM_BG( 20))-1, T(COLOR_BG_0000D7), 3, T("%X<#0000D7>"), 11},
|
|
{ CS_BG( 21), CS_BACKGROUND, XTERM_BG( 21), sizeof(XTERM_BG( 21))-1, T(COLOR_BG_0000FF), 3, T("%X<#0000FF>"), 11},
|
|
{ CS_BG( 22), CS_BACKGROUND, XTERM_BG( 22), sizeof(XTERM_BG( 22))-1, T(COLOR_BG_005F00), 3, T("%X<#005F00>"), 11},
|
|
{ CS_BG( 23), CS_BACKGROUND, XTERM_BG( 23), sizeof(XTERM_BG( 23))-1, T(COLOR_BG_005F5F), 3, T("%X<#005F5F>"), 11},
|
|
{ CS_BG( 24), CS_BACKGROUND, XTERM_BG( 24), sizeof(XTERM_BG( 24))-1, T(COLOR_BG_005F87), 3, T("%X<#005F87>"), 11},
|
|
{ CS_BG( 25), CS_BACKGROUND, XTERM_BG( 25), sizeof(XTERM_BG( 25))-1, T(COLOR_BG_005FAF), 3, T("%X<#005FAF>"), 11},
|
|
{ CS_BG( 26), CS_BACKGROUND, XTERM_BG( 26), sizeof(XTERM_BG( 26))-1, T(COLOR_BG_005FD7), 3, T("%X<#005FD7>"), 11},
|
|
{ CS_BG( 27), CS_BACKGROUND, XTERM_BG( 27), sizeof(XTERM_BG( 27))-1, T(COLOR_BG_005FFF), 3, T("%X<#005FFF>"), 11},
|
|
{ CS_BG( 28), CS_BACKGROUND, XTERM_BG( 28), sizeof(XTERM_BG( 28))-1, T(COLOR_BG_008700), 3, T("%X<#008700>"), 11},
|
|
{ CS_BG( 29), CS_BACKGROUND, XTERM_BG( 29), sizeof(XTERM_BG( 29))-1, T(COLOR_BG_00875F), 3, T("%X<#00875F>"), 11},
|
|
{ CS_BG( 30), CS_BACKGROUND, XTERM_BG( 30), sizeof(XTERM_BG( 30))-1, T(COLOR_BG_008785), 3, T("%X<#008785>"), 11},
|
|
{ CS_BG( 31), CS_BACKGROUND, XTERM_BG( 31), sizeof(XTERM_BG( 31))-1, T(COLOR_BG_0087AF), 3, T("%X<#0087AF>"), 11},
|
|
{ CS_BG( 32), CS_BACKGROUND, XTERM_BG( 32), sizeof(XTERM_BG( 32))-1, T(COLOR_BG_0087D7), 3, T("%X<#0087D7>"), 11},
|
|
{ CS_BG( 33), CS_BACKGROUND, XTERM_BG( 33), sizeof(XTERM_BG( 33))-1, T(COLOR_BG_0087FF), 3, T("%X<#0087FF>"), 11},
|
|
{ CS_BG( 34), CS_BACKGROUND, XTERM_BG( 34), sizeof(XTERM_BG( 34))-1, T(COLOR_BG_00AF00), 3, T("%X<#00AF00>"), 11},
|
|
{ CS_BG( 35), CS_BACKGROUND, XTERM_BG( 35), sizeof(XTERM_BG( 35))-1, T(COLOR_BG_00AF5F), 3, T("%X<#00AF5F>"), 11},
|
|
{ CS_BG( 36), CS_BACKGROUND, XTERM_BG( 36), sizeof(XTERM_BG( 36))-1, T(COLOR_BG_00AF87), 3, T("%X<#00AF87>"), 11},
|
|
{ CS_BG( 37), CS_BACKGROUND, XTERM_BG( 37), sizeof(XTERM_BG( 37))-1, T(COLOR_BG_00AFAF), 3, T("%X<#00AFAF>"), 11},
|
|
{ CS_BG( 38), CS_BACKGROUND, XTERM_BG( 38), sizeof(XTERM_BG( 38))-1, T(COLOR_BG_00AFD7), 3, T("%X<#00AFD7>"), 11},
|
|
{ CS_BG( 39), CS_BACKGROUND, XTERM_BG( 39), sizeof(XTERM_BG( 39))-1, T(COLOR_BG_00AFFF), 3, T("%X<#00AFFF>"), 11},
|
|
{ CS_BG( 40), CS_BACKGROUND, XTERM_BG( 40), sizeof(XTERM_BG( 40))-1, T(COLOR_BG_00D700), 3, T("%X<#00D700>"), 11},
|
|
{ CS_BG( 41), CS_BACKGROUND, XTERM_BG( 41), sizeof(XTERM_BG( 41))-1, T(COLOR_BG_00D75F), 3, T("%X<#00D75F>"), 11},
|
|
{ CS_BG( 42), CS_BACKGROUND, XTERM_BG( 42), sizeof(XTERM_BG( 42))-1, T(COLOR_BG_00D787), 3, T("%X<#00D787>"), 11},
|
|
{ CS_BG( 43), CS_BACKGROUND, XTERM_BG( 43), sizeof(XTERM_BG( 43))-1, T(COLOR_BG_00D7AF), 3, T("%X<#00D7AF>"), 11},
|
|
{ CS_BG( 44), CS_BACKGROUND, XTERM_BG( 44), sizeof(XTERM_BG( 44))-1, T(COLOR_BG_00D7D7), 3, T("%X<#00D7D7>"), 11},
|
|
{ CS_BG( 45), CS_BACKGROUND, XTERM_BG( 45), sizeof(XTERM_BG( 45))-1, T(COLOR_BG_00D7FF), 3, T("%X<#00D7FF>"), 11},
|
|
{ CS_BG( 46), CS_BACKGROUND, XTERM_BG( 46), sizeof(XTERM_BG( 46))-1, T(COLOR_BG_00FF00), 3, T("%X<#00FF00>"), 11},
|
|
{ CS_BG( 47), CS_BACKGROUND, XTERM_BG( 47), sizeof(XTERM_BG( 47))-1, T(COLOR_BG_00FF5A), 3, T("%X<#00FF5A>"), 11},
|
|
{ CS_BG( 48), CS_BACKGROUND, XTERM_BG( 48), sizeof(XTERM_BG( 48))-1, T(COLOR_BG_00FF87), 3, T("%X<#00FF87>"), 11},
|
|
{ CS_BG( 49), CS_BACKGROUND, XTERM_BG( 49), sizeof(XTERM_BG( 49))-1, T(COLOR_BG_00FFAF), 3, T("%X<#00FFAF>"), 11},
|
|
{ CS_BG( 50), CS_BACKGROUND, XTERM_BG( 50), sizeof(XTERM_BG( 50))-1, T(COLOR_BG_00FFD7), 3, T("%X<#00FFD7>"), 11},
|
|
{ CS_BG( 51), CS_BACKGROUND, XTERM_BG( 51), sizeof(XTERM_BG( 51))-1, T(COLOR_BG_00FFFF), 3, T("%X<#00FFFF>"), 11},
|
|
{ CS_BG( 52), CS_BACKGROUND, XTERM_BG( 52), sizeof(XTERM_BG( 52))-1, T(COLOR_BG_5F0000), 3, T("%X<#5F0000>"), 11},
|
|
{ CS_BG( 53), CS_BACKGROUND, XTERM_BG( 53), sizeof(XTERM_BG( 53))-1, T(COLOR_BG_5F005F), 3, T("%X<#5F005F>"), 11},
|
|
{ CS_BG( 54), CS_BACKGROUND, XTERM_BG( 54), sizeof(XTERM_BG( 54))-1, T(COLOR_BG_5F0087), 3, T("%X<#5F0087>"), 11},
|
|
{ CS_BG( 55), CS_BACKGROUND, XTERM_BG( 55), sizeof(XTERM_BG( 55))-1, T(COLOR_BG_5F00AF), 3, T("%X<#5F00AF>"), 11},
|
|
{ CS_BG( 56), CS_BACKGROUND, XTERM_BG( 56), sizeof(XTERM_BG( 56))-1, T(COLOR_BG_5F00D7), 3, T("%X<#5F00D7>"), 11},
|
|
{ CS_BG( 57), CS_BACKGROUND, XTERM_BG( 57), sizeof(XTERM_BG( 57))-1, T(COLOR_BG_5F00FF), 3, T("%X<#5F00FF>"), 11},
|
|
{ CS_BG( 58), CS_BACKGROUND, XTERM_BG( 58), sizeof(XTERM_BG( 58))-1, T(COLOR_BG_5F5F00), 3, T("%X<#5F5F00>"), 11},
|
|
{ CS_BG( 59), CS_BACKGROUND, XTERM_BG( 59), sizeof(XTERM_BG( 59))-1, T(COLOR_BG_5F5F5F), 3, T("%X<#5F5F5F>"), 11},
|
|
{ CS_BG( 60), CS_BACKGROUND, XTERM_BG( 60), sizeof(XTERM_BG( 60))-1, T(COLOR_BG_5F5F87), 3, T("%X<#5F5F87>"), 11},
|
|
{ CS_BG( 61), CS_BACKGROUND, XTERM_BG( 61), sizeof(XTERM_BG( 61))-1, T(COLOR_BG_5F5FAF), 3, T("%X<#5F5FAF>"), 11},
|
|
{ CS_BG( 62), CS_BACKGROUND, XTERM_BG( 62), sizeof(XTERM_BG( 62))-1, T(COLOR_BG_5F5FD7), 3, T("%X<#5F5FD7>"), 11},
|
|
{ CS_BG( 63), CS_BACKGROUND, XTERM_BG( 63), sizeof(XTERM_BG( 63))-1, T(COLOR_BG_5F5FFF), 3, T("%X<#5F5FFF>"), 11},
|
|
{ CS_BG( 64), CS_BACKGROUND, XTERM_BG( 64), sizeof(XTERM_BG( 64))-1, T(COLOR_BG_5F8700), 3, T("%X<#5F8700>"), 11},
|
|
{ CS_BG( 65), CS_BACKGROUND, XTERM_BG( 65), sizeof(XTERM_BG( 65))-1, T(COLOR_BG_5F875F), 3, T("%X<#5F875F>"), 11},
|
|
{ CS_BG( 66), CS_BACKGROUND, XTERM_BG( 66), sizeof(XTERM_BG( 66))-1, T(COLOR_BG_5F8787), 3, T("%X<#5F8787>"), 11},
|
|
{ CS_BG( 67), CS_BACKGROUND, XTERM_BG( 67), sizeof(XTERM_BG( 67))-1, T(COLOR_BG_5F87AF), 3, T("%X<#5F87AF>"), 11},
|
|
{ CS_BG( 68), CS_BACKGROUND, XTERM_BG( 68), sizeof(XTERM_BG( 68))-1, T(COLOR_BG_5F87D7), 3, T("%X<#5F87D7>"), 11},
|
|
{ CS_BG( 69), CS_BACKGROUND, XTERM_BG( 69), sizeof(XTERM_BG( 69))-1, T(COLOR_BG_5F87FF), 3, T("%X<#5F87FF>"), 11},
|
|
{ CS_BG( 70), CS_BACKGROUND, XTERM_BG( 70), sizeof(XTERM_BG( 70))-1, T(COLOR_BG_5FAF00), 3, T("%X<#5FAF00>"), 11},
|
|
{ CS_BG( 71), CS_BACKGROUND, XTERM_BG( 71), sizeof(XTERM_BG( 71))-1, T(COLOR_BG_5FAF5F), 3, T("%X<#5FAF5F>"), 11},
|
|
{ CS_BG( 72), CS_BACKGROUND, XTERM_BG( 72), sizeof(XTERM_BG( 72))-1, T(COLOR_BG_5FAF87), 3, T("%X<#5FAF87>"), 11},
|
|
{ CS_BG( 73), CS_BACKGROUND, XTERM_BG( 73), sizeof(XTERM_BG( 73))-1, T(COLOR_BG_5FAFAF), 3, T("%X<#5FAFAF>"), 11},
|
|
{ CS_BG( 74), CS_BACKGROUND, XTERM_BG( 74), sizeof(XTERM_BG( 74))-1, T(COLOR_BG_5FAFD7), 3, T("%X<#5FAFD7>"), 11},
|
|
{ CS_BG( 75), CS_BACKGROUND, XTERM_BG( 75), sizeof(XTERM_BG( 75))-1, T(COLOR_BG_5FAFFF), 3, T("%X<#5FAFFF>"), 11},
|
|
{ CS_BG( 76), CS_BACKGROUND, XTERM_BG( 76), sizeof(XTERM_BG( 76))-1, T(COLOR_BG_5FD700), 3, T("%X<#5FD700>"), 11},
|
|
{ CS_BG( 77), CS_BACKGROUND, XTERM_BG( 77), sizeof(XTERM_BG( 77))-1, T(COLOR_BG_5FD75F), 3, T("%X<#5FD75F>"), 11},
|
|
{ CS_BG( 78), CS_BACKGROUND, XTERM_BG( 78), sizeof(XTERM_BG( 78))-1, T(COLOR_BG_5FD787), 3, T("%X<#5FD787>"), 11},
|
|
{ CS_BG( 79), CS_BACKGROUND, XTERM_BG( 79), sizeof(XTERM_BG( 79))-1, T(COLOR_BG_5FD7AF), 3, T("%X<#5FD7AF>"), 11},
|
|
{ CS_BG( 80), CS_BACKGROUND, XTERM_BG( 80), sizeof(XTERM_BG( 80))-1, T(COLOR_BG_5FD7D7), 3, T("%X<#5FD7D7>"), 11},
|
|
{ CS_BG( 81), CS_BACKGROUND, XTERM_BG( 81), sizeof(XTERM_BG( 81))-1, T(COLOR_BG_5FD7FF), 3, T("%X<#5FD7FF>"), 11},
|
|
{ CS_BG( 82), CS_BACKGROUND, XTERM_BG( 82), sizeof(XTERM_BG( 82))-1, T(COLOR_BG_5FFF00), 3, T("%X<#5FFF00>"), 11},
|
|
{ CS_BG( 83), CS_BACKGROUND, XTERM_BG( 83), sizeof(XTERM_BG( 83))-1, T(COLOR_BG_5FFF5F), 3, T("%X<#5FFF5F>"), 11},
|
|
{ CS_BG( 84), CS_BACKGROUND, XTERM_BG( 84), sizeof(XTERM_BG( 84))-1, T(COLOR_BG_5FFF87), 3, T("%X<#5FFF87>"), 11},
|
|
{ CS_BG( 85), CS_BACKGROUND, XTERM_BG( 85), sizeof(XTERM_BG( 85))-1, T(COLOR_BG_5FFFAF), 3, T("%X<#5FFFAF>"), 11},
|
|
{ CS_BG( 86), CS_BACKGROUND, XTERM_BG( 86), sizeof(XTERM_BG( 86))-1, T(COLOR_BG_5FFFD7), 3, T("%X<#5FFFD7>"), 11},
|
|
{ CS_BG( 87), CS_BACKGROUND, XTERM_BG( 87), sizeof(XTERM_BG( 87))-1, T(COLOR_BG_5FFFFF), 3, T("%X<#5FFFFF>"), 11},
|
|
{ CS_BG( 88), CS_BACKGROUND, XTERM_BG( 88), sizeof(XTERM_BG( 88))-1, T(COLOR_BG_870000), 3, T("%X<#870000>"), 11},
|
|
{ CS_BG( 89), CS_BACKGROUND, XTERM_BG( 89), sizeof(XTERM_BG( 89))-1, T(COLOR_BG_87005F), 3, T("%X<#87005F>"), 11},
|
|
{ CS_BG( 90), CS_BACKGROUND, XTERM_BG( 90), sizeof(XTERM_BG( 90))-1, T(COLOR_BG_870087), 3, T("%X<#870087>"), 11},
|
|
{ CS_BG( 91), CS_BACKGROUND, XTERM_BG( 91), sizeof(XTERM_BG( 91))-1, T(COLOR_BG_8700AF), 3, T("%X<#8700AF>"), 11},
|
|
{ CS_BG( 92), CS_BACKGROUND, XTERM_BG( 92), sizeof(XTERM_BG( 92))-1, T(COLOR_BG_8700D7), 3, T("%X<#8700D7>"), 11},
|
|
{ CS_BG( 93), CS_BACKGROUND, XTERM_BG( 93), sizeof(XTERM_BG( 93))-1, T(COLOR_BG_8700FF), 3, T("%X<#8700FF>"), 11},
|
|
{ CS_BG( 94), CS_BACKGROUND, XTERM_BG( 94), sizeof(XTERM_BG( 94))-1, T(COLOR_BG_875F00), 3, T("%X<#875F00>"), 11},
|
|
{ CS_BG( 95), CS_BACKGROUND, XTERM_BG( 95), sizeof(XTERM_BG( 95))-1, T(COLOR_BG_875F5F), 3, T("%X<#875F5F>"), 11},
|
|
{ CS_BG( 96), CS_BACKGROUND, XTERM_BG( 96), sizeof(XTERM_BG( 96))-1, T(COLOR_BG_875F87), 3, T("%X<#875F87>"), 11},
|
|
{ CS_BG( 97), CS_BACKGROUND, XTERM_BG( 97), sizeof(XTERM_BG( 97))-1, T(COLOR_BG_875FAF), 3, T("%X<#875FAF>"), 11},
|
|
{ CS_BG( 98), CS_BACKGROUND, XTERM_BG( 98), sizeof(XTERM_BG( 98))-1, T(COLOR_BG_875FD7), 3, T("%X<#875FD7>"), 11},
|
|
{ CS_BG( 99), CS_BACKGROUND, XTERM_BG( 99), sizeof(XTERM_BG( 99))-1, T(COLOR_BG_875FFF), 3, T("%X<#875FFF>"), 11},
|
|
{ CS_BG(100), CS_BACKGROUND, XTERM_BG(100), sizeof(XTERM_BG(100))-1, T(COLOR_BG_878700), 3, T("%X<#878700>"), 11},
|
|
{ CS_BG(101), CS_BACKGROUND, XTERM_BG(101), sizeof(XTERM_BG(101))-1, T(COLOR_BG_87875F), 3, T("%X<#87875F>"), 11},
|
|
{ CS_BG(102), CS_BACKGROUND, XTERM_BG(102), sizeof(XTERM_BG(102))-1, T(COLOR_BG_878787), 3, T("%X<#878787>"), 11},
|
|
{ CS_BG(103), CS_BACKGROUND, XTERM_BG(103), sizeof(XTERM_BG(103))-1, T(COLOR_BG_8787AF), 3, T("%X<#8787AF>"), 11},
|
|
{ CS_BG(104), CS_BACKGROUND, XTERM_BG(104), sizeof(XTERM_BG(104))-1, T(COLOR_BG_8787D7), 3, T("%X<#8787D7>"), 11},
|
|
{ CS_BG(105), CS_BACKGROUND, XTERM_BG(105), sizeof(XTERM_BG(105))-1, T(COLOR_BG_8787FF), 3, T("%X<#8787FF>"), 11},
|
|
{ CS_BG(106), CS_BACKGROUND, XTERM_BG(106), sizeof(XTERM_BG(106))-1, T(COLOR_BG_87AF00), 3, T("%X<#87AF00>"), 11},
|
|
{ CS_BG(107), CS_BACKGROUND, XTERM_BG(107), sizeof(XTERM_BG(107))-1, T(COLOR_BG_87AF5F), 3, T("%X<#87AF5F>"), 11},
|
|
{ CS_BG(108), CS_BACKGROUND, XTERM_BG(108), sizeof(XTERM_BG(108))-1, T(COLOR_BG_87AF87), 3, T("%X<#87AF87>"), 11},
|
|
{ CS_BG(109), CS_BACKGROUND, XTERM_BG(109), sizeof(XTERM_BG(109))-1, T(COLOR_BG_87AFAF), 3, T("%X<#87AFAF>"), 11},
|
|
{ CS_BG(110), CS_BACKGROUND, XTERM_BG(110), sizeof(XTERM_BG(110))-1, T(COLOR_BG_87AFD7), 3, T("%X<#87AFD7>"), 11},
|
|
{ CS_BG(111), CS_BACKGROUND, XTERM_BG(111), sizeof(XTERM_BG(111))-1, T(COLOR_BG_87AFFF), 3, T("%X<#87AFFF>"), 11},
|
|
{ CS_BG(112), CS_BACKGROUND, XTERM_BG(112), sizeof(XTERM_BG(112))-1, T(COLOR_BG_87D700), 3, T("%X<#87D700>"), 11},
|
|
{ CS_BG(113), CS_BACKGROUND, XTERM_BG(113), sizeof(XTERM_BG(113))-1, T(COLOR_BG_87D75A), 3, T("%X<#87D75A>"), 11},
|
|
{ CS_BG(114), CS_BACKGROUND, XTERM_BG(114), sizeof(XTERM_BG(114))-1, T(COLOR_BG_87D787), 3, T("%X<#87D787>"), 11},
|
|
{ CS_BG(115), CS_BACKGROUND, XTERM_BG(115), sizeof(XTERM_BG(115))-1, T(COLOR_BG_87D7AF), 3, T("%X<#87D7AF>"), 11},
|
|
{ CS_BG(116), CS_BACKGROUND, XTERM_BG(116), sizeof(XTERM_BG(116))-1, T(COLOR_BG_87D7D7), 3, T("%X<#87D7D7>"), 11},
|
|
{ CS_BG(117), CS_BACKGROUND, XTERM_BG(117), sizeof(XTERM_BG(117))-1, T(COLOR_BG_87D7FF), 3, T("%X<#87D7FF>"), 11},
|
|
{ CS_BG(118), CS_BACKGROUND, XTERM_BG(118), sizeof(XTERM_BG(118))-1, T(COLOR_BG_87FF00), 3, T("%X<#87FF00>"), 11},
|
|
{ CS_BG(119), CS_BACKGROUND, XTERM_BG(119), sizeof(XTERM_BG(119))-1, T(COLOR_BG_87FF5F), 3, T("%X<#87FF5F>"), 11},
|
|
{ CS_BG(120), CS_BACKGROUND, XTERM_BG(120), sizeof(XTERM_BG(120))-1, T(COLOR_BG_87FF87), 3, T("%X<#87FF87>"), 11},
|
|
{ CS_BG(121), CS_BACKGROUND, XTERM_BG(121), sizeof(XTERM_BG(121))-1, T(COLOR_BG_87FFAF), 3, T("%X<#87FFAF>"), 11},
|
|
{ CS_BG(122), CS_BACKGROUND, XTERM_BG(122), sizeof(XTERM_BG(122))-1, T(COLOR_BG_87FFD7), 3, T("%X<#87FFD7>"), 11},
|
|
{ CS_BG(123), CS_BACKGROUND, XTERM_BG(123), sizeof(XTERM_BG(123))-1, T(COLOR_BG_87FFFF), 3, T("%X<#87FFFF>"), 11},
|
|
{ CS_BG(124), CS_BACKGROUND, XTERM_BG(124), sizeof(XTERM_BG(124))-1, T(COLOR_BG_AF0000), 3, T("%X<#AF0000>"), 11},
|
|
{ CS_BG(125), CS_BACKGROUND, XTERM_BG(125), sizeof(XTERM_BG(125))-1, T(COLOR_BG_AF005F), 3, T("%X<#AF005F>"), 11},
|
|
{ CS_BG(126), CS_BACKGROUND, XTERM_BG(126), sizeof(XTERM_BG(126))-1, T(COLOR_BG_AF0087), 3, T("%X<#AF0087>"), 11},
|
|
{ CS_BG(127), CS_BACKGROUND, XTERM_BG(127), sizeof(XTERM_BG(127))-1, T(COLOR_BG_AF00AF), 3, T("%X<#AF00AF>"), 11},
|
|
{ CS_BG(128), CS_BACKGROUND, XTERM_BG(128), sizeof(XTERM_BG(128))-1, T(COLOR_BG_AF00D7), 3, T("%X<#AF00D7>"), 11},
|
|
{ CS_BG(129), CS_BACKGROUND, XTERM_BG(129), sizeof(XTERM_BG(129))-1, T(COLOR_BG_AF00FF), 3, T("%X<#AF00FF>"), 11},
|
|
{ CS_BG(130), CS_BACKGROUND, XTERM_BG(130), sizeof(XTERM_BG(130))-1, T(COLOR_BG_AF5F00), 3, T("%X<#AF5F00>"), 11},
|
|
{ CS_BG(131), CS_BACKGROUND, XTERM_BG(131), sizeof(XTERM_BG(131))-1, T(COLOR_BG_AF5F5F), 3, T("%X<#AF5F5F>"), 11},
|
|
{ CS_BG(132), CS_BACKGROUND, XTERM_BG(132), sizeof(XTERM_BG(132))-1, T(COLOR_BG_AF5F87), 3, T("%X<#AF5F87>"), 11},
|
|
{ CS_BG(133), CS_BACKGROUND, XTERM_BG(133), sizeof(XTERM_BG(133))-1, T(COLOR_BG_AF5FAF), 3, T("%X<#AF5FAF>"), 11},
|
|
{ CS_BG(134), CS_BACKGROUND, XTERM_BG(134), sizeof(XTERM_BG(134))-1, T(COLOR_BG_AF5FD7), 3, T("%X<#AF5FD7>"), 11},
|
|
{ CS_BG(135), CS_BACKGROUND, XTERM_BG(135), sizeof(XTERM_BG(135))-1, T(COLOR_BG_AF5FFF), 3, T("%X<#AF5FFF>"), 11},
|
|
{ CS_BG(136), CS_BACKGROUND, XTERM_BG(136), sizeof(XTERM_BG(136))-1, T(COLOR_BG_AF8700), 3, T("%X<#AF8700>"), 11},
|
|
{ CS_BG(137), CS_BACKGROUND, XTERM_BG(137), sizeof(XTERM_BG(137))-1, T(COLOR_BG_AF875F), 3, T("%X<#AF875F>"), 11},
|
|
{ CS_BG(138), CS_BACKGROUND, XTERM_BG(138), sizeof(XTERM_BG(138))-1, T(COLOR_BG_AF8787), 3, T("%X<#AF8787>"), 11},
|
|
{ CS_BG(139), CS_BACKGROUND, XTERM_BG(139), sizeof(XTERM_BG(139))-1, T(COLOR_BG_AF87AF), 3, T("%X<#AF87AF>"), 11},
|
|
{ CS_BG(140), CS_BACKGROUND, XTERM_BG(140), sizeof(XTERM_BG(140))-1, T(COLOR_BG_AF87D7), 3, T("%X<#AF87D7>"), 11},
|
|
{ CS_BG(141), CS_BACKGROUND, XTERM_BG(141), sizeof(XTERM_BG(141))-1, T(COLOR_BG_AF87FF), 3, T("%X<#AF87FF>"), 11},
|
|
{ CS_BG(142), CS_BACKGROUND, XTERM_BG(142), sizeof(XTERM_BG(142))-1, T(COLOR_BG_AFAF00), 3, T("%X<#AFAF00>"), 11},
|
|
{ CS_BG(143), CS_BACKGROUND, XTERM_BG(143), sizeof(XTERM_BG(143))-1, T(COLOR_BG_AFAF5F), 3, T("%X<#AFAF5F>"), 11},
|
|
{ CS_BG(144), CS_BACKGROUND, XTERM_BG(144), sizeof(XTERM_BG(144))-1, T(COLOR_BG_AFAF87), 3, T("%X<#AFAF87>"), 11},
|
|
{ CS_BG(145), CS_BACKGROUND, XTERM_BG(145), sizeof(XTERM_BG(145))-1, T(COLOR_BG_AFAFAF), 3, T("%X<#AFAFAF>"), 11},
|
|
{ CS_BG(146), CS_BACKGROUND, XTERM_BG(146), sizeof(XTERM_BG(146))-1, T(COLOR_BG_AFAFD7), 3, T("%X<#AFAFD7>"), 11},
|
|
{ CS_BG(147), CS_BACKGROUND, XTERM_BG(147), sizeof(XTERM_BG(147))-1, T(COLOR_BG_AFAFFF), 3, T("%X<#AFAFFF>"), 11},
|
|
{ CS_BG(148), CS_BACKGROUND, XTERM_BG(148), sizeof(XTERM_BG(148))-1, T(COLOR_BG_AFD700), 3, T("%X<#AFD700>"), 11},
|
|
{ CS_BG(149), CS_BACKGROUND, XTERM_BG(149), sizeof(XTERM_BG(149))-1, T(COLOR_BG_AFD75F), 3, T("%X<#AFD75F>"), 11},
|
|
{ CS_BG(150), CS_BACKGROUND, XTERM_BG(150), sizeof(XTERM_BG(150))-1, T(COLOR_BG_AFD787), 3, T("%X<#AFD787>"), 11},
|
|
{ CS_BG(151), CS_BACKGROUND, XTERM_BG(151), sizeof(XTERM_BG(151))-1, T(COLOR_BG_AFD7AF), 3, T("%X<#AFD7AF>"), 11},
|
|
{ CS_BG(152), CS_BACKGROUND, XTERM_BG(152), sizeof(XTERM_BG(152))-1, T(COLOR_BG_AFD7D7), 3, T("%X<#AFD7D7>"), 11},
|
|
{ CS_BG(153), CS_BACKGROUND, XTERM_BG(153), sizeof(XTERM_BG(153))-1, T(COLOR_BG_AFD7FF), 3, T("%X<#AFD7FF>"), 11},
|
|
{ CS_BG(154), CS_BACKGROUND, XTERM_BG(154), sizeof(XTERM_BG(154))-1, T(COLOR_BG_AFFF00), 3, T("%X<#AFFF00>"), 11},
|
|
{ CS_BG(155), CS_BACKGROUND, XTERM_BG(155), sizeof(XTERM_BG(155))-1, T(COLOR_BG_AFFF5F), 3, T("%X<#AFFF5F>"), 11},
|
|
{ CS_BG(156), CS_BACKGROUND, XTERM_BG(156), sizeof(XTERM_BG(156))-1, T(COLOR_BG_AFFF87), 3, T("%X<#AFFF87>"), 11},
|
|
{ CS_BG(157), CS_BACKGROUND, XTERM_BG(157), sizeof(XTERM_BG(157))-1, T(COLOR_BG_AFFFAF), 3, T("%X<#AFFFAF>"), 11},
|
|
{ CS_BG(158), CS_BACKGROUND, XTERM_BG(158), sizeof(XTERM_BG(158))-1, T(COLOR_BG_AFFFD7), 3, T("%X<#AFFFD7>"), 11},
|
|
{ CS_BG(159), CS_BACKGROUND, XTERM_BG(159), sizeof(XTERM_BG(159))-1, T(COLOR_BG_AFFFFF), 3, T("%X<#AFFFFF>"), 11},
|
|
{ CS_BG(160), CS_BACKGROUND, XTERM_BG(160), sizeof(XTERM_BG(160))-1, T(COLOR_BG_D70000), 3, T("%X<#D70000>"), 11},
|
|
{ CS_BG(161), CS_BACKGROUND, XTERM_BG(161), sizeof(XTERM_BG(161))-1, T(COLOR_BG_D7005F), 3, T("%X<#D7005F>"), 11},
|
|
{ CS_BG(162), CS_BACKGROUND, XTERM_BG(162), sizeof(XTERM_BG(162))-1, T(COLOR_BG_D70087), 3, T("%X<#D70087>"), 11},
|
|
{ CS_BG(163), CS_BACKGROUND, XTERM_BG(163), sizeof(XTERM_BG(163))-1, T(COLOR_BG_D700AF), 3, T("%X<#D700AF>"), 11},
|
|
{ CS_BG(164), CS_BACKGROUND, XTERM_BG(164), sizeof(XTERM_BG(164))-1, T(COLOR_BG_D700D7), 3, T("%X<#D700D7>"), 11},
|
|
{ CS_BG(165), CS_BACKGROUND, XTERM_BG(165), sizeof(XTERM_BG(165))-1, T(COLOR_BG_D700FF), 3, T("%X<#D700FF>"), 11},
|
|
{ CS_BG(166), CS_BACKGROUND, XTERM_BG(166), sizeof(XTERM_BG(166))-1, T(COLOR_BG_D75F00), 3, T("%X<#D75F00>"), 11},
|
|
{ CS_BG(167), CS_BACKGROUND, XTERM_BG(167), sizeof(XTERM_BG(167))-1, T(COLOR_BG_D75F5F), 3, T("%X<#D75F5F>"), 11},
|
|
{ CS_BG(168), CS_BACKGROUND, XTERM_BG(168), sizeof(XTERM_BG(168))-1, T(COLOR_BG_D75F87), 3, T("%X<#D75F87>"), 11},
|
|
{ CS_BG(169), CS_BACKGROUND, XTERM_BG(169), sizeof(XTERM_BG(169))-1, T(COLOR_BG_D75FAF), 3, T("%X<#D75FAF>"), 11},
|
|
{ CS_BG(170), CS_BACKGROUND, XTERM_BG(170), sizeof(XTERM_BG(170))-1, T(COLOR_BG_D75FD7), 3, T("%X<#D75FD7>"), 11},
|
|
{ CS_BG(171), CS_BACKGROUND, XTERM_BG(171), sizeof(XTERM_BG(171))-1, T(COLOR_BG_D75FFF), 3, T("%X<#D75FFF>"), 11},
|
|
{ CS_BG(172), CS_BACKGROUND, XTERM_BG(172), sizeof(XTERM_BG(172))-1, T(COLOR_BG_D78700), 3, T("%X<#D78700>"), 11},
|
|
{ CS_BG(173), CS_BACKGROUND, XTERM_BG(173), sizeof(XTERM_BG(173))-1, T(COLOR_BG_D7875A), 3, T("%X<#D7875A>"), 11},
|
|
{ CS_BG(174), CS_BACKGROUND, XTERM_BG(174), sizeof(XTERM_BG(174))-1, T(COLOR_BG_D78787), 3, T("%X<#D78787>"), 11},
|
|
{ CS_BG(175), CS_BACKGROUND, XTERM_BG(175), sizeof(XTERM_BG(175))-1, T(COLOR_BG_D787AF), 3, T("%X<#D787AF>"), 11},
|
|
{ CS_BG(176), CS_BACKGROUND, XTERM_BG(176), sizeof(XTERM_BG(176))-1, T(COLOR_BG_D787D7), 3, T("%X<#D787D7>"), 11},
|
|
{ CS_BG(177), CS_BACKGROUND, XTERM_BG(177), sizeof(XTERM_BG(177))-1, T(COLOR_BG_D787FF), 3, T("%X<#D787FF>"), 11},
|
|
{ CS_BG(178), CS_BACKGROUND, XTERM_BG(178), sizeof(XTERM_BG(178))-1, T(COLOR_BG_D7AF00), 3, T("%X<#D7AF00>"), 11},
|
|
{ CS_BG(179), CS_BACKGROUND, XTERM_BG(179), sizeof(XTERM_BG(179))-1, T(COLOR_BG_D7AF5A), 3, T("%X<#D7AF5A>"), 11},
|
|
{ CS_BG(180), CS_BACKGROUND, XTERM_BG(180), sizeof(XTERM_BG(180))-1, T(COLOR_BG_D7AF87), 3, T("%X<#D7AF87>"), 11},
|
|
{ CS_BG(181), CS_BACKGROUND, XTERM_BG(181), sizeof(XTERM_BG(181))-1, T(COLOR_BG_D7AFAF), 3, T("%X<#D7AFAF>"), 11},
|
|
{ CS_BG(182), CS_BACKGROUND, XTERM_BG(182), sizeof(XTERM_BG(182))-1, T(COLOR_BG_D7AFD7), 3, T("%X<#D7AFD7>"), 11},
|
|
{ CS_BG(183), CS_BACKGROUND, XTERM_BG(183), sizeof(XTERM_BG(183))-1, T(COLOR_BG_D7AFFF), 3, T("%X<#D7AFFF>"), 11},
|
|
{ CS_BG(184), CS_BACKGROUND, XTERM_BG(184), sizeof(XTERM_BG(184))-1, T(COLOR_BG_D7D700), 3, T("%X<#D7D700>"), 11},
|
|
{ CS_BG(185), CS_BACKGROUND, XTERM_BG(185), sizeof(XTERM_BG(185))-1, T(COLOR_BG_D7D75F), 3, T("%X<#D7D75F>"), 11},
|
|
{ CS_BG(186), CS_BACKGROUND, XTERM_BG(186), sizeof(XTERM_BG(186))-1, T(COLOR_BG_D7D787), 3, T("%X<#D7D787>"), 11},
|
|
{ CS_BG(187), CS_BACKGROUND, XTERM_BG(187), sizeof(XTERM_BG(187))-1, T(COLOR_BG_D7D7AF), 3, T("%X<#D7D7AF>"), 11},
|
|
{ CS_BG(188), CS_BACKGROUND, XTERM_BG(188), sizeof(XTERM_BG(188))-1, T(COLOR_BG_D7D7D7), 3, T("%X<#D7D7D7>"), 11},
|
|
{ CS_BG(189), CS_BACKGROUND, XTERM_BG(189), sizeof(XTERM_BG(189))-1, T(COLOR_BG_D7D7FF), 3, T("%X<#D7D7FF>"), 11},
|
|
{ CS_BG(190), CS_BACKGROUND, XTERM_BG(190), sizeof(XTERM_BG(190))-1, T(COLOR_BG_D7FF00), 3, T("%X<#D7FF00>"), 11},
|
|
{ CS_BG(191), CS_BACKGROUND, XTERM_BG(191), sizeof(XTERM_BG(191))-1, T(COLOR_BG_D7FF5F), 3, T("%X<#D7FF5F>"), 11},
|
|
{ CS_BG(192), CS_BACKGROUND, XTERM_BG(192), sizeof(XTERM_BG(192))-1, T(COLOR_BG_D7FF87), 3, T("%X<#D7FF87>"), 11},
|
|
{ CS_BG(193), CS_BACKGROUND, XTERM_BG(193), sizeof(XTERM_BG(193))-1, T(COLOR_BG_D7FFAF), 3, T("%X<#D7FFAF>"), 11},
|
|
{ CS_BG(194), CS_BACKGROUND, XTERM_BG(194), sizeof(XTERM_BG(194))-1, T(COLOR_BG_D7FFD7), 3, T("%X<#D7FFD7>"), 11},
|
|
{ CS_BG(195), CS_BACKGROUND, XTERM_BG(195), sizeof(XTERM_BG(195))-1, T(COLOR_BG_D7FFFF), 3, T("%X<#D7FFFF>"), 11},
|
|
{ CS_BG(196), CS_BACKGROUND, XTERM_BG(196), sizeof(XTERM_BG(196))-1, T(COLOR_BG_FF0000), 3, T("%X<#FF0000>"), 11},
|
|
{ CS_BG(197), CS_BACKGROUND, XTERM_BG(197), sizeof(XTERM_BG(197))-1, T(COLOR_BG_FF005F), 3, T("%X<#FF005F>"), 11},
|
|
{ CS_BG(198), CS_BACKGROUND, XTERM_BG(198), sizeof(XTERM_BG(198))-1, T(COLOR_BG_FF0087), 3, T("%X<#FF0087>"), 11},
|
|
{ CS_BG(199), CS_BACKGROUND, XTERM_BG(199), sizeof(XTERM_BG(199))-1, T(COLOR_BG_FF00AF), 3, T("%X<#FF00AF>"), 11},
|
|
{ CS_BG(200), CS_BACKGROUND, XTERM_BG(200), sizeof(XTERM_BG(200))-1, T(COLOR_BG_FF00D7), 3, T("%X<#FF00D7>"), 11},
|
|
{ CS_BG(201), CS_BACKGROUND, XTERM_BG(201), sizeof(XTERM_BG(201))-1, T(COLOR_BG_FF00FF), 3, T("%X<#FF00FF>"), 11},
|
|
{ CS_BG(202), CS_BACKGROUND, XTERM_BG(202), sizeof(XTERM_BG(202))-1, T(COLOR_BG_FF5F00), 3, T("%X<#FF5F00>"), 11},
|
|
{ CS_BG(203), CS_BACKGROUND, XTERM_BG(203), sizeof(XTERM_BG(203))-1, T(COLOR_BG_FF5F5F), 3, T("%X<#FF5F5F>"), 11},
|
|
{ CS_BG(204), CS_BACKGROUND, XTERM_BG(204), sizeof(XTERM_BG(204))-1, T(COLOR_BG_FF5F87), 3, T("%X<#FF5F87>"), 11},
|
|
{ CS_BG(205), CS_BACKGROUND, XTERM_BG(205), sizeof(XTERM_BG(205))-1, T(COLOR_BG_FF5FAF), 3, T("%X<#FF5FAF>"), 11},
|
|
{ CS_BG(206), CS_BACKGROUND, XTERM_BG(206), sizeof(XTERM_BG(206))-1, T(COLOR_BG_FF5FD7), 3, T("%X<#FF5FD7>"), 11},
|
|
{ CS_BG(207), CS_BACKGROUND, XTERM_BG(207), sizeof(XTERM_BG(207))-1, T(COLOR_BG_FF5FFF), 3, T("%X<#FF5FFF>"), 11},
|
|
{ CS_BG(208), CS_BACKGROUND, XTERM_BG(208), sizeof(XTERM_BG(208))-1, T(COLOR_BG_FF8700), 3, T("%X<#FF8700>"), 11},
|
|
{ CS_BG(209), CS_BACKGROUND, XTERM_BG(209), sizeof(XTERM_BG(209))-1, T(COLOR_BG_FF875F), 3, T("%X<#FF875F>"), 11},
|
|
{ CS_BG(210), CS_BACKGROUND, XTERM_BG(210), sizeof(XTERM_BG(210))-1, T(COLOR_BG_FF8787), 3, T("%X<#FF8787>"), 11},
|
|
{ CS_BG(211), CS_BACKGROUND, XTERM_BG(211), sizeof(XTERM_BG(211))-1, T(COLOR_BG_FF87AF), 3, T("%X<#FF87AF>"), 11},
|
|
{ CS_BG(212), CS_BACKGROUND, XTERM_BG(212), sizeof(XTERM_BG(212))-1, T(COLOR_BG_FF87D7), 3, T("%X<#FF87D7>"), 11},
|
|
{ CS_BG(213), CS_BACKGROUND, XTERM_BG(213), sizeof(XTERM_BG(213))-1, T(COLOR_BG_FF87FF), 3, T("%X<#FF87FF>"), 11},
|
|
{ CS_BG(214), CS_BACKGROUND, XTERM_BG(214), sizeof(XTERM_BG(214))-1, T(COLOR_BG_FFAF00), 3, T("%X<#FFAF00>"), 11},
|
|
{ CS_BG(215), CS_BACKGROUND, XTERM_BG(215), sizeof(XTERM_BG(215))-1, T(COLOR_BG_FFAF5F), 3, T("%X<#FFAF5F>"), 11},
|
|
{ CS_BG(216), CS_BACKGROUND, XTERM_BG(216), sizeof(XTERM_BG(216))-1, T(COLOR_BG_FFAF87), 3, T("%X<#FFAF87>"), 11},
|
|
{ CS_BG(217), CS_BACKGROUND, XTERM_BG(217), sizeof(XTERM_BG(217))-1, T(COLOR_BG_FFAFAF), 3, T("%X<#FFAFAF>"), 11},
|
|
{ CS_BG(218), CS_BACKGROUND, XTERM_BG(218), sizeof(XTERM_BG(218))-1, T(COLOR_BG_FFAFD7), 3, T("%X<#FFAFD7>"), 11},
|
|
{ CS_BG(219), CS_BACKGROUND, XTERM_BG(219), sizeof(XTERM_BG(219))-1, T(COLOR_BG_FFAFFF), 3, T("%X<#FFAFFF>"), 11},
|
|
{ CS_BG(220), CS_BACKGROUND, XTERM_BG(220), sizeof(XTERM_BG(220))-1, T(COLOR_BG_FFD700), 3, T("%X<#FFD700>"), 11},
|
|
{ CS_BG(221), CS_BACKGROUND, XTERM_BG(221), sizeof(XTERM_BG(221))-1, T(COLOR_BG_FFD75F), 3, T("%X<#FFD75F>"), 11},
|
|
{ CS_BG(222), CS_BACKGROUND, XTERM_BG(222), sizeof(XTERM_BG(222))-1, T(COLOR_BG_FFD787), 3, T("%X<#FFD787>"), 11},
|
|
{ CS_BG(223), CS_BACKGROUND, XTERM_BG(223), sizeof(XTERM_BG(223))-1, T(COLOR_BG_FFD7AF), 3, T("%X<#FFD7AF>"), 11},
|
|
{ CS_BG(224), CS_BACKGROUND, XTERM_BG(224), sizeof(XTERM_BG(224))-1, T(COLOR_BG_FFD7D7), 3, T("%X<#FFD7D7>"), 11},
|
|
{ CS_BG(225), CS_BACKGROUND, XTERM_BG(225), sizeof(XTERM_BG(225))-1, T(COLOR_BG_FFD7FF), 3, T("%X<#FFD7FF>"), 11},
|
|
{ CS_BG(226), CS_BACKGROUND, XTERM_BG(226), sizeof(XTERM_BG(226))-1, T(COLOR_BG_FFFF00), 3, T("%X<#FFFF00>"), 11},
|
|
{ CS_BG(227), CS_BACKGROUND, XTERM_BG(227), sizeof(XTERM_BG(227))-1, T(COLOR_BG_FFFF5F), 3, T("%X<#FFFF5F>"), 11},
|
|
{ CS_BG(228), CS_BACKGROUND, XTERM_BG(228), sizeof(XTERM_BG(228))-1, T(COLOR_BG_FFFF87), 3, T("%X<#FFFF87>"), 11},
|
|
{ CS_BG(229), CS_BACKGROUND, XTERM_BG(229), sizeof(XTERM_BG(229))-1, T(COLOR_BG_FFFFAF), 3, T("%X<#FFFFAF>"), 11},
|
|
{ CS_BG(230), CS_BACKGROUND, XTERM_BG(230), sizeof(XTERM_BG(230))-1, T(COLOR_BG_FFFFD7), 3, T("%X<#FFFFD7>"), 11},
|
|
{ CS_BG(231), CS_BACKGROUND, XTERM_BG(231), sizeof(XTERM_BG(231))-1, T(COLOR_BG_FFFFFF_2),3, T("%X<#FFFFFF>"), 11},
|
|
{ CS_BG(232), CS_BACKGROUND, XTERM_BG(232), sizeof(XTERM_BG(232))-1, T(COLOR_BG_080808), 3, T("%X<#080808>"), 11},
|
|
{ CS_BG(233), CS_BACKGROUND, XTERM_BG(233), sizeof(XTERM_BG(233))-1, T(COLOR_BG_121212), 3, T("%X<#121212>"), 11},
|
|
{ CS_BG(234), CS_BACKGROUND, XTERM_BG(234), sizeof(XTERM_BG(234))-1, T(COLOR_BG_1C1C1C), 3, T("%X<#1C1C1C>"), 11},
|
|
{ CS_BG(235), CS_BACKGROUND, XTERM_BG(235), sizeof(XTERM_BG(235))-1, T(COLOR_BG_262626), 3, T("%X<#262626>"), 11},
|
|
{ CS_BG(236), CS_BACKGROUND, XTERM_BG(236), sizeof(XTERM_BG(236))-1, T(COLOR_BG_303030), 3, T("%X<#303030>"), 11},
|
|
{ CS_BG(237), CS_BACKGROUND, XTERM_BG(237), sizeof(XTERM_BG(237))-1, T(COLOR_BG_3A3A3A), 3, T("%X<#3A3A3A>"), 11},
|
|
{ CS_BG(238), CS_BACKGROUND, XTERM_BG(238), sizeof(XTERM_BG(238))-1, T(COLOR_BG_444444), 3, T("%X<#444444>"), 11},
|
|
{ CS_BG(239), CS_BACKGROUND, XTERM_BG(239), sizeof(XTERM_BG(239))-1, T(COLOR_BG_4E4E4E), 3, T("%X<#4E4E4E>"), 11},
|
|
{ CS_BG(240), CS_BACKGROUND, XTERM_BG(240), sizeof(XTERM_BG(240))-1, T(COLOR_BG_585858), 3, T("%X<#585858>"), 11},
|
|
{ CS_BG(241), CS_BACKGROUND, XTERM_BG(241), sizeof(XTERM_BG(241))-1, T(COLOR_BG_626262), 3, T("%X<#626262>"), 11},
|
|
{ CS_BG(242), CS_BACKGROUND, XTERM_BG(242), sizeof(XTERM_BG(242))-1, T(COLOR_BG_6C6C6C), 3, T("%X<#6C6C6C>"), 11},
|
|
{ CS_BG(243), CS_BACKGROUND, XTERM_BG(243), sizeof(XTERM_BG(243))-1, T(COLOR_BG_767676), 3, T("%X<#767676>"), 11},
|
|
{ CS_BG(244), CS_BACKGROUND, XTERM_BG(244), sizeof(XTERM_BG(244))-1, T(COLOR_BG_808080), 3, T("%X<#808080>"), 11},
|
|
{ CS_BG(245), CS_BACKGROUND, XTERM_BG(245), sizeof(XTERM_BG(245))-1, T(COLOR_BG_8A8A8A), 3, T("%X<#8A8A8A>"), 11},
|
|
{ CS_BG(246), CS_BACKGROUND, XTERM_BG(246), sizeof(XTERM_BG(246))-1, T(COLOR_BG_949494), 3, T("%X<#949494>"), 11},
|
|
{ CS_BG(247), CS_BACKGROUND, XTERM_BG(247), sizeof(XTERM_BG(247))-1, T(COLOR_BG_9E9E9E), 3, T("%X<#9E9E9E>"), 11},
|
|
{ CS_BG(248), CS_BACKGROUND, XTERM_BG(248), sizeof(XTERM_BG(248))-1, T(COLOR_BG_A8A8A8), 3, T("%X<#A8A8A8>"), 11},
|
|
{ CS_BG(249), CS_BACKGROUND, XTERM_BG(249), sizeof(XTERM_BG(249))-1, T(COLOR_BG_B2B2B2), 3, T("%X<#B2B2B2>"), 11},
|
|
{ CS_BG(250), CS_BACKGROUND, XTERM_BG(250), sizeof(XTERM_BG(250))-1, T(COLOR_BG_BCBCBC), 3, T("%X<#BCBCBC>"), 11},
|
|
{ CS_BG(251), CS_BACKGROUND, XTERM_BG(251), sizeof(XTERM_BG(251))-1, T(COLOR_BG_C6C6C6), 3, T("%X<#C6C6C6>"), 11},
|
|
{ CS_BG(252), CS_BACKGROUND, XTERM_BG(252), sizeof(XTERM_BG(252))-1, T(COLOR_BG_D0D0D0), 3, T("%X<#D0D0D0>"), 11},
|
|
{ CS_BG(253), CS_BACKGROUND, XTERM_BG(253), sizeof(XTERM_BG(253))-1, T(COLOR_BG_DADADA), 3, T("%X<#DADADA>"), 11},
|
|
{ CS_BG(254), CS_BACKGROUND, XTERM_BG(254), sizeof(XTERM_BG(254))-1, T(COLOR_BG_E4E4E4), 3, T("%X<#E4E4E4>"), 11},
|
|
{ CS_BG(255), CS_BACKGROUND, XTERM_BG(255), sizeof(XTERM_BG(255))-1, T(COLOR_BG_EEEEEE), 3, T("%X<#EEEEEE>"), 11},
|
|
};
|
|
|
|
/*! \brief Validate ColorState.
|
|
*
|
|
* Checks (with assertions) that the given ColorState is valid. This is
|
|
* useful during development and debugging, but if any of the assertions are
|
|
* false, the process ends.
|
|
*
|
|
* \param cs ColorState.
|
|
* \return None.
|
|
*/
|
|
|
|
inline void ValidateColorState(ColorState cs)
|
|
{
|
|
const ColorState Mask = static_cast<ColorState>(~(CS_FOREGROUND|CS_BACKGROUND|CS_ATTRS));
|
|
mux_assert((Mask & cs) == 0);
|
|
mux_assert((CS_FOREGROUND & cs) <= CS_FG_DEFAULT);
|
|
mux_assert((CS_BACKGROUND & cs) <= CS_BG_DEFAULT);
|
|
}
|
|
|
|
inline ColorState UpdateColorState(ColorState cs, int iColorCode, const UTF8 *pRaw = nullptr)
|
|
{
|
|
mux_assert(0 <= iColorCode && iColorCode <= COLOR_INDEX_LAST);
|
|
if (COLOR_INDEX_FG_24_CP1 <= iColorCode)
|
|
{
|
|
// 24-bit color: 2-code-point encoding.
|
|
// CP1 carries R high nibble + G, CP2 carries R low nibble + B.
|
|
// pRaw points to the 4-byte UTF-8 sequence: F3 Bx xx xx.
|
|
//
|
|
mux_assert(pRaw != nullptr);
|
|
unsigned int payload = mux_color_smp_payload(pRaw);
|
|
unsigned int hi = payload >> 8; // 4-bit nibble (CP1) or nibble (CP2)
|
|
unsigned int lo = payload & 0xFF; // G (CP1) or B (CP2)
|
|
|
|
switch (iColorCode)
|
|
{
|
|
case COLOR_INDEX_FG_24_CP1:
|
|
if (CS_FG_INDEXED & cs)
|
|
{
|
|
cs = (cs & ~CS_FOREGROUND) | rgb2cs(&palette[CS_FG_FIELD_INDEXED(cs)].rgb);
|
|
}
|
|
cs = (cs & ~CS_FOREGROUND_RED) | (static_cast<ColorState>(hi << 4) << 16);
|
|
cs = (cs & ~CS_FOREGROUND_GREEN) | (static_cast<ColorState>(lo) << 8);
|
|
break;
|
|
|
|
case COLOR_INDEX_FG_24_CP2:
|
|
if (CS_FG_INDEXED & cs)
|
|
{
|
|
cs = (cs & ~CS_FOREGROUND) | rgb2cs(&palette[CS_FG_FIELD_INDEXED(cs)].rgb);
|
|
}
|
|
{
|
|
ColorState red = (cs >> 16) & 0xF0;
|
|
cs = (cs & ~CS_FOREGROUND_RED) | ((red | hi) << 16);
|
|
}
|
|
cs = (cs & ~CS_FOREGROUND_BLUE) | static_cast<ColorState>(lo);
|
|
break;
|
|
|
|
case COLOR_INDEX_BG_24_CP1:
|
|
if (CS_BG_INDEXED & cs)
|
|
{
|
|
cs = (cs & ~CS_BACKGROUND) | (rgb2cs(&palette[CS_BG_FIELD_INDEXED(cs)].rgb) << 32);
|
|
}
|
|
cs = (cs & ~CS_BACKGROUND_RED) | (static_cast<ColorState>(hi << 4) << 48);
|
|
cs = (cs & ~CS_BACKGROUND_GREEN) | (static_cast<ColorState>(lo) << 40);
|
|
break;
|
|
|
|
case COLOR_INDEX_BG_24_CP2:
|
|
if (CS_BG_INDEXED & cs)
|
|
{
|
|
cs = (cs & ~CS_BACKGROUND) | (rgb2cs(&palette[CS_BG_FIELD_INDEXED(cs)].rgb) << 32);
|
|
}
|
|
{
|
|
ColorState red = (cs >> 48) & 0xF0;
|
|
cs = (cs & ~CS_BACKGROUND_RED) | ((red | hi) << 48);
|
|
}
|
|
cs = (cs & ~CS_BACKGROUND_BLUE) | (static_cast<ColorState>(lo) << 32);
|
|
break;
|
|
}
|
|
mux_assert((cs & ~CS_ALLBITS) == 0);
|
|
return cs;
|
|
}
|
|
mux_assert(iColorCode < sizeof(aColors)/sizeof(aColors[0]));
|
|
return (cs & ~aColors[iColorCode].csMask) | aColors[iColorCode].cs;
|
|
}
|
|
|
|
// Maximum binary transition length is:
|
|
//
|
|
// COLOR_RESET "\xEF\x94\x80"
|
|
// + COLOR_INTENSE "\xEF\x94\x81"
|
|
// + COLOR_UNDERLINE "\xEF\x94\x84"
|
|
// + COLOR_BLINK "\xEF\x94\x85"
|
|
// + COLOR_INVERSE "\xEF\x94\x87"
|
|
// + COLOR_FG_RED "\xEF\x98\x81"
|
|
// + COLOR_BG_WHITE "\xEF\x9C\x87"
|
|
//
|
|
// Each of the seven codes is 3 bytes or 21 bytes total. Plus two 24-bit
|
|
// SMP code points per layer (4 bytes each), for FG and BG = 4 code points.
|
|
//
|
|
#define COLOR_MAXIMUM_BINARY_TRANSITION_LENGTH (21+4*4)
|
|
|
|
// Emit a 4-byte SMP PUA color code point.
|
|
// block: 0=FG CP1, 1=FG CP2, 2=BG CP1, 3=BG CP2
|
|
// payload: 12-bit value ((nibble << 8) | channel_byte)
|
|
//
|
|
static inline void EmitSMPColor(UTF8 *buf, unsigned int block, unsigned int payload)
|
|
{
|
|
buf[0] = 0xF3;
|
|
buf[1] = static_cast<UTF8>(0xB0 + block);
|
|
buf[2] = static_cast<UTF8>(0x80 | ((payload >> 6) & 0x3F));
|
|
buf[3] = static_cast<UTF8>(0x80 | (payload & 0x3F));
|
|
}
|
|
|
|
// Generate the minimal color sequence that will transition from one color state
|
|
// to another.
|
|
//
|
|
static UTF8 *ColorTransitionBinary
|
|
(
|
|
ColorState csCurrent,
|
|
ColorState csNext,
|
|
size_t *nTransition
|
|
)
|
|
{
|
|
ValidateColorState(csCurrent);
|
|
ValidateColorState(csNext);
|
|
|
|
static UTF8 Buffer[COLOR_MAXIMUM_BINARY_TRANSITION_LENGTH+1];
|
|
|
|
if (csCurrent == csNext)
|
|
{
|
|
*nTransition = 0;
|
|
Buffer[0] = '\0';
|
|
return Buffer;
|
|
}
|
|
size_t i = 0;
|
|
|
|
// Do we need to go through the normal state?
|
|
//
|
|
if ( ((csCurrent & ~csNext) & CS_ATTRS)
|
|
|| ( (csNext & CS_BACKGROUND) == CS_BG_DEFAULT
|
|
&& (csCurrent & CS_BACKGROUND) != CS_BG_DEFAULT)
|
|
|| ( (csNext & CS_FOREGROUND) == CS_FG_DEFAULT
|
|
&& (csCurrent & CS_FOREGROUND) != CS_FG_DEFAULT))
|
|
{
|
|
memcpy(Buffer + i, COLOR_RESET, sizeof(COLOR_RESET)-1);
|
|
i += sizeof(COLOR_RESET)-1;
|
|
csCurrent = CS_NORMAL;
|
|
}
|
|
|
|
ColorState tmp = csCurrent ^ csNext;
|
|
if (CS_ATTRS & tmp)
|
|
{
|
|
for (unsigned int iAttr = COLOR_INDEX_ATTR; iAttr < COLOR_INDEX_FG; iAttr++)
|
|
{
|
|
if (aColors[iAttr].cs == (aColors[iAttr].csMask & tmp))
|
|
{
|
|
memcpy(Buffer + i, aColors[iAttr].pUTF, aColors[iAttr].nUTF);
|
|
i += aColors[iAttr].nUTF;
|
|
}
|
|
}
|
|
}
|
|
|
|
RGB rgb;
|
|
unsigned int iColor;
|
|
if (CS_FOREGROUND & tmp)
|
|
{
|
|
bool fExact;
|
|
if (CS_FG_INDEXED & csNext)
|
|
{
|
|
iColor = static_cast<unsigned int>(CS_FG_FIELD(csNext));
|
|
fExact = true;
|
|
}
|
|
else
|
|
{
|
|
cs2rgb(CS_FG_FIELD(csNext), &rgb);
|
|
iColor = FindNearestPaletteEntry(rgb, true);
|
|
fExact = ( palette[iColor].rgb.r == rgb.r
|
|
&& palette[iColor].rgb.g == rgb.g
|
|
&& palette[iColor].rgb.b == rgb.b);
|
|
}
|
|
if (iColor < COLOR_INDEX_DEFAULT)
|
|
{
|
|
memcpy(Buffer + i, aColors[COLOR_INDEX_FG + iColor].pUTF, aColors[COLOR_INDEX_FG + iColor].nUTF);
|
|
i += aColors[COLOR_INDEX_FG + iColor].nUTF;
|
|
if (!fExact)
|
|
{
|
|
// 2-code-point FG encoding: CP1 (block 0) + CP2 (block 1)
|
|
//
|
|
EmitSMPColor(Buffer + i, 0, ((rgb.r >> 4) << 8) | rgb.g);
|
|
i += 4;
|
|
EmitSMPColor(Buffer + i, 1, ((rgb.r & 0xF) << 8) | rgb.b);
|
|
i += 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (CS_BACKGROUND & tmp)
|
|
{
|
|
bool fExact;
|
|
if (CS_BG_INDEXED & csNext)
|
|
{
|
|
iColor = static_cast<unsigned int>(CS_BG_FIELD(csNext));
|
|
fExact = true;
|
|
}
|
|
else
|
|
{
|
|
cs2rgb(CS_BG_FIELD(csNext), &rgb);
|
|
iColor = FindNearestPaletteEntry(rgb, true);
|
|
fExact = ( palette[iColor].rgb.r == rgb.r
|
|
&& palette[iColor].rgb.g == rgb.g
|
|
&& palette[iColor].rgb.b == rgb.b);
|
|
}
|
|
if (iColor < COLOR_INDEX_DEFAULT)
|
|
{
|
|
memcpy(Buffer + i, aColors[COLOR_INDEX_BG + iColor].pUTF, aColors[COLOR_INDEX_BG + iColor].nUTF);
|
|
i += aColors[COLOR_INDEX_BG + iColor].nUTF;
|
|
if (!fExact)
|
|
{
|
|
// 2-code-point BG encoding: CP1 (block 2) + CP2 (block 3)
|
|
//
|
|
EmitSMPColor(Buffer + i, 2, ((rgb.r >> 4) << 8) | rgb.g);
|
|
i += 4;
|
|
EmitSMPColor(Buffer + i, 3, ((rgb.r & 0xF) << 8) | rgb.b);
|
|
i += 4;
|
|
}
|
|
}
|
|
}
|
|
Buffer[i] = '\0';
|
|
*nTransition = i;
|
|
return Buffer;
|
|
}
|
|
|
|
// Maximum binary transition to normal is:
|
|
//
|
|
// COLOR_RESET "\xEF\x94\x80"
|
|
//
|
|
// The code is 3 bytes.
|
|
//
|
|
#define COLOR_MAXIMUM_BINARY_NORMAL 3
|
|
|
|
// Generate the minimal color sequence that will transition from one color state
|
|
// to the normal state.
|
|
//
|
|
static const UTF8 *ColorBinaryNormal
|
|
(
|
|
ColorState csCurrent,
|
|
size_t *nTransition
|
|
)
|
|
{
|
|
ValidateColorState(csCurrent);
|
|
|
|
if (csCurrent == CS_NORMAL)
|
|
{
|
|
*nTransition = 0;
|
|
return T("");
|
|
}
|
|
else
|
|
{
|
|
*nTransition = sizeof(COLOR_RESET) - 1;
|
|
return T(COLOR_RESET);
|
|
}
|
|
}
|
|
|
|
// Maximum escape transition length is:
|
|
//
|
|
// COLOR_RESET "%xn"
|
|
// + COLOR_INTENSE "%xh"
|
|
// + COLOR_UNDERLINE "%xu"
|
|
// + COLOR_BLINK "%xf"
|
|
// + COLOR_INVERSE "%xi"
|
|
// + COLOR_FG_... "%x<#FFFFFF>"
|
|
// + COLOR_BG_... "%x<#FFFFFF>"
|
|
//
|
|
// Each of the five codes is 3 bytes, and two codes are 11 bytes, or 37 bytes total.
|
|
//
|
|
#define COLOR_MAXIMUM_ESCAPE_TRANSITION_LENGTH 37
|
|
|
|
// Generate the minimal color %-sequence that will transition from one color state
|
|
// to another.
|
|
//
|
|
static UTF8 *ColorTransitionEscape
|
|
(
|
|
ColorState csCurrent,
|
|
ColorState csNext,
|
|
size_t *nTransition
|
|
)
|
|
{
|
|
ValidateColorState(csCurrent);
|
|
ValidateColorState(csNext);
|
|
|
|
static UTF8 Buffer[COLOR_MAXIMUM_ESCAPE_TRANSITION_LENGTH+1];
|
|
|
|
if (csCurrent == csNext)
|
|
{
|
|
*nTransition = 0;
|
|
Buffer[0] = '\0';
|
|
return Buffer;
|
|
}
|
|
size_t i = 0;
|
|
|
|
// Do we need to go through the normal state?
|
|
//
|
|
if ( ((csCurrent & ~csNext) & CS_ATTRS)
|
|
|| ( (csNext & CS_BACKGROUND) == CS_BG_DEFAULT
|
|
&& (csCurrent & CS_BACKGROUND) != CS_BG_DEFAULT)
|
|
|| ( (csNext & CS_FOREGROUND) == CS_FG_DEFAULT
|
|
&& (csCurrent & CS_FOREGROUND) != CS_FG_DEFAULT))
|
|
{
|
|
memcpy(Buffer + i, aColors[COLOR_INDEX_RESET].pEscape, aColors[COLOR_INDEX_RESET].nEscape);
|
|
i += aColors[COLOR_INDEX_RESET].nEscape;
|
|
csCurrent = CS_NORMAL;
|
|
}
|
|
|
|
ColorState tmp = csCurrent ^ csNext;
|
|
if (CS_ATTRS & tmp)
|
|
{
|
|
for (unsigned int iAttr = COLOR_INDEX_ATTR; iAttr < COLOR_INDEX_FG; iAttr++)
|
|
{
|
|
if (aColors[iAttr].cs == (aColors[iAttr].csMask & tmp))
|
|
{
|
|
memcpy(Buffer + i, aColors[iAttr].pEscape, aColors[iAttr].nEscape);
|
|
i += aColors[iAttr].nEscape;
|
|
}
|
|
}
|
|
}
|
|
|
|
RGB rgb;
|
|
unsigned int iColor;
|
|
if (CS_FOREGROUND & tmp)
|
|
{
|
|
if (CS_FG_INDEXED & csNext)
|
|
{
|
|
iColor = COLOR_INDEX_FG + static_cast<unsigned int>(CS_FG_FIELD(csNext));
|
|
if (iColor < COLOR_INDEX_FG + COLOR_INDEX_DEFAULT)
|
|
{
|
|
memcpy(Buffer + i, aColors[iColor].pEscape, aColors[iColor].nEscape);
|
|
i += aColors[iColor].nEscape;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cs2rgb(CS_FG_FIELD(csNext), &rgb);
|
|
mux_sprintf(Buffer + i, 12, T("%%x<#%02X%02X%02X>"), rgb.r, rgb.g, rgb.b);
|
|
i += 11;
|
|
}
|
|
}
|
|
|
|
if (CS_BACKGROUND & tmp)
|
|
{
|
|
if (CS_BG_INDEXED & csNext)
|
|
{
|
|
iColor = COLOR_INDEX_BG + static_cast<unsigned int>(CS_BG_FIELD(csNext));
|
|
if (iColor < COLOR_INDEX_BG + COLOR_INDEX_DEFAULT)
|
|
{
|
|
memcpy(Buffer + i, aColors[iColor].pEscape, aColors[iColor].nEscape);
|
|
i += aColors[iColor].nEscape;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cs2rgb(CS_BG_FIELD(csNext), &rgb);
|
|
mux_sprintf(Buffer + i, 12, T("%%X<#%02X%02X%02X>"), rgb.r, rgb.g, rgb.b);
|
|
i += 11;
|
|
}
|
|
}
|
|
Buffer[i] = '\0';
|
|
*nTransition = i;
|
|
return Buffer;
|
|
}
|
|
|
|
// Maximum ANSI transition length is:
|
|
//
|
|
// ANSI_NORMAL "\033[0m"
|
|
// + ANSI_HILITE "\033[1m"
|
|
// + ANSI_UNDER "\033[4m"
|
|
// + ANSI_BLINK "\033[5m"
|
|
// + ANSI_INVERSE "\033[7m"
|
|
// + ANSI_FG_... "\033[38;5;255m"
|
|
// + ANSI_BWHITE "\033[48;5;255m"
|
|
//
|
|
// Five of the seven codes are 4 bytes, and two are 11 bytes, or 42 bytes total.
|
|
//
|
|
#define COLOR_MAXIMUM_ANSI_TRANSITION_LENGTH 42
|
|
|
|
// Generate the minimal ANSI sequence that will transition from one color state
|
|
// to another.
|
|
//
|
|
static UTF8 *ColorTransitionANSI
|
|
(
|
|
ColorState &csClient,
|
|
ColorState csNext,
|
|
size_t *nTransition,
|
|
bool fNoBleed,
|
|
bool fColor256
|
|
)
|
|
{
|
|
ValidateColorState(csClient);
|
|
ValidateColorState(csNext);
|
|
|
|
static UTF8 Buffer[COLOR_MAXIMUM_ANSI_TRANSITION_LENGTH+1];
|
|
|
|
// First, modify our sense of what 'normal' is.
|
|
//
|
|
if ( fNoBleed
|
|
&& (csNext & CS_FOREGROUND) == CS_FG_DEFAULT)
|
|
{
|
|
csNext = (csNext & ~CS_FOREGROUND) | CS_FG_WHITE;
|
|
}
|
|
|
|
// Approximate Foreground Color
|
|
//
|
|
RGB rgb;
|
|
unsigned int iColor;
|
|
if (fColor256)
|
|
{
|
|
if (CS_FG_INDEXED & csNext)
|
|
{
|
|
if (CS_FG_FIELD(csNext) < COLOR_INDEX_DEFAULT)
|
|
{
|
|
iColor = COLOR_INDEX_FG + static_cast<unsigned int>(CS_FG_FIELD(csNext));
|
|
}
|
|
else
|
|
{
|
|
iColor = COLOR_INDEX_FG + COLOR_INDEX_DEFAULT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cs2rgb(CS_FG_FIELD(csNext), &rgb);
|
|
iColor = COLOR_INDEX_FG + FindNearestPaletteEntry(rgb, true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (CS_FG_INDEXED & csNext)
|
|
{
|
|
if (CS_FG_FIELD(csNext) < COLOR_INDEX_DEFAULT)
|
|
{
|
|
iColor = COLOR_INDEX_FG + palette[CS_FG_FIELD(csNext)].color16;
|
|
}
|
|
else
|
|
{
|
|
iColor = COLOR_INDEX_FG + COLOR_INDEX_DEFAULT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cs2rgb(CS_FG_FIELD(csNext), &rgb);
|
|
iColor = COLOR_INDEX_FG + FindNearestPaletteEntry(rgb, false);
|
|
}
|
|
|
|
// For foreground 256-to-16-color down-conversion, we 'borrow' the
|
|
// highlite capability. We don't need or want it if the client supports
|
|
// 256-color, and there is no highlite capability we can borrow for
|
|
// background color. This decision is a prerequisite to the 'return
|
|
// to normal' decision below.
|
|
//
|
|
if (COLOR_INDEX_FG + 8 <= iColor && iColor <= COLOR_INDEX_FG + 15)
|
|
{
|
|
csNext |= CS_INTENSE;
|
|
iColor -= 8;
|
|
}
|
|
}
|
|
if (iColor < COLOR_INDEX_FG + COLOR_INDEX_DEFAULT)
|
|
{
|
|
csNext = UpdateColorState(csNext, iColor);
|
|
}
|
|
|
|
// Aproximate Background Color
|
|
//
|
|
if (fColor256)
|
|
{
|
|
if (CS_BG_INDEXED & csNext)
|
|
{
|
|
if (CS_BG_FIELD(csNext) < COLOR_INDEX_DEFAULT)
|
|
{
|
|
iColor = COLOR_INDEX_BG + static_cast<unsigned int>(CS_BG_FIELD(csNext));
|
|
}
|
|
else
|
|
{
|
|
iColor = COLOR_INDEX_BG + COLOR_INDEX_DEFAULT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cs2rgb(CS_BG_FIELD(csNext), &rgb);
|
|
iColor = COLOR_INDEX_BG + FindNearestPaletteEntry(rgb, true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (CS_BG_INDEXED & csNext)
|
|
{
|
|
if (CS_BG_FIELD(csNext) < COLOR_INDEX_DEFAULT)
|
|
{
|
|
iColor = COLOR_INDEX_BG + palette[CS_BG_FIELD(csNext)].color8;
|
|
}
|
|
else
|
|
{
|
|
iColor = COLOR_INDEX_BG + COLOR_INDEX_DEFAULT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cs2rgb(CS_BG_FIELD(csNext), &rgb);
|
|
iColor = COLOR_INDEX_BG + FindNearestPalette8Entry(rgb);
|
|
}
|
|
}
|
|
if (iColor < COLOR_INDEX_BG + COLOR_INDEX_DEFAULT)
|
|
{
|
|
csNext = UpdateColorState(csNext, iColor);
|
|
}
|
|
|
|
if (csClient == csNext)
|
|
{
|
|
*nTransition = 0;
|
|
Buffer[0] = '\0';
|
|
return Buffer;
|
|
}
|
|
size_t i = 0;
|
|
|
|
// Do we need to go through the normal state?
|
|
//
|
|
if ( ((csClient & ~csNext) & CS_ATTRS)
|
|
|| ( (csNext & CS_BACKGROUND) == CS_BG_DEFAULT
|
|
&& (csClient & CS_BACKGROUND) != CS_BG_DEFAULT)
|
|
|| ( (csNext & CS_FOREGROUND) == CS_FG_DEFAULT
|
|
&& (csClient & CS_FOREGROUND) != CS_FG_DEFAULT))
|
|
{
|
|
memcpy(Buffer + i, ANSI_NORMAL, sizeof(ANSI_NORMAL)-1);
|
|
i += sizeof(ANSI_NORMAL)-1;
|
|
csClient = CS_NORMAL;
|
|
}
|
|
|
|
ColorState tmp = csClient ^ csNext;
|
|
if (CS_ATTRS & tmp)
|
|
{
|
|
for (unsigned int iAttr = COLOR_INDEX_ATTR; iAttr < COLOR_INDEX_FG; iAttr++)
|
|
{
|
|
if ( g_no_flash
|
|
&& COLOR_INDEX_BLINK == iAttr)
|
|
{
|
|
continue;
|
|
}
|
|
if (aColors[iAttr].cs == (aColors[iAttr].csMask & tmp))
|
|
{
|
|
memcpy(Buffer + i, aColors[iAttr].pAnsi, aColors[iAttr].nAnsi);
|
|
i += aColors[iAttr].nAnsi;
|
|
}
|
|
}
|
|
}
|
|
|
|
// At this point, all colors are indexed.
|
|
//
|
|
if (CS_FOREGROUND & tmp)
|
|
{
|
|
iColor = COLOR_INDEX_FG + static_cast<unsigned int>(CS_FG_FIELD(csNext));
|
|
if (iColor < COLOR_INDEX_FG + COLOR_INDEX_DEFAULT)
|
|
{
|
|
memcpy(Buffer + i, aColors[iColor].pAnsi, aColors[iColor].nAnsi);
|
|
i += aColors[iColor].nAnsi;
|
|
}
|
|
}
|
|
|
|
if (CS_BACKGROUND & tmp)
|
|
{
|
|
iColor = COLOR_INDEX_BG + static_cast<unsigned int>(CS_BG_FIELD(csNext));
|
|
if (iColor < COLOR_INDEX_BG + COLOR_INDEX_DEFAULT)
|
|
{
|
|
memcpy(Buffer + i, aColors[iColor].pAnsi, aColors[iColor].nAnsi);
|
|
i += aColors[iColor].nAnsi;
|
|
}
|
|
}
|
|
Buffer[i] = '\0';
|
|
*nTransition = i;
|
|
csClient = csNext;
|
|
return Buffer;
|
|
}
|
|
|
|
void LettersToColorState(ColorState &cs, UTF8 *pIn)
|
|
{
|
|
cs = CS_NORMAL;
|
|
bool fBackground = false;
|
|
size_t i = 0;
|
|
while ('\0' != pIn[i])
|
|
{
|
|
unsigned int iColor;
|
|
unsigned ch = pIn[i];
|
|
if ('<' == ch)
|
|
{
|
|
i++;
|
|
size_t j = i;
|
|
while ( '\0' != (ch = pIn[i])
|
|
&& '>' != ch)
|
|
{
|
|
i++;
|
|
}
|
|
RGB rgb;
|
|
if ('>' == ch)
|
|
{
|
|
if (parse_rgb(i - j, pIn + j, rgb))
|
|
{
|
|
iColor = FindNearestPaletteEntry(rgb, true);
|
|
bool fExact = ( palette[iColor].rgb.r == rgb.r
|
|
&& palette[iColor].rgb.g == rgb.g
|
|
&& palette[iColor].rgb.b == rgb.b);
|
|
if (fBackground)
|
|
{
|
|
cs = (cs & ~CS_BACKGROUND) | (fExact ? CS_BG(iColor) : (rgb2cs(&rgb) << 32));
|
|
}
|
|
else
|
|
{
|
|
cs = (cs & ~CS_FOREGROUND) | (fExact ? CS_FG(iColor) : rgb2cs(&rgb));
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
fBackground = false;
|
|
}
|
|
else if ('/' == ch)
|
|
{
|
|
fBackground = true;
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
iColor = ColorTable[pIn[i]];
|
|
if (iColor)
|
|
{
|
|
cs = UpdateColorState(cs, iColor);
|
|
}
|
|
fBackground = false;
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
UTF8 *LettersToBinary(UTF8 *pLetters)
|
|
{
|
|
size_t n;
|
|
ColorState cs = CS_NORMAL;
|
|
LettersToColorState(cs, pLetters);
|
|
return ColorTransitionBinary(CS_NORMAL, cs, &n);
|
|
}
|
|
|
|
enum class HTMLtag
|
|
{
|
|
kIntense,
|
|
kUnderline,
|
|
kBlink,
|
|
kInverse,
|
|
kColor,
|
|
kNormal,
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
bool fBeginEnd;
|
|
HTMLtag kTag;
|
|
ColorState cs;
|
|
int iStart;
|
|
} tag_node;
|
|
|
|
UTF8 *convert_to_html(const UTF8 *pString)
|
|
{
|
|
// Converting to HTML is performed in two passes. The first pass
|
|
// determines an optimal nesting order of tags. The second pass generates
|
|
// the HTML.
|
|
//
|
|
tag_node List[(LBUF_SIZE-1)/3];
|
|
int nList = 0;
|
|
int Stack[10];
|
|
int nStack = 0;
|
|
|
|
HTMLtag tagmap[5] = {HTMLtag::kIntense, HTMLtag::kUnderline, HTMLtag::kBlink, HTMLtag::kInverse, HTMLtag::kColor };
|
|
|
|
int iCopy;
|
|
int i = 0;
|
|
ColorState csPrev = CS_NORMAL;
|
|
ColorState csNext = CS_NORMAL;
|
|
unsigned int iCode = COLOR_NOTCOLOR;
|
|
|
|
if ('\0' != pString[i])
|
|
{
|
|
iCode = mux_color(pString + i);
|
|
if (COLOR_NOTCOLOR == iCode)
|
|
{
|
|
List[nList].fBeginEnd = true;
|
|
List[nList].kTag = HTMLtag::kNormal;
|
|
List[nList].cs = CS_NORMAL;
|
|
List[nList].iStart = -1;
|
|
nList++;
|
|
}
|
|
}
|
|
|
|
while ( '\0' != pString[i]
|
|
|| csNext != csPrev)
|
|
{
|
|
iCopy = i;
|
|
while ( '\0' != pString[i]
|
|
&& COLOR_NOTCOLOR == iCode)
|
|
{
|
|
i += utf8_advance_nul(pString + i);
|
|
iCode = mux_color(pString + i);
|
|
}
|
|
|
|
while (csNext != csPrev)
|
|
{
|
|
for (unsigned int iAttr = COLOR_INDEX_ATTR; iAttr < COLOR_INDEX_FG + 1; iAttr++)
|
|
{
|
|
ColorState tmp = csNext ^ csPrev;
|
|
HTMLtag kNext = tagmap[iAttr - COLOR_INDEX_ATTR];
|
|
bool fOpen = false;
|
|
bool fClose = false;
|
|
|
|
if (iAttr < COLOR_INDEX_FG)
|
|
{
|
|
// Attribute
|
|
//
|
|
if (tmp & aColors[iAttr].csMask)
|
|
{
|
|
if (csNext & aColors[iAttr].csMask)
|
|
{
|
|
fOpen = true;
|
|
}
|
|
else
|
|
{
|
|
fClose = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Color
|
|
//
|
|
if (tmp & CS_FOREGROUND)
|
|
{
|
|
if ( (csPrev & CS_FOREGROUND) == CS_FG_DEFAULT
|
|
&& (csNext & CS_FOREGROUND) != CS_FG_DEFAULT)
|
|
{
|
|
fOpen = true;
|
|
}
|
|
else if ( (csPrev & CS_FOREGROUND) != CS_FG_DEFAULT
|
|
&& (csNext & CS_FOREGROUND) == CS_FG_DEFAULT)
|
|
{
|
|
fClose = true;
|
|
}
|
|
else
|
|
{
|
|
fOpen = true;
|
|
fClose = true;
|
|
}
|
|
}
|
|
if (tmp & CS_BACKGROUND)
|
|
{
|
|
if ( (csPrev & CS_BACKGROUND) == CS_BG_DEFAULT
|
|
&& (csNext & CS_BACKGROUND) != CS_BG_DEFAULT)
|
|
{
|
|
fOpen = true;
|
|
}
|
|
else if ( (csPrev & CS_BACKGROUND) != CS_BG_DEFAULT
|
|
&& (csNext & CS_BACKGROUND) == CS_BG_DEFAULT)
|
|
{
|
|
fClose = true;
|
|
}
|
|
else
|
|
{
|
|
fOpen = true;
|
|
fClose = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fClose)
|
|
{
|
|
for (int j = nStack - 1; 0 <= j; j--)
|
|
{
|
|
if (List[Stack[j]].kTag == kNext)
|
|
{
|
|
if (List[Stack[j]].iStart != List[Stack[nStack-1]].iStart)
|
|
{
|
|
// Pop other tags and mark in csPrev that they are gone. We'll add them back in the next
|
|
// iteration of the loop. We stop at the point where tags can be swapped with the one
|
|
// we're interested in.
|
|
//
|
|
for (int k = nStack - 1; j < k && List[Stack[j]].iStart != List[Stack[nStack-1]].iStart; k--)
|
|
{
|
|
List[nList] = List[Stack[k]];
|
|
List[nList].fBeginEnd = false;
|
|
List[nList].iStart = -1;
|
|
|
|
switch (List[nList].kTag)
|
|
{
|
|
case HTMLtag::kIntense:
|
|
csPrev &= ~CS_INTENSE;
|
|
break;
|
|
|
|
case HTMLtag::kUnderline:
|
|
csPrev &= ~CS_UNDERLINE;
|
|
break;
|
|
|
|
case HTMLtag::kBlink:
|
|
csPrev &= ~CS_BLINK;
|
|
break;
|
|
|
|
case HTMLtag::kInverse:
|
|
csPrev &= ~CS_INVERSE;
|
|
break;
|
|
|
|
case HTMLtag::kColor:
|
|
csPrev = (csPrev & ~(CS_FOREGROUND|CS_BACKGROUND)) | CS_NORMAL;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
nList++;
|
|
nStack--;
|
|
}
|
|
}
|
|
|
|
if (j != nStack - 1)
|
|
{
|
|
// Change the order of tags which open at the
|
|
// same position so that the one we want to
|
|
// close can be popped.
|
|
//
|
|
tag_node t = List[Stack[j]];
|
|
List[Stack[j]] = List[Stack[nStack-1]];
|
|
List[Stack[nStack-1]] = t;
|
|
j = nStack - 1;
|
|
}
|
|
|
|
List[nList] = List[Stack[j]];
|
|
List[nList].fBeginEnd = false;
|
|
List[nList].iStart = -1;
|
|
switch (List[nList].kTag)
|
|
{
|
|
case HTMLtag::kIntense:
|
|
csPrev &= ~CS_INTENSE;
|
|
break;
|
|
|
|
case HTMLtag::kUnderline:
|
|
csPrev &= ~CS_UNDERLINE;
|
|
break;
|
|
|
|
case HTMLtag::kBlink:
|
|
csPrev &= ~CS_BLINK;
|
|
break;
|
|
|
|
case HTMLtag::kInverse:
|
|
csPrev &= ~CS_INVERSE;
|
|
break;
|
|
|
|
case HTMLtag::kColor:
|
|
csPrev = (csPrev & ~(CS_FOREGROUND|CS_BACKGROUND)) | CS_NORMAL;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
nList++;
|
|
|
|
nStack--;
|
|
if (0 == nStack)
|
|
{
|
|
List[nList].fBeginEnd = true;
|
|
List[nList].kTag = HTMLtag::kNormal;
|
|
List[nList].cs = CS_NORMAL;
|
|
List[nList].iStart = -1;
|
|
nList++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fOpen)
|
|
{
|
|
List[nList].fBeginEnd = true;
|
|
List[nList].cs = csNext;
|
|
List[nList].kTag = kNext;
|
|
List[nList].iStart = -1;
|
|
switch (List[nList].kTag)
|
|
{
|
|
case HTMLtag::kIntense:
|
|
csPrev |= CS_INTENSE;
|
|
break;
|
|
|
|
case HTMLtag::kUnderline:
|
|
csPrev |= CS_UNDERLINE;
|
|
break;
|
|
|
|
case HTMLtag::kBlink:
|
|
csPrev |= CS_BLINK;
|
|
break;
|
|
|
|
case HTMLtag::kInverse:
|
|
csPrev |= CS_INVERSE;
|
|
break;
|
|
|
|
case HTMLtag::kColor:
|
|
csPrev &= ~(CS_FOREGROUND|CS_BACKGROUND);
|
|
csPrev |= (CS_FOREGROUND|CS_BACKGROUND) & csNext;;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
Stack[nStack++] = nList++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 < nList)
|
|
{
|
|
List[nList-1].iStart = iCopy;
|
|
}
|
|
|
|
while ( '\0' != pString[i]
|
|
&& COLOR_NOTCOLOR != iCode)
|
|
{
|
|
csNext = UpdateColorState(csNext, iCode, pString + i);
|
|
i += utf8_advance_nul(pString + i);
|
|
iCode = mux_color(pString + i);
|
|
}
|
|
|
|
// When CS_INTENSE is active and the foreground is a basic ANSI
|
|
// color (0-7), substitute the bright palette entry (8-15) so
|
|
// that HTML <COLOR> tags carry the correct RGB value.
|
|
//
|
|
if ( (csNext & CS_INTENSE)
|
|
&& (CS_FG_INDEXED & csNext))
|
|
{
|
|
unsigned int idx = static_cast<unsigned int>(CS_FG_FIELD(csNext));
|
|
if (idx < 8)
|
|
{
|
|
csNext = (csNext & ~CS_FOREGROUND) | CS_FG(idx + 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
static UTF8 aBuffer[2*LBUF_SIZE];
|
|
UTF8 *pBuffer = aBuffer;
|
|
|
|
for (int iList = 0; iList < nList; iList++)
|
|
{
|
|
if (HTMLtag::kNormal != List[iList].kTag)
|
|
{
|
|
*pBuffer++ = '<';
|
|
if (!List[iList].fBeginEnd)
|
|
{
|
|
*pBuffer++ = '/';
|
|
}
|
|
|
|
switch (List[iList].kTag)
|
|
{
|
|
case HTMLtag::kIntense:
|
|
*pBuffer++ = 'B';
|
|
break;
|
|
|
|
case HTMLtag::kUnderline:
|
|
*pBuffer++ = 'U';
|
|
break;
|
|
|
|
case HTMLtag::kBlink:
|
|
*pBuffer++ = 'I';
|
|
break;
|
|
|
|
case HTMLtag::kInverse:
|
|
*pBuffer++ = 'S';
|
|
break;
|
|
|
|
case HTMLtag::kColor:
|
|
if (List[iList].fBeginEnd)
|
|
{
|
|
ColorState cs = List[iList].cs;
|
|
if ( (CS_FOREGROUND & cs) != CS_FG_DEFAULT
|
|
&& (CS_FG_INDEXED & cs))
|
|
{
|
|
cs = (cs & ~CS_FOREGROUND) | rgb2cs(&palette[CS_FG_FIELD(cs)].rgb);
|
|
}
|
|
|
|
if ( (CS_BACKGROUND & cs) != CS_BG_DEFAULT
|
|
&& (CS_BG_INDEXED & cs))
|
|
{
|
|
cs = (cs & ~CS_BACKGROUND) | (rgb2cs(&palette[CS_BG_FIELD(cs)].rgb) << 32);
|
|
}
|
|
|
|
if ((CS_FOREGROUND & cs) == CS_FG_DEFAULT)
|
|
{
|
|
if ((CS_BACKGROUND & cs) != CS_BG_DEFAULT)
|
|
{
|
|
mux_sprintf(pBuffer, sizeof(aBuffer) - (pBuffer - aBuffer) - 1, T("COLOR BACK=#%06llX"), CS_BG_FIELD(cs));
|
|
pBuffer += strlen(reinterpret_cast<char *>(pBuffer));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((CS_BACKGROUND & cs) == CS_BG_DEFAULT)
|
|
{
|
|
mux_sprintf(pBuffer, sizeof(aBuffer) - (pBuffer - aBuffer) - 1, T("COLOR #%06llX"), CS_FG_FIELD(cs));
|
|
pBuffer += strlen(reinterpret_cast<char *>(pBuffer));
|
|
}
|
|
else
|
|
{
|
|
mux_sprintf(pBuffer, sizeof(aBuffer) - (pBuffer - aBuffer) - 1, T("COLOR #%06llX #%06llX"), CS_FG_FIELD(cs), CS_BG_FIELD(cs));
|
|
pBuffer += strlen(reinterpret_cast<char *>(pBuffer));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mux_sprintf(pBuffer, sizeof(aBuffer) - (pBuffer - aBuffer) - 1, T("COLOR"));
|
|
pBuffer += strlen(reinterpret_cast<char *>(pBuffer));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
*pBuffer++ = '>';
|
|
}
|
|
|
|
iCopy = i = List[iList].iStart;
|
|
if (0 <= iCopy)
|
|
{
|
|
if ('\0' != pString[i])
|
|
{
|
|
iCode = mux_color(pString + i);
|
|
}
|
|
while ( '\0' != pString[i]
|
|
&& COLOR_NOTCOLOR == iCode)
|
|
{
|
|
i += utf8_advance_nul(pString + i);
|
|
iCode = mux_color(pString + i);
|
|
}
|
|
size_t n = i - iCopy;
|
|
|
|
if (0 < n)
|
|
{
|
|
memcpy(pBuffer, pString + List[iList].iStart, n);
|
|
pBuffer += n;
|
|
}
|
|
}
|
|
}
|
|
|
|
*pBuffer = '\0';
|
|
return aBuffer;
|
|
}
|
|
|
|
/*! \brief Convert private color code points within a string to ANSI color
|
|
* sequences.
|
|
*
|
|
* This routine converts these internal color code points to ANSI sequences
|
|
* which clients will recognize.
|
|
*
|
|
* Internally, the server uses color code points to represent color. This
|
|
* representation is more compact, it simplifies the parser, and it thwarts
|
|
* the possibility of softcode generating naked ESC characters. Several
|
|
* protocols use the ESC character, so it is helpful if the server controls
|
|
* their use.
|
|
*
|
|
* \param pString String (length LBUF_SIZE-1 or less) with color code points.
|
|
* \param fNoBleed Should we dodge a naked return-to-normal state.
|
|
* \param fColor256 Can we use the full 256-color palette?
|
|
* \return String with exportable ANSI color sequences.
|
|
*/
|
|
|
|
UTF8 *convert_color(const UTF8 *pString, bool fNoBleed, bool fColor256)
|
|
{
|
|
static UTF8 aBuffer[2*LBUF_SIZE];
|
|
|
|
static const UTF8 *pNormal= T(ANSI_NORMAL ANSI_WHITE);
|
|
size_t nNormal = sizeof(ANSI_NORMAL)-1;
|
|
if (fNoBleed)
|
|
{
|
|
nNormal += sizeof(ANSI_WHITE)-1;
|
|
}
|
|
|
|
ColorState csClient = (fNoBleed)?CS_FG_WHITE:CS_NORMAL;
|
|
ColorState csPrev = CS_NORMAL;
|
|
ColorState csNext = CS_NORMAL;
|
|
UTF8 *pBuffer = aBuffer;
|
|
size_t i = 0;
|
|
size_t iCopy = 0;
|
|
unsigned int iCode = COLOR_NOTCOLOR;
|
|
if ('\0' != pString[i])
|
|
{
|
|
iCode = mux_color(pString + i);
|
|
}
|
|
while ('\0' != pString[i])
|
|
{
|
|
iCopy = i;
|
|
while ( '\0' != pString[i]
|
|
&& COLOR_NOTCOLOR == iCode)
|
|
{
|
|
i += utf8_advance_nul(pString + i);
|
|
iCode = mux_color(pString + i);
|
|
}
|
|
|
|
if (iCopy < i)
|
|
{
|
|
if (csNext != csPrev)
|
|
{
|
|
UTF8 *pTransition = nullptr;
|
|
size_t nTransition;
|
|
pTransition = ColorTransitionANSI( csClient, csNext,
|
|
&nTransition, fNoBleed, fColor256);
|
|
if (nTransition)
|
|
{
|
|
if (sizeof(aBuffer) - (pBuffer - aBuffer) - nNormal - 1 < nTransition)
|
|
{
|
|
break;
|
|
}
|
|
memcpy(pBuffer, pTransition, nTransition);
|
|
pBuffer += nTransition;
|
|
}
|
|
csPrev = csNext;
|
|
}
|
|
|
|
if (sizeof(aBuffer) - (pBuffer - aBuffer) - nNormal - 1 < i - iCopy)
|
|
{
|
|
break;
|
|
}
|
|
memcpy(pBuffer, pString + iCopy, i - iCopy);
|
|
pBuffer += i - iCopy;
|
|
iCopy = i;
|
|
}
|
|
|
|
while ( '\0' != pString[i]
|
|
&& COLOR_NOTCOLOR != iCode)
|
|
{
|
|
csNext = UpdateColorState(csNext, iCode, pString + i);
|
|
i += utf8_advance_nul(pString + i);
|
|
iCode = mux_color(pString + i);
|
|
}
|
|
}
|
|
if (csPrev != CS_NORMAL)
|
|
{
|
|
memcpy(pBuffer, pNormal, nNormal);
|
|
pBuffer += nNormal;
|
|
}
|
|
*pBuffer = '\0';
|
|
return aBuffer;
|
|
}
|
|
|
|
UTF8 *strip_color(const UTF8 *pString, size_t *pnBytes, size_t *pnPoints)
|
|
{
|
|
static UTF8 aBuffer[LBUF_SIZE];
|
|
UTF8 *pBuffer = aBuffer;
|
|
|
|
if (nullptr == pString)
|
|
{
|
|
if (nullptr != pnBytes)
|
|
{
|
|
*pnBytes = 0;
|
|
}
|
|
if (nullptr != pnPoints)
|
|
{
|
|
*pnPoints = 0;
|
|
}
|
|
*pBuffer = '\0';
|
|
return aBuffer;
|
|
}
|
|
|
|
size_t nPoints = 0;
|
|
while ('\0' != *pString)
|
|
{
|
|
if (COLOR_NOTCOLOR == mux_color(pString))
|
|
{
|
|
utf8_safe_chr(pString, aBuffer, &pBuffer);
|
|
nPoints++;
|
|
}
|
|
pString += utf8_advance_nul(pString);
|
|
}
|
|
*pBuffer = '\0';
|
|
if (nullptr != pnBytes)
|
|
{
|
|
*pnBytes = pBuffer - aBuffer;
|
|
}
|
|
if (nullptr != pnPoints)
|
|
{
|
|
*pnPoints = nPoints;
|
|
}
|
|
return aBuffer;
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
int len;
|
|
const UTF8 *p;
|
|
} LITERAL_STRING_STRUCT;
|
|
|
|
#define NUM_WS_SUBS 6
|
|
#define NUM_MU_SUBS 14
|
|
static LITERAL_STRING_STRUCT MU_Substitutes[NUM_MU_SUBS] =
|
|
{
|
|
{ 1, T(" ") }, // 0
|
|
{ 1, T(" ") }, // 1
|
|
{ 2, T("%t") }, // 2
|
|
{ 2, T("%r") }, // 3
|
|
{ 0, nullptr }, // 4
|
|
{ 2, T("%b") }, // 5
|
|
{ 2, T("%%") }, // 6
|
|
{ 2, T("%(") }, // 7
|
|
{ 2, T("%)") }, // 8
|
|
{ 2, T("%[") }, // 9
|
|
{ 2, T("%]") }, // 10
|
|
{ 2, T("%{") }, // 11
|
|
{ 2, T("%}") }, // 12
|
|
{ 2, T("\\\\") } // 13
|
|
};
|
|
|
|
const unsigned char MU_EscapeConvert[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 4, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
1, 0, 0, 0, 0, 6, 0, 0, 7, 8, 0, 0, 0, 0, 0, 0, // 2
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,13,10, 0, 0, // 5
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,11, 0,12, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
const unsigned char MU_EscapeNoConvert[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
//
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 4, 0, 0, // 0
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
|
|
};
|
|
|
|
// Convert raw character sequences into MUX substitutions (type = 1)
|
|
// or strips them (type = 0).
|
|
//
|
|
UTF8 *translate_string(const UTF8 *pString, bool bConvert)
|
|
{
|
|
static UTF8 szTranslatedString[LBUF_SIZE];
|
|
UTF8 *pTranslatedString = szTranslatedString;
|
|
|
|
if (!pString)
|
|
{
|
|
*pTranslatedString = '\0';
|
|
return szTranslatedString;
|
|
}
|
|
|
|
ColorState csCurrent = CS_NOBLEED;
|
|
ColorState csPrevious = csCurrent;
|
|
|
|
const UTF8 *MU_EscapeChar = (bConvert)? MU_EscapeConvert : MU_EscapeNoConvert;
|
|
while ('\0' != *pString)
|
|
{
|
|
unsigned int iCode = mux_color(pString);
|
|
if (COLOR_NOTCOLOR == iCode)
|
|
{
|
|
size_t nTransition = 0;
|
|
if (bConvert)
|
|
{
|
|
UTF8 *pTransition = ColorTransitionEscape(csPrevious, csCurrent, &nTransition);
|
|
safe_str(pTransition, szTranslatedString, &pTranslatedString);
|
|
csPrevious = csCurrent;
|
|
}
|
|
|
|
UTF8 ch = pString[0];
|
|
unsigned char code = MU_EscapeChar[ch];
|
|
if ( 0 < code
|
|
&& code < NUM_MU_SUBS)
|
|
{
|
|
if ( ' ' == ch
|
|
&& ' ' == pString[1])
|
|
{
|
|
code = 5;
|
|
}
|
|
safe_copy_buf(MU_Substitutes[code].p,
|
|
MU_Substitutes[code].len, szTranslatedString,
|
|
&pTranslatedString);
|
|
}
|
|
else
|
|
{
|
|
utf8_safe_chr(pString, szTranslatedString, &pTranslatedString);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
csCurrent = UpdateColorState(csCurrent, iCode, pString);
|
|
}
|
|
pString += utf8_advance_nul(pString);
|
|
}
|
|
*pTranslatedString = '\0';
|
|
return szTranslatedString;
|
|
}
|
|
|
|
bool IsDecompFriendly(const UTF8 *pString)
|
|
{
|
|
bool fFriendly = true;
|
|
if (!pString)
|
|
{
|
|
return fFriendly;
|
|
}
|
|
|
|
const UTF8 *MU_EscapeChar = MU_EscapeConvert;
|
|
while ( '\0' != *pString
|
|
&& fFriendly)
|
|
{
|
|
unsigned int iCode = mux_color(pString);
|
|
if (COLOR_NOTCOLOR == iCode)
|
|
{
|
|
UTF8 ch = pString[0];
|
|
unsigned char code = MU_EscapeChar[ch];
|
|
if ( 0 < code
|
|
&& code < NUM_WS_SUBS)
|
|
{
|
|
if (' ' == ch)
|
|
{
|
|
if (' ' == pString[1])
|
|
{
|
|
// Two adjacent spaces are not @decomp-friendly.
|
|
//
|
|
fFriendly = false;
|
|
break;
|
|
}
|
|
|
|
// An isolated space is still @decomp-friendly.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
// Raw tabs and newlines are not @decomp-friendly.
|
|
//
|
|
fFriendly = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Raw color codes are not @decomp-friendly.
|
|
//
|
|
fFriendly = false;
|
|
break;
|
|
}
|
|
pString += utf8_advance_nul(pString);
|
|
}
|
|
return fFriendly;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* munge_space: Compress multiple spaces to one space, also remove leading and
|
|
* trailing spaces.
|
|
*/
|
|
UTF8 *munge_space(const UTF8 *string)
|
|
{
|
|
UTF8 *buffer = alloc_lbuf("munge_space");
|
|
const UTF8 *p = string;
|
|
UTF8 *q = buffer;
|
|
|
|
if (p)
|
|
{
|
|
// Remove initial spaces.
|
|
//
|
|
while (mux_isspace(*p))
|
|
p++;
|
|
|
|
while (*p)
|
|
{
|
|
while (*p && !mux_isspace(*p))
|
|
*q++ = *p++;
|
|
|
|
while (mux_isspace(*p))
|
|
{
|
|
p++;
|
|
}
|
|
|
|
if (*p)
|
|
*q++ = ' ';
|
|
}
|
|
}
|
|
|
|
// Remove terminal spaces and terminate string.
|
|
//
|
|
*q = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* trim_spaces: Remove leading and trailing spaces and space-compress internal
|
|
* spaces.
|
|
*/
|
|
UTF8 *trim_spaces(const UTF8 *string)
|
|
{
|
|
UTF8 *buffer = alloc_lbuf("trim_spaces");
|
|
const UTF8 *p = string;
|
|
UTF8 *q = buffer;
|
|
|
|
if (p)
|
|
{
|
|
// Remove initial spaces.
|
|
//
|
|
while (mux_isspace(*p))
|
|
{
|
|
p++;
|
|
}
|
|
|
|
while (*p)
|
|
{
|
|
// Copy non-space characters.
|
|
//
|
|
while (*p && !mux_isspace(*p))
|
|
{
|
|
*q++ = *p++;
|
|
}
|
|
|
|
// Compress spaces.
|
|
//
|
|
while (mux_isspace(*p))
|
|
{
|
|
p++;
|
|
}
|
|
|
|
// Leave one space.
|
|
//
|
|
if (*p)
|
|
{
|
|
*q++ = ' ';
|
|
}
|
|
}
|
|
}
|
|
|
|
// Terminate string.
|
|
//
|
|
*q = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
/*
|
|
* ---------------------------------------------------------------------------
|
|
* * grabto: Return portion of a string up to the indicated character. Also
|
|
* * returns a modified pointer to the string ready for another call.
|
|
*/
|
|
|
|
UTF8 *grabto(UTF8 **str, UTF8 targ)
|
|
{
|
|
UTF8 *savec, *cp;
|
|
|
|
if (!str || !*str || !**str)
|
|
return nullptr;
|
|
|
|
savec = cp = *str;
|
|
while (*cp && *cp != targ)
|
|
cp++;
|
|
if (*cp)
|
|
*cp++ = '\0';
|
|
*str = cp;
|
|
return savec;
|
|
}
|
|
|
|
int string_compare(const UTF8 *s1, const UTF8 *s2)
|
|
{
|
|
if (g_space_compress)
|
|
{
|
|
while (mux_isspace(*s1))
|
|
{
|
|
s1++;
|
|
}
|
|
while (mux_isspace(*s2))
|
|
{
|
|
s2++;
|
|
}
|
|
|
|
while (*s1 && *s2)
|
|
{
|
|
if (mux_isspace(*s1) && mux_isspace(*s2))
|
|
{
|
|
// Both are spaces — skip all contiguous spaces.
|
|
//
|
|
do
|
|
{
|
|
s1++;
|
|
} while (mux_isspace(*s1));
|
|
|
|
do
|
|
{
|
|
s2++;
|
|
} while (mux_isspace(*s2));
|
|
continue;
|
|
}
|
|
|
|
// ASCII fast path: compare via table without the full
|
|
// Unicode state machine.
|
|
//
|
|
if (*s1 < 0x80 && *s2 < 0x80)
|
|
{
|
|
if (mux_tolower_ascii[*s1] != mux_tolower_ascii[*s2])
|
|
{
|
|
break;
|
|
}
|
|
s1++;
|
|
s2++;
|
|
continue;
|
|
}
|
|
|
|
// Compare code points case-insensitively (Unicode-aware).
|
|
//
|
|
UTF8 la[4], lb[4];
|
|
size_t na, nb;
|
|
|
|
bool bXorA;
|
|
const string_desc *qA = mux_tolower(s1, bXorA);
|
|
if (nullptr == qA)
|
|
{
|
|
na = utf8_FirstByte[static_cast<unsigned char>(*s1)];
|
|
if (na >= UTF8_CONTINUE) na = 1;
|
|
for (size_t j = 0; j < na; j++) la[j] = s1[j];
|
|
}
|
|
else
|
|
{
|
|
na = qA->n_bytes;
|
|
if (bXorA)
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = s1[j] ^ qA->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = qA->p[j];
|
|
}
|
|
}
|
|
|
|
bool bXorB;
|
|
const string_desc *qB = mux_tolower(s2, bXorB);
|
|
if (nullptr == qB)
|
|
{
|
|
nb = utf8_FirstByte[static_cast<unsigned char>(*s2)];
|
|
if (nb >= UTF8_CONTINUE) nb = 1;
|
|
for (size_t j = 0; j < nb; j++) lb[j] = s2[j];
|
|
}
|
|
else
|
|
{
|
|
nb = qB->n_bytes;
|
|
if (bXorB)
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = s2[j] ^ qB->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = qB->p[j];
|
|
}
|
|
}
|
|
|
|
// If lowercased code points differ, we're done.
|
|
//
|
|
if (na != nb)
|
|
{
|
|
break;
|
|
}
|
|
bool bEqual = true;
|
|
for (size_t j = 0; j < na; j++)
|
|
{
|
|
if (la[j] != lb[j])
|
|
{
|
|
bEqual = false;
|
|
break;
|
|
}
|
|
}
|
|
if (!bEqual)
|
|
{
|
|
break;
|
|
}
|
|
|
|
s1 += na;
|
|
s2 += nb;
|
|
}
|
|
if ( *s1
|
|
&& *s2)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (mux_isspace(*s1))
|
|
{
|
|
while (mux_isspace(*s1))
|
|
{
|
|
s1++;
|
|
}
|
|
return *s1;
|
|
}
|
|
if (mux_isspace(*s2))
|
|
{
|
|
while (mux_isspace(*s2))
|
|
{
|
|
s2++;
|
|
}
|
|
return *s2;
|
|
}
|
|
if ( *s1
|
|
|| *s2)
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return mux_stricmp(s1, s2);
|
|
}
|
|
}
|
|
|
|
int string_prefix(const UTF8 *string, const UTF8 *prefix)
|
|
{
|
|
int count = 0;
|
|
|
|
// ASCII fast path: compare bytes directly via tolower table.
|
|
// Most object names and commands are pure ASCII — this avoids
|
|
// the full Unicode mux_tolower state machine per character.
|
|
//
|
|
while (*string && *prefix
|
|
&& *string < 0x80 && *prefix < 0x80)
|
|
{
|
|
if (mux_tolower_ascii[*string] != mux_tolower_ascii[*prefix])
|
|
{
|
|
return 0;
|
|
}
|
|
string++;
|
|
prefix++;
|
|
count++;
|
|
}
|
|
|
|
// Unicode fallback: code-point-at-a-time case-insensitive comparison.
|
|
//
|
|
while (*string && *prefix)
|
|
{
|
|
UTF8 la[4], lb[4];
|
|
size_t na, nb;
|
|
|
|
bool bXorA;
|
|
const string_desc *qA = mux_tolower(string, bXorA);
|
|
if (nullptr == qA)
|
|
{
|
|
na = utf8_FirstByte[static_cast<unsigned char>(*string)];
|
|
if (na >= UTF8_CONTINUE) na = 1;
|
|
for (size_t j = 0; j < na; j++) la[j] = string[j];
|
|
}
|
|
else
|
|
{
|
|
na = qA->n_bytes;
|
|
if (bXorA)
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = string[j] ^ qA->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = qA->p[j];
|
|
}
|
|
}
|
|
|
|
bool bXorB;
|
|
const string_desc *qB = mux_tolower(prefix, bXorB);
|
|
if (nullptr == qB)
|
|
{
|
|
nb = utf8_FirstByte[static_cast<unsigned char>(*prefix)];
|
|
if (nb >= UTF8_CONTINUE) nb = 1;
|
|
for (size_t j = 0; j < nb; j++) lb[j] = prefix[j];
|
|
}
|
|
else
|
|
{
|
|
nb = qB->n_bytes;
|
|
if (bXorB)
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = prefix[j] ^ qB->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = qB->p[j];
|
|
}
|
|
}
|
|
|
|
if (na != nb)
|
|
{
|
|
return 0;
|
|
}
|
|
for (size_t j = 0; j < na; j++)
|
|
{
|
|
if (la[j] != lb[j])
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
string += na;
|
|
prefix += nb;
|
|
count += static_cast<int>(na);
|
|
}
|
|
if (*prefix == '\0')
|
|
{
|
|
// Matched all of prefix.
|
|
//
|
|
return count;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* accepts only nonempty matches starting at the beginning of a word
|
|
*/
|
|
|
|
const UTF8 *string_match(const UTF8 *src, const UTF8 *sub)
|
|
{
|
|
if ((*sub != '\0') && (src))
|
|
{
|
|
const bool ascii_sub = (*sub < 0x80);
|
|
const UTF8 sub0_lower = ascii_sub
|
|
? mux_tolower_ascii[*sub]
|
|
: 0;
|
|
|
|
while (*src)
|
|
{
|
|
if (ascii_sub && *src < 0x80)
|
|
{
|
|
if (mux_tolower_ascii[*src] != sub0_lower)
|
|
{
|
|
while (mux_isalnum(*src))
|
|
{
|
|
src++;
|
|
}
|
|
while (*src && !mux_isalnum(*src))
|
|
{
|
|
src++;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
const UTF8 *s = src;
|
|
const UTF8 *p = sub;
|
|
|
|
while (*s && *p && *s < 0x80 && *p < 0x80)
|
|
{
|
|
if (mux_tolower_ascii[*s] != mux_tolower_ascii[*p])
|
|
{
|
|
break;
|
|
}
|
|
s++;
|
|
p++;
|
|
}
|
|
|
|
if (*p == '\0')
|
|
{
|
|
return src;
|
|
}
|
|
|
|
// If the ASCII prefix matched and either side then went
|
|
// non-ASCII, fall back to the full Unicode-aware matcher.
|
|
if ((*s || *p) && !(*s < 0x80 && *p < 0x80)
|
|
&& string_prefix(src, sub))
|
|
{
|
|
return src;
|
|
}
|
|
}
|
|
else if (string_prefix(src, sub))
|
|
{
|
|
return src;
|
|
}
|
|
|
|
// else scan to beginning of next word
|
|
//
|
|
while (mux_isalnum(*src))
|
|
{
|
|
src++;
|
|
}
|
|
while (*src && !mux_isalnum(*src))
|
|
{
|
|
src++;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* ---------------------------------------------------------------------------
|
|
* * replace_string: Returns an lbuf containing string STRING with all occurances
|
|
* * of OLD replaced by NEW. OLD and NEW may be different lengths.
|
|
* * (mitch 1 feb 91)
|
|
*/
|
|
|
|
UTF8 *replace_string(const UTF8 *old, const UTF8 *new0, const UTF8 *s)
|
|
{
|
|
if (!s)
|
|
{
|
|
return nullptr;
|
|
}
|
|
size_t olen = strlen(reinterpret_cast<const char *>(old));
|
|
UTF8 *result = alloc_lbuf("replace_string");
|
|
UTF8 *r = result;
|
|
while (*s)
|
|
{
|
|
// Find next occurrence of the first character of OLD string.
|
|
//
|
|
const UTF8 *p = reinterpret_cast<const UTF8 *>(strchr(reinterpret_cast<const char *>(s), old[0]));
|
|
if ( olen
|
|
&& p)
|
|
{
|
|
// Copy up to the next occurrence of the first char of OLD.
|
|
//
|
|
size_t n = p - s;
|
|
if (n)
|
|
{
|
|
safe_copy_buf(s, n, result, &r);
|
|
s += n;
|
|
}
|
|
|
|
// If we are really at an complete OLD, append NEW to the result
|
|
// and bump the input string past the occurrence of OLD.
|
|
// Otherwise, copy the character and try matching again.
|
|
//
|
|
if (!strncmp(reinterpret_cast<const char *>(old), reinterpret_cast<const char *>(s), olen))
|
|
{
|
|
safe_str(new0, result, &r);
|
|
s += olen;
|
|
}
|
|
else
|
|
{
|
|
safe_chr(*s, result, &r);
|
|
s++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Finish copying source string. No matches. No further
|
|
// work to perform.
|
|
//
|
|
safe_str(s, result, &r);
|
|
break;
|
|
}
|
|
}
|
|
*r = '\0';
|
|
return result;
|
|
}
|
|
|
|
bool minmatch(const UTF8 *str, const UTF8 *target, int min)
|
|
{
|
|
// Code-point-at-a-time case-insensitive comparison (Unicode-aware).
|
|
// min tracks bytes matched (callers pass byte-based minlen).
|
|
//
|
|
while (*str && *target)
|
|
{
|
|
UTF8 la[4], lb[4];
|
|
size_t na, nb;
|
|
|
|
bool bXorA;
|
|
const string_desc *qA = mux_tolower(str, bXorA);
|
|
if (nullptr == qA)
|
|
{
|
|
na = utf8_FirstByte[static_cast<unsigned char>(*str)];
|
|
if (na >= UTF8_CONTINUE) na = 1;
|
|
for (size_t j = 0; j < na; j++) la[j] = str[j];
|
|
}
|
|
else
|
|
{
|
|
na = qA->n_bytes;
|
|
if (bXorA)
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = str[j] ^ qA->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = qA->p[j];
|
|
}
|
|
}
|
|
|
|
bool bXorB;
|
|
const string_desc *qB = mux_tolower(target, bXorB);
|
|
if (nullptr == qB)
|
|
{
|
|
nb = utf8_FirstByte[static_cast<unsigned char>(*target)];
|
|
if (nb >= UTF8_CONTINUE) nb = 1;
|
|
for (size_t j = 0; j < nb; j++) lb[j] = target[j];
|
|
}
|
|
else
|
|
{
|
|
nb = qB->n_bytes;
|
|
if (bXorB)
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = target[j] ^ qB->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = qB->p[j];
|
|
}
|
|
}
|
|
|
|
if (na != nb)
|
|
{
|
|
return false;
|
|
}
|
|
for (size_t j = 0; j < na; j++)
|
|
{
|
|
if (la[j] != lb[j])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
str += na;
|
|
target += nb;
|
|
min -= static_cast<int>(na);
|
|
}
|
|
if (*str)
|
|
{
|
|
return false;
|
|
}
|
|
if (!*target)
|
|
{
|
|
return true;
|
|
}
|
|
return (min <= 0);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// StringCloneLen: allocate memory and copy string
|
|
//
|
|
UTF8 *StringCloneLen(const UTF8 *str, size_t nStr)
|
|
{
|
|
UTF8 *buff = reinterpret_cast<UTF8 *>(MEMALLOC(nStr+1));
|
|
if (buff)
|
|
{
|
|
memcpy(buff, str, nStr);
|
|
buff[nStr] = '\0';
|
|
}
|
|
else
|
|
{
|
|
OutOfMemory(reinterpret_cast<const UTF8 *>(__FILE__), __LINE__);
|
|
}
|
|
return buff;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// StringClone: allocate memory and copy string
|
|
//
|
|
UTF8 *StringClone(const UTF8 *str)
|
|
{
|
|
return StringCloneLen(str, strlen(reinterpret_cast<const char *>(str)));
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* safe_copy_str - Copy buffers, watching for overflows.
|
|
*/
|
|
|
|
void safe_copy_str(const UTF8 *src, UTF8 *buff, UTF8 **bufp, size_t nSizeOfBuffer)
|
|
{
|
|
if (src == nullptr) return;
|
|
|
|
UTF8 *tp = *bufp;
|
|
UTF8 *maxtp = buff + nSizeOfBuffer;
|
|
while (tp < maxtp && *src)
|
|
{
|
|
*tp++ = *src++;
|
|
}
|
|
*bufp = buff + TrimPartialSequence(tp - buff, buff);
|
|
}
|
|
|
|
void safe_copy_str_lbuf(const UTF8 *src, UTF8 *buff, UTF8 **bufp)
|
|
{
|
|
if (src == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
UTF8 *tp = *bufp;
|
|
UTF8 *maxtp = buff + LBUF_SIZE - 1;
|
|
while (tp < maxtp && *src)
|
|
{
|
|
*tp++ = *src++;
|
|
}
|
|
*bufp = buff + TrimPartialSequence(tp - buff, buff);
|
|
}
|
|
|
|
size_t safe_copy_buf(const UTF8 *src, size_t nLen, UTF8 *buff, UTF8 **bufc)
|
|
{
|
|
size_t left = LBUF_SIZE - (*bufc - buff) - 1;
|
|
if (left < nLen)
|
|
{
|
|
nLen = TrimPartialSequence(left, src);
|
|
}
|
|
memcpy(*bufc, src, nLen);
|
|
*bufc += nLen;
|
|
return nLen;
|
|
}
|
|
|
|
size_t safe_fill(UTF8 *buff, UTF8 **bufc, UTF8 chFill, size_t nSpaces)
|
|
{
|
|
// Check for buffer limits.
|
|
//
|
|
size_t nBufferAvailable = LBUF_SIZE - (*bufc - buff) - 1;
|
|
if (nSpaces > nBufferAvailable)
|
|
{
|
|
nSpaces = nBufferAvailable;
|
|
}
|
|
|
|
// Fill with spaces.
|
|
//
|
|
memset(*bufc, chFill, nSpaces);
|
|
*bufc += nSpaces;
|
|
return nSpaces;
|
|
}
|
|
|
|
void utf8_safe_chr(const UTF8 *src, UTF8 *buff, UTF8 **bufc)
|
|
{
|
|
size_t nLen;
|
|
size_t nLeft;
|
|
if ( nullptr == src
|
|
|| UTF8_CONTINUE <= (nLen = utf8_FirstByte[*src]))
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (size_t i = 1; i < nLen; i++)
|
|
{
|
|
if ( '\0' == src[i]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[src[i]])
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
nLeft = LBUF_SIZE - (*bufc - buff) - 1;
|
|
if (nLeft < nLen)
|
|
{
|
|
return;
|
|
}
|
|
memcpy(*bufc, src, nLen);
|
|
*bufc += nLen;
|
|
}
|
|
|
|
UTF8 *ConvertToUTF8
|
|
(
|
|
UTF32 ch
|
|
)
|
|
{
|
|
static UTF8 buffer[6];
|
|
const UTF32 byteMask = 0xBF;
|
|
const UTF32 byteMark = 0x80;
|
|
|
|
if (ch < (UTF32)0x80)
|
|
{
|
|
// ASCII
|
|
//
|
|
buffer[1] = '\0';
|
|
buffer[0] = static_cast<UTF8>(ch);
|
|
}
|
|
else if (ch < (UTF32)0x800)
|
|
{
|
|
buffer[2] = '\0';
|
|
buffer[1] = static_cast<char>((ch | byteMark) & byteMask);
|
|
ch >>= 6;
|
|
buffer[0] = static_cast<char>(0xC0 | ch);
|
|
}
|
|
else if (ch < (UTF32)0x10000)
|
|
{
|
|
if ( UNI_SUR_HIGH_START <= ch
|
|
&& ch <= UNI_SUR_LOW_END)
|
|
{
|
|
buffer[0] = '\0';
|
|
return buffer;
|
|
}
|
|
buffer[3] = '\0';
|
|
buffer[2] =static_cast<char>((ch | byteMark) & byteMask);
|
|
ch >>= 6;
|
|
buffer[1] = static_cast<char>((ch | byteMark) & byteMask);
|
|
ch >>= 6;
|
|
buffer[0] = static_cast<char>(0xE0 | ch);
|
|
}
|
|
else if (ch <= UNI_MAX_LEGAL_UTF32)
|
|
{
|
|
buffer[4] = '\0';
|
|
buffer[3] = static_cast<char>((ch | byteMark) & byteMask);
|
|
ch >>= 6;
|
|
buffer[2] = static_cast<char>((ch | byteMark) & byteMask);
|
|
ch >>= 6;
|
|
buffer[1] = static_cast<char>((ch | byteMark) & byteMask);
|
|
ch >>= 6;
|
|
buffer[0] = static_cast<char>(0xF0 | ch);
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
UTF16 *ConvertToUTF16(UTF32 ch)
|
|
{
|
|
static UTF16 buffer[3];
|
|
if ( ch < UNI_SUR_HIGH_START
|
|
|| UNI_SUR_LOW_END < ch)
|
|
{
|
|
// This is the common case.
|
|
//
|
|
buffer[0] = (UTF16)ch;
|
|
buffer[1] = 0x0000;
|
|
return buffer;
|
|
}
|
|
else if (ch <= UNI_MAX_LEGAL_UTF32)
|
|
{
|
|
const int halfShift = 10;
|
|
const UTF32 halfBase = 0x0010000UL;
|
|
const UTF32 halfMask = 0x3FFUL;
|
|
|
|
ch -= halfBase;
|
|
buffer[0] = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
|
|
buffer[1] = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
|
|
buffer[2] = 0x0000;
|
|
}
|
|
else
|
|
{
|
|
buffer[0] = UNI_REPLACEMENT_CHAR;
|
|
buffer[1] = 0x0000;
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
UTF32 ConvertFromUTF8(const UTF8 *pString)
|
|
{
|
|
size_t t = utf8_FirstByte[*pString];
|
|
if (UTF8_CONTINUE <= t)
|
|
{
|
|
return UNI_EOF;
|
|
}
|
|
|
|
UTF32 ch;
|
|
if (1 == t)
|
|
{
|
|
// This is the most common case, and the value is always smaller than
|
|
// UNI_SUR_HIGH_START.
|
|
//
|
|
return pString[0];
|
|
}
|
|
else if (2 == t)
|
|
{
|
|
if ( '\0' == pString[1]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[pString[1]])
|
|
{
|
|
return UNI_EOF;
|
|
}
|
|
ch = utf8_decode_raw(pString, 2);
|
|
if (!utf8_is_valid_scalar(ch, 2))
|
|
{
|
|
return UNI_EOF;
|
|
}
|
|
}
|
|
else if (3 == t)
|
|
{
|
|
if ( '\0' == pString[1]
|
|
|| '\0' == pString[2]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[pString[1]]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[pString[2]])
|
|
{
|
|
return UNI_EOF;
|
|
}
|
|
ch = utf8_decode_raw(pString, 3);
|
|
if (!utf8_is_valid_scalar(ch, 3))
|
|
{
|
|
return UNI_EOF;
|
|
}
|
|
}
|
|
else if (4 == t)
|
|
{
|
|
if ( '\0' == pString[1]
|
|
|| '\0' == pString[2]
|
|
|| '\0' == pString[3]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[pString[1]]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[pString[2]]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[pString[3]])
|
|
{
|
|
return UNI_EOF;
|
|
}
|
|
ch = utf8_decode_raw(pString, 4);
|
|
if (!utf8_is_valid_scalar(ch, 4))
|
|
{
|
|
return UNI_EOF;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return UNI_EOF;
|
|
}
|
|
|
|
if (utf8_is_valid_scalar(ch, t))
|
|
{
|
|
return ch;
|
|
}
|
|
else
|
|
{
|
|
return UNI_EOF;
|
|
}
|
|
}
|
|
|
|
size_t ConvertFromUTF16(UTF16 *pString, UTF32 &ch)
|
|
{
|
|
ch = pString[0];
|
|
if ( ch < UNI_SUR_HIGH_START
|
|
|| UNI_SUR_LOW_END < ch)
|
|
{
|
|
// This is the most-common case.
|
|
//
|
|
return 1;
|
|
}
|
|
else if (ch <= UNI_SUR_HIGH_END)
|
|
{
|
|
UTF32 ch2 = pString[1];
|
|
if ( UNI_SUR_LOW_START <= ch2
|
|
&& ch2 <= UNI_SUR_LOW_END)
|
|
{
|
|
const int halfShift = 10;
|
|
const UTF32 halfBase = 0x0010000UL;
|
|
|
|
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
|
|
+ (ch2 - UNI_SUR_LOW_START)
|
|
+ halfBase;
|
|
return 2;
|
|
}
|
|
}
|
|
ch = UNI_EOF;
|
|
return 0;
|
|
}
|
|
|
|
UTF16 *ConvertFromUTF8ToUTF16(const UTF8 *pString, size_t& length)
|
|
{
|
|
static UTF16 buffer[2*LBUF_SIZE];
|
|
UTF16 *p = buffer;
|
|
UTF16 *const pEnd = buffer + sizeof(buffer) / sizeof(buffer[0]);
|
|
|
|
length = 0;
|
|
while ('\0' != *pString)
|
|
{
|
|
UTF32 ch = ConvertFromUTF8(pString);
|
|
if (UNI_EOF == ch)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
UTF16 *q = ConvertToUTF16(ch);
|
|
while (0x0000 != *q)
|
|
{
|
|
if (p + 1 >= pEnd)
|
|
{
|
|
return nullptr;
|
|
}
|
|
*p++ = *q++;
|
|
}
|
|
size_t nAdvance = utf8_FirstByte[static_cast<unsigned char>(*pString)];
|
|
if (nAdvance < 1 || nAdvance >= UTF8_CONTINUE)
|
|
{
|
|
return nullptr;
|
|
}
|
|
pString += nAdvance;
|
|
}
|
|
|
|
if (p >= pEnd)
|
|
{
|
|
return nullptr;
|
|
}
|
|
*p = '\0';
|
|
length = p - buffer;
|
|
return buffer;
|
|
}
|
|
|
|
// We want to remove mal-formed ESC sequences completely and convert the
|
|
// well-formed ones.
|
|
//
|
|
UTF8 *ConvertToUTF8(const char *p, size_t *pn)
|
|
{
|
|
*pn = 0;
|
|
|
|
static UTF8 aBuffer[LBUF_SIZE];
|
|
UTF8 *pBuffer = aBuffer;
|
|
|
|
while ('\0' != *p)
|
|
{
|
|
if (ESC_CHAR != *p)
|
|
{
|
|
const UTF8 *q = latin1_utf8[static_cast<unsigned char>(*p)];
|
|
utf8_safe_chr(q, aBuffer, &pBuffer);
|
|
p++;
|
|
}
|
|
else
|
|
{
|
|
// We have an ANSI sequence.
|
|
//
|
|
p++;
|
|
if ('[' == *p)
|
|
{
|
|
p++;
|
|
const char *q = p;
|
|
while (ANSI_TokenTerminatorTable[static_cast<unsigned char>(*q)] == 0)
|
|
{
|
|
q++;
|
|
}
|
|
|
|
if ('\0' != q[0])
|
|
{
|
|
// The segment [p,q) should contain a list of semi-color delimited codes.
|
|
//
|
|
const char *r = p;
|
|
while (r != q)
|
|
{
|
|
while ( r != q
|
|
&& ';' != r[0])
|
|
{
|
|
r++;
|
|
}
|
|
|
|
// The segment [p,r) should contain one code.
|
|
//
|
|
size_t n = r - p;
|
|
const UTF8 *s = nullptr;
|
|
switch (n)
|
|
{
|
|
case 1:
|
|
if ('0' == *p)
|
|
{
|
|
s = aColors[COLOR_INDEX_RESET].pUTF;
|
|
}
|
|
else if ('1' == *p)
|
|
{
|
|
s = aColors[COLOR_INDEX_INTENSE].pUTF;
|
|
}
|
|
else if ('4' == *p)
|
|
{
|
|
s = aColors[COLOR_INDEX_UNDERLINE].pUTF;
|
|
}
|
|
else if ('5' == *p)
|
|
{
|
|
s = aColors[COLOR_INDEX_BLINK].pUTF;
|
|
}
|
|
else if ('7' == *p)
|
|
{
|
|
s = aColors[COLOR_INDEX_INVERSE].pUTF;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if ('3' == *p)
|
|
{
|
|
unsigned int iCode = COLOR_INDEX_FG + (p[1] - '0');
|
|
if ( COLOR_INDEX_FG <= iCode
|
|
&& iCode < COLOR_INDEX_FG + 7)
|
|
{
|
|
s = aColors[iCode].pUTF;
|
|
}
|
|
}
|
|
else if ('4' == *p)
|
|
{
|
|
unsigned int iCode = COLOR_INDEX_BG + (p[1] - '0');
|
|
if ( COLOR_INDEX_BG <= iCode
|
|
&& iCode <= COLOR_INDEX_BG + 7)
|
|
{
|
|
s = aColors[iCode].pUTF;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (nullptr != s)
|
|
{
|
|
utf8_safe_chr(s, aBuffer, &pBuffer);
|
|
}
|
|
|
|
while ( r != q
|
|
&& ';' == r[0])
|
|
{
|
|
r++;
|
|
}
|
|
p = r;
|
|
}
|
|
|
|
// Eat trailing terminator.
|
|
//
|
|
p = q + 1;
|
|
}
|
|
else
|
|
{
|
|
// Skip to end of mal-formed ANSI sequence.
|
|
//
|
|
p = q;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*pBuffer = '\0';
|
|
*pn = pBuffer - aBuffer;
|
|
return aBuffer;
|
|
}
|
|
|
|
// mux_strncpy: Copies up to specified number of chars from source.
|
|
// Note: unlike strncpy(), this null-terminates after copying.
|
|
//
|
|
void mux_strncpy(UTF8 *dest, const UTF8 *src, size_t length_to_copy)
|
|
{
|
|
size_t i = 0;
|
|
if ( nullptr != src
|
|
|| length_to_copy < 0)
|
|
{
|
|
while ( i < length_to_copy
|
|
&& '\0' != src[i])
|
|
{
|
|
dest[i] = src[i];
|
|
i++;
|
|
}
|
|
}
|
|
dest[i] = '\0';
|
|
}
|
|
|
|
bool matches_exit_from_list(const UTF8 *str, const UTF8 *pattern)
|
|
{
|
|
const UTF8 *s;
|
|
|
|
while (*pattern)
|
|
{
|
|
// Compare str against this exit name, code-point-at-a-time
|
|
// (Unicode-aware).
|
|
//
|
|
s = str;
|
|
while ( *s
|
|
&& *pattern
|
|
&& *pattern != EXIT_DELIMITER)
|
|
{
|
|
UTF8 la[4], lb[4];
|
|
size_t na, nb;
|
|
|
|
bool bXorA;
|
|
const string_desc *qA = mux_tolower(s, bXorA);
|
|
if (nullptr == qA)
|
|
{
|
|
na = utf8_FirstByte[static_cast<unsigned char>(*s)];
|
|
if (na >= UTF8_CONTINUE) na = 1;
|
|
for (size_t j = 0; j < na; j++) la[j] = s[j];
|
|
}
|
|
else
|
|
{
|
|
na = qA->n_bytes;
|
|
if (bXorA)
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = s[j] ^ qA->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = qA->p[j];
|
|
}
|
|
}
|
|
|
|
bool bXorB;
|
|
const string_desc *qB = mux_tolower(pattern, bXorB);
|
|
if (nullptr == qB)
|
|
{
|
|
nb = utf8_FirstByte[static_cast<unsigned char>(*pattern)];
|
|
if (nb >= UTF8_CONTINUE) nb = 1;
|
|
for (size_t j = 0; j < nb; j++) lb[j] = pattern[j];
|
|
}
|
|
else
|
|
{
|
|
nb = qB->n_bytes;
|
|
if (bXorB)
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = pattern[j] ^ qB->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = qB->p[j];
|
|
}
|
|
}
|
|
|
|
if (na != nb)
|
|
{
|
|
break;
|
|
}
|
|
bool bEqual = true;
|
|
for (size_t j = 0; j < na; j++)
|
|
{
|
|
if (la[j] != lb[j])
|
|
{
|
|
bEqual = false;
|
|
break;
|
|
}
|
|
}
|
|
if (!bEqual)
|
|
{
|
|
break;
|
|
}
|
|
|
|
s += na;
|
|
pattern += nb;
|
|
}
|
|
|
|
// Did we match it all?
|
|
//
|
|
if (*s == '\0')
|
|
{
|
|
// Make sure nothing afterwards
|
|
//
|
|
while (mux_isspace(*pattern))
|
|
{
|
|
pattern++;
|
|
}
|
|
|
|
// Did we get it?
|
|
//
|
|
if ( !*pattern
|
|
|| (*pattern == EXIT_DELIMITER))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
// We didn't get it, find next string to test
|
|
//
|
|
while ( *pattern
|
|
&& *pattern++ != EXIT_DELIMITER)
|
|
{
|
|
; // Nothing.
|
|
}
|
|
while (mux_isspace(*pattern))
|
|
{
|
|
pattern++;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void string_token::set_source(UTF8* source_arg)
|
|
{
|
|
source = source_arg;
|
|
}
|
|
|
|
void string_token::set_control(const UTF8* control_arg)
|
|
{
|
|
memset(control, 0, sizeof(control));
|
|
|
|
// The '\0' character is always a control character.
|
|
//
|
|
control[0] = true;
|
|
|
|
// Record the user-specified control characters.
|
|
//
|
|
while (*control_arg)
|
|
{
|
|
control[static_cast<unsigned char>(*control_arg)] = 1;
|
|
control_arg++;
|
|
}
|
|
}
|
|
|
|
UTF8* string_token::parse_length(size_t* length)
|
|
{
|
|
*length = 0;
|
|
UTF8 *p = source;
|
|
if (!p)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
// Skip over leading control characters except for the NUL character.
|
|
//
|
|
while (control[static_cast<unsigned char>(*p)] && *p)
|
|
{
|
|
p++;
|
|
}
|
|
|
|
UTF8 *pReturn = p;
|
|
|
|
// Skip over non-control characters.
|
|
//
|
|
while (control[static_cast<unsigned char>(*p)] == 0)
|
|
{
|
|
p++;
|
|
}
|
|
|
|
// What is the length of this token?
|
|
//
|
|
*length = p - pReturn;
|
|
|
|
// Terminate the token with a NUL.
|
|
//
|
|
if (p[0])
|
|
{
|
|
// We found a non-NUL delimiter, so the next call will begin parsing
|
|
// on the character after this one.
|
|
//
|
|
source = p+1;
|
|
}
|
|
else
|
|
{
|
|
// We hit the end of the string, so the end of the string is where
|
|
// the next call will begin.
|
|
//
|
|
source = p;
|
|
}
|
|
|
|
// Did we find a token?
|
|
//
|
|
if (*length > 0)
|
|
{
|
|
return pReturn;
|
|
}
|
|
else
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
UTF8* string_token::parse()
|
|
{
|
|
size_t nLen;
|
|
UTF8 *p = parse_length(&nLen);
|
|
if (p)
|
|
{
|
|
p[nLen] = '\0';
|
|
}
|
|
return p;
|
|
}
|
|
|
|
mux_field StripTabsAndTruncate
|
|
(
|
|
const UTF8 *pString,
|
|
UTF8 *pBuffer,
|
|
size_t nLength,
|
|
size_t nWidth0
|
|
)
|
|
{
|
|
mux_field fldOutput(0, 0);
|
|
|
|
if ( nullptr == pBuffer
|
|
|| nullptr == pString
|
|
|| 0 == nLength
|
|
|| 0 == nWidth0
|
|
|| '\0' == pString[0])
|
|
{
|
|
if ( nullptr != pBuffer
|
|
&& 0 < nLength)
|
|
{
|
|
pBuffer[0] = '\0';
|
|
}
|
|
return fldOutput;
|
|
}
|
|
|
|
LBUF_OFFSET nWidth = static_cast<LBUF_OFFSET>(nWidth0);
|
|
if (nLength < nWidth)
|
|
{
|
|
nWidth = static_cast<LBUF_OFFSET>(nLength);
|
|
}
|
|
|
|
mux_cursor curPos(0, 0);
|
|
mux_field fldLimit(nLength, nWidth);
|
|
|
|
mux_field fldTransition(0, 0);
|
|
mux_field fldNormal(0, 0);
|
|
const UTF8 *pTransition = nullptr, *pNormal = nullptr;
|
|
size_t nNormalBytes = 0, nTransition = 0;
|
|
ColorState csCurrent = CS_NORMAL, csNext = CS_NORMAL;
|
|
|
|
while ('\0' != pString[curPos.m_byte])
|
|
{
|
|
int iCode = mux_color(pString + curPos.m_byte);
|
|
size_t nPointBytes = utf8_FirstByte[static_cast<unsigned char>(pString[curPos.m_byte])];
|
|
if (nPointBytes >= UTF8_CONTINUE)
|
|
{
|
|
nPointBytes = UTF8_SIZE1;
|
|
}
|
|
if (nPointBytes > nLength - curPos.m_byte)
|
|
{
|
|
nPointBytes = nLength - curPos.m_byte;
|
|
}
|
|
if (0 == nPointBytes)
|
|
{
|
|
break;
|
|
}
|
|
mux_cursor curPoint(static_cast<LBUF_OFFSET>(nPointBytes), 1);
|
|
if (COLOR_NOTCOLOR != iCode)
|
|
{
|
|
csNext = UpdateColorState(csNext, iCode, pString + curPos.m_byte);
|
|
}
|
|
else if (nullptr == strchr("\r\n\t", pString[curPos.m_byte]))
|
|
{
|
|
int nPointWidth = ConsoleWidth(pString + curPos.m_byte);
|
|
mux_field fldPoint(static_cast<LBUF_OFFSET>(nPointBytes), static_cast<LBUF_OFFSET>(nPointWidth));
|
|
if (csCurrent != csNext)
|
|
{
|
|
pTransition = ColorTransitionBinary(csCurrent, csNext, &nTransition);
|
|
pNormal = ColorBinaryNormal(csNext, &nNormalBytes);
|
|
fldNormal(nNormalBytes, 0);
|
|
}
|
|
else
|
|
{
|
|
nTransition = 0;
|
|
}
|
|
fldTransition(nTransition, 0);
|
|
if (fldOutput + fldTransition + fldPoint + fldNormal <= fldLimit)
|
|
{
|
|
if (0 < nTransition)
|
|
{
|
|
memcpy(pBuffer + fldOutput.m_byte, pTransition, nTransition);
|
|
csCurrent = csNext;
|
|
}
|
|
fldOutput += fldTransition;
|
|
|
|
for (size_t j = 0; j < fldPoint.m_byte; j++)
|
|
{
|
|
pBuffer[fldOutput.m_byte + j] = pString[curPos.m_byte + j];
|
|
}
|
|
fldOutput += fldPoint;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
curPos += curPoint;
|
|
}
|
|
|
|
if (csCurrent != csNext)
|
|
{
|
|
pNormal = ColorBinaryNormal(csCurrent, &nNormalBytes);
|
|
fldNormal(nNormalBytes, 0);
|
|
}
|
|
|
|
if ( 0 < nNormalBytes
|
|
&& fldOutput + fldNormal <= fldLimit)
|
|
{
|
|
memcpy(pBuffer + fldOutput.m_byte, pNormal, nNormalBytes);
|
|
fldOutput += fldNormal;
|
|
}
|
|
|
|
pBuffer[fldOutput.m_byte] = '\0';
|
|
return fldOutput;
|
|
}
|
|
|
|
// TruncateToBuffer()
|
|
//
|
|
// pString is parsed into alternating runs of text and color. These runs are
|
|
// then encoded into the given buffer with proper truncation. Every run of
|
|
// text will be of the same color. The color is collapsed into the minimal
|
|
// expression necessary to change from the color of the last run of text to
|
|
// the color of the next run of text. The initial color state and last color
|
|
// state are both CS_NORMAL.
|
|
//
|
|
// Parsing runs of text: As long as mux_color() returns COLOR_NOTCOLOR, we are
|
|
// in a run of text.
|
|
//
|
|
// Parsing runs of color: As long as mux_color() returns something besides
|
|
// COLOR_NOTCOLOR, we are in a run of color code points and use
|
|
// UpdateColorState() to merge the color code point into the current color
|
|
// state.
|
|
//
|
|
// It is sometimes not necessary to parse the entire string. Once we truncate
|
|
// a run of text, we know that no runs of text after the truncated one will
|
|
// fit either.
|
|
//
|
|
// The initial state is { CS_NORMAL, "" }. In turn, new runs of text,
|
|
// { CS(i), TEXT(i) } are encoded. To encode { CS(i+1), TEXT(i+1) } on the
|
|
// end of { CS(i), TEXT(i) }, we use ColorTransitionBinary(CS(i), CS(i+1), ...)
|
|
// and ColorBinaryNormal(CS(i+1), ...) to determine the two transitions. If
|
|
// there isn't enough room remaining in the buffer for these transitions,
|
|
// TEXT(i+1), TEXT(i+1) is truncated until there is room. If TEXT(i+1) is
|
|
// truncated to zero, neither color transition nor any of TEXT(i+1) is used.
|
|
//
|
|
size_t TruncateToBuffer
|
|
(
|
|
const UTF8 *pString,
|
|
UTF8 *pBuffer,
|
|
size_t nBuffer
|
|
)
|
|
{
|
|
size_t nOutput = 0;
|
|
|
|
if ( nullptr == pBuffer
|
|
|| nullptr == pString
|
|
|| 0 == nBuffer
|
|
|| '\0' == pString[0])
|
|
{
|
|
if (nullptr != pBuffer)
|
|
{
|
|
pBuffer[0] = '\0';
|
|
}
|
|
return nOutput;
|
|
}
|
|
|
|
size_t nNormal;
|
|
const UTF8 *pNormal;
|
|
|
|
ColorState csLast = CS_NORMAL;
|
|
ColorState csCurrent = CS_NORMAL;
|
|
|
|
bool bText = false;
|
|
const UTF8 *p = pString;
|
|
bool bTruncated = false;
|
|
while ( '\0' != p[0]
|
|
&& !bTruncated)
|
|
{
|
|
// Parse a run of color code points.
|
|
//
|
|
int iCode;
|
|
while ( ( UTF8_SIZE3 == utf8_FirstByte[p[0]]
|
|
|| UTF8_SIZE4 == utf8_FirstByte[p[0]])
|
|
&& COLOR_NOTCOLOR != (iCode = mux_color(p)))
|
|
{
|
|
csCurrent = UpdateColorState(csCurrent, iCode, p);
|
|
size_t nAdvance = utf8_advance_nul(p);
|
|
if (0 == nAdvance)
|
|
{
|
|
break;
|
|
}
|
|
p += nAdvance;
|
|
}
|
|
|
|
// Parse a run of text. A run of text is always ended by '\0' and
|
|
// sometimes by '\xEF' since all color code points start with '\xEF'.
|
|
//
|
|
bText = false;
|
|
size_t nTextRun = 0;
|
|
const UTF8 *pTextRun = p;
|
|
for (;;)
|
|
{
|
|
const UTF8 *pEF, *pF3;
|
|
if (nullptr != (pEF = reinterpret_cast<const UTF8 *>(strchr(reinterpret_cast<const char *>(p), '\xEF'))))
|
|
{
|
|
nTextRun += pEF - p;
|
|
p = pEF;
|
|
if (COLOR_NOTCOLOR != mux_color(p))
|
|
{
|
|
break;
|
|
}
|
|
size_t nAdvance = utf8_advance_nul(p);
|
|
nTextRun += nAdvance;
|
|
p += nAdvance;
|
|
}
|
|
else if (nullptr != (pF3 = reinterpret_cast<const UTF8 *>(strchr(reinterpret_cast<const char *>(p), '\xF3'))))
|
|
{
|
|
nTextRun += pF3 - p;
|
|
p = pF3;
|
|
if (COLOR_NOTCOLOR != mux_color(p))
|
|
{
|
|
break;
|
|
}
|
|
size_t nAdvance = utf8_advance_nul(p);
|
|
nTextRun += nAdvance;
|
|
p += nAdvance;
|
|
}
|
|
else
|
|
{
|
|
size_t n = strlen(reinterpret_cast<const char *>(p));
|
|
nTextRun += n;
|
|
p += n;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// We have either reached a color code point or end of the string.
|
|
// We have seen { csCurrent, (nTextRun, pTextRun) }. Before we parse
|
|
// further, we need to encode this into the destination buffer.
|
|
// There is a color transition, then a possibly truncated run of text
|
|
// followed by another color transition to CS_NORMAL. We won't lay
|
|
// anything down unless there is room for at least one character of
|
|
// the text.
|
|
//
|
|
if (0 < nTextRun)
|
|
{
|
|
// Calculate the two transitions.
|
|
//
|
|
size_t nTransition;
|
|
const UTF8 *pTransition = ColorTransitionBinary(csLast, csCurrent, &nTransition);
|
|
pNormal = ColorBinaryNormal(csCurrent, &nNormal);
|
|
|
|
size_t nMinChar = utf8_advance_nul(pTextRun);
|
|
if (0 == nMinChar)
|
|
{
|
|
nMinChar = 1;
|
|
}
|
|
if (nOutput + nTransition + nMinChar + nNormal <= nBuffer)
|
|
{
|
|
// Lay down the initial color transition.
|
|
//
|
|
if (0 < nTransition)
|
|
{
|
|
memcpy(pBuffer + nOutput, pTransition, nTransition);
|
|
nOutput += nTransition;
|
|
csLast = csCurrent;
|
|
}
|
|
|
|
if ( nBuffer < nOutput + nTextRun + nNormal
|
|
&& nOutput + nNormal <= nBuffer)
|
|
{
|
|
// We need to truncate the text.
|
|
//
|
|
nTextRun = nBuffer - (nOutput + nNormal);
|
|
while ( 0 < nTextRun
|
|
&& UTF8_CONTINUE <= utf8_FirstByte[pTextRun[nTextRun]])
|
|
{
|
|
nTextRun--;
|
|
}
|
|
bTruncated = true;
|
|
}
|
|
|
|
// Lay down text.
|
|
//
|
|
bText = true;
|
|
memcpy(pBuffer + nOutput, pTextRun, nTextRun);
|
|
nOutput += nTextRun;
|
|
|
|
// We have left room for the transition to CS_NORMAL, but it
|
|
// isn't laid down.
|
|
//
|
|
}
|
|
}
|
|
}
|
|
|
|
pNormal = ColorBinaryNormal((bText)?csCurrent:csLast, &nNormal);
|
|
if ( 0 < nNormal
|
|
&& nOutput + nNormal <= nBuffer)
|
|
{
|
|
memcpy(pBuffer + nOutput, pNormal, nNormal);
|
|
nOutput += nNormal;
|
|
}
|
|
|
|
pBuffer[nOutput] = '\0';
|
|
return nOutput;
|
|
}
|
|
|
|
mux_field PadField( UTF8 *pBuffer, size_t nMaxBytes, LBUF_OFFSET nMinWidth,
|
|
mux_field fldOutput)
|
|
{
|
|
if (nullptr == pBuffer)
|
|
{
|
|
return fldMin;
|
|
}
|
|
|
|
while ( fldOutput.m_byte < nMaxBytes
|
|
&& fldOutput.m_column < nMinWidth)
|
|
{
|
|
pBuffer[fldOutput.m_byte] = static_cast<UTF8>(' ');
|
|
fldOutput += fldAscii;
|
|
}
|
|
if (fldOutput.m_byte <= nMaxBytes)
|
|
{
|
|
pBuffer[fldOutput.m_byte] = '\0';
|
|
}
|
|
return fldOutput;
|
|
}
|
|
|
|
void ItemToList_Init(ITL *p, UTF8 *arg_buff, UTF8 **arg_bufc,
|
|
UTF8 arg_chPrefix, UTF8 arg_chSep)
|
|
{
|
|
p->bFirst = true;
|
|
p->chPrefix = arg_chPrefix;
|
|
p->chSep = arg_chSep;
|
|
p->buff = arg_buff;
|
|
p->bufc = arg_bufc;
|
|
p->nBufferAvailable = LBUF_SIZE - (*arg_bufc - arg_buff) - 1;
|
|
}
|
|
|
|
bool ItemToList_AddInteger(ITL *pContext, int i)
|
|
{
|
|
UTF8 smbuf[SBUF_SIZE];
|
|
UTF8 *p = smbuf;
|
|
if ( !pContext->bFirst
|
|
&& pContext->chSep)
|
|
{
|
|
*p++ = pContext->chSep;
|
|
}
|
|
if (pContext->chPrefix)
|
|
{
|
|
*p++ = pContext->chPrefix;
|
|
}
|
|
p += mux_ltoa(i, p);
|
|
size_t nLen = p - smbuf;
|
|
if ( pContext->nBufferAvailable < nLen
|
|
|| sizeof(smbuf) < nLen)
|
|
{
|
|
// Out of room.
|
|
//
|
|
return false;
|
|
}
|
|
if (pContext->bFirst)
|
|
{
|
|
pContext->bFirst = false;
|
|
}
|
|
memcpy(*(pContext->bufc), smbuf, nLen);
|
|
*(pContext->bufc) += nLen;
|
|
pContext->nBufferAvailable -= nLen;
|
|
return true;
|
|
}
|
|
|
|
bool ItemToList_AddInteger64(ITL *pContext, int64_t i64)
|
|
{
|
|
UTF8 smbuf[SBUF_SIZE];
|
|
UTF8 *p = smbuf;
|
|
if ( !pContext->bFirst
|
|
&& pContext->chSep)
|
|
{
|
|
*p++ = pContext->chSep;
|
|
}
|
|
if (pContext->chPrefix)
|
|
{
|
|
*p++ = pContext->chPrefix;
|
|
}
|
|
p += mux_i64toa(i64, p);
|
|
size_t nLen = p - smbuf;
|
|
if ( pContext->nBufferAvailable < nLen
|
|
|| sizeof(smbuf) < nLen)
|
|
{
|
|
// Out of room.
|
|
//
|
|
return false;
|
|
}
|
|
if (pContext->bFirst)
|
|
{
|
|
pContext->bFirst = false;
|
|
}
|
|
memcpy(*(pContext->bufc), smbuf, nLen);
|
|
*(pContext->bufc) += nLen;
|
|
pContext->nBufferAvailable -= nLen;
|
|
return true;
|
|
}
|
|
|
|
bool ItemToList_AddStringLEN(ITL *pContext, size_t nStr, const UTF8 *pStr)
|
|
{
|
|
size_t nLen = nStr;
|
|
if ( !pContext->bFirst
|
|
&& pContext->chSep)
|
|
{
|
|
nLen++;
|
|
}
|
|
if (pContext->chPrefix)
|
|
{
|
|
nLen++;
|
|
}
|
|
if (nLen > pContext->nBufferAvailable)
|
|
{
|
|
// Out of room.
|
|
//
|
|
return false;
|
|
}
|
|
UTF8 *p = *(pContext->bufc);
|
|
if (pContext->bFirst)
|
|
{
|
|
pContext->bFirst = false;
|
|
}
|
|
else if (pContext->chSep)
|
|
{
|
|
*p++ = pContext->chSep;
|
|
}
|
|
if (pContext->chPrefix)
|
|
{
|
|
*p++ = pContext->chPrefix;
|
|
}
|
|
memcpy(p, pStr, nStr);
|
|
*(pContext->bufc) += nLen;
|
|
pContext->nBufferAvailable -= nLen;
|
|
return true;
|
|
}
|
|
|
|
bool ItemToList_AddString(ITL *pContext, const UTF8 *pStr)
|
|
{
|
|
size_t nStr = strlen(reinterpret_cast<const char *>(pStr));
|
|
return ItemToList_AddStringLEN(pContext, nStr, pStr);
|
|
}
|
|
|
|
void ItemToList_Final(ITL *pContext)
|
|
{
|
|
**(pContext->bufc) = '\0';
|
|
}
|
|
|
|
// mux_stricmp - Compare two strings ignoring case.
|
|
//
|
|
int mux_stricmp(const UTF8 *a, const UTF8 *b)
|
|
{
|
|
// ASCII fast path: compare via tolower table without entering
|
|
// the Unicode state machine. Falls through to the full path
|
|
// when a non-ASCII byte is encountered.
|
|
//
|
|
while (*a && *b && *a < 0x80 && *b < 0x80)
|
|
{
|
|
unsigned char la = mux_tolower_ascii[*a];
|
|
unsigned char lb = mux_tolower_ascii[*b];
|
|
if (la != lb)
|
|
{
|
|
return (la < lb) ? -1 : 1;
|
|
}
|
|
a++;
|
|
b++;
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
if ('\0' == *a || '\0' == *b)
|
|
{
|
|
// Compare terminating bytes.
|
|
//
|
|
if (*a < *b) return -1;
|
|
if (*a > *b) return 1;
|
|
return 0;
|
|
}
|
|
|
|
// Get lowercased bytes for each code point.
|
|
//
|
|
UTF8 la[4], lb[4];
|
|
size_t na, nb;
|
|
|
|
bool bXorA;
|
|
const string_desc *qA = mux_tolower(a, bXorA);
|
|
if (nullptr == qA)
|
|
{
|
|
na = utf8_FirstByte[static_cast<unsigned char>(*a)];
|
|
if (na >= UTF8_CONTINUE) na = 1;
|
|
for (size_t j = 0; j < na; j++) la[j] = a[j];
|
|
}
|
|
else
|
|
{
|
|
na = qA->n_bytes;
|
|
if (bXorA)
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = a[j] ^ qA->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = qA->p[j];
|
|
}
|
|
}
|
|
|
|
bool bXorB;
|
|
const string_desc *qB = mux_tolower(b, bXorB);
|
|
if (nullptr == qB)
|
|
{
|
|
nb = utf8_FirstByte[static_cast<unsigned char>(*b)];
|
|
if (nb >= UTF8_CONTINUE) nb = 1;
|
|
for (size_t j = 0; j < nb; j++) lb[j] = b[j];
|
|
}
|
|
else
|
|
{
|
|
nb = qB->n_bytes;
|
|
if (bXorB)
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = b[j] ^ qB->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = qB->p[j];
|
|
}
|
|
}
|
|
|
|
// Compare the lowercased code-point bytes.
|
|
//
|
|
size_t nMin = (na < nb) ? na : nb;
|
|
for (size_t j = 0; j < nMin; j++)
|
|
{
|
|
if (la[j] < lb[j]) return -1;
|
|
if (la[j] > lb[j]) return 1;
|
|
}
|
|
if (na < nb) return -1;
|
|
if (na > nb) return 1;
|
|
|
|
a += na;
|
|
b += nb;
|
|
}
|
|
}
|
|
|
|
// mux_memicmp - Compare two buffers ignoring case (Unicode-aware).
|
|
// Bounded by byte count n from each buffer.
|
|
//
|
|
int mux_memicmp(const void *p1_arg, const void *p2_arg, size_t n)
|
|
{
|
|
const UTF8 *p1 = reinterpret_cast<const UTF8 *>(p1_arg);
|
|
const UTF8 *p2 = reinterpret_cast<const UTF8 *>(p2_arg);
|
|
const UTF8 *p1End = p1 + n;
|
|
const UTF8 *p2End = p2 + n;
|
|
|
|
while (p1 < p1End && p2 < p2End)
|
|
{
|
|
UTF8 la[4], lb[4];
|
|
size_t na, nb;
|
|
|
|
size_t remA = static_cast<size_t>(p1End - p1);
|
|
size_t srcA = utf8_FirstByte[static_cast<unsigned char>(*p1)];
|
|
if (srcA >= UTF8_CONTINUE)
|
|
{
|
|
srcA = UTF8_SIZE1;
|
|
}
|
|
bool bValidA = (srcA <= remA);
|
|
if (bValidA)
|
|
{
|
|
for (size_t i = 1; i < srcA; i++)
|
|
{
|
|
if (UTF8_CONTINUE != utf8_FirstByte[static_cast<unsigned char>(p1[i])])
|
|
{
|
|
bValidA = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!bValidA)
|
|
{
|
|
srcA = UTF8_SIZE1;
|
|
}
|
|
UTF8 cpA[5];
|
|
for (size_t j = 0; j < srcA; j++)
|
|
{
|
|
cpA[j] = p1[j];
|
|
}
|
|
cpA[srcA] = '\0';
|
|
|
|
bool bXorA;
|
|
const string_desc *qA = bValidA ? mux_tolower(cpA, bXorA) : nullptr;
|
|
if (nullptr == qA)
|
|
{
|
|
na = srcA;
|
|
for (size_t j = 0; j < na; j++) la[j] = cpA[j];
|
|
}
|
|
else
|
|
{
|
|
na = qA->n_bytes;
|
|
if (bXorA && na > srcA)
|
|
{
|
|
na = srcA;
|
|
}
|
|
if (na > remA)
|
|
{
|
|
na = remA;
|
|
}
|
|
if (bXorA)
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = cpA[j] ^ qA->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < na; j++) la[j] = qA->p[j];
|
|
}
|
|
}
|
|
|
|
size_t remB = static_cast<size_t>(p2End - p2);
|
|
size_t srcB = utf8_FirstByte[static_cast<unsigned char>(*p2)];
|
|
if (srcB >= UTF8_CONTINUE)
|
|
{
|
|
srcB = UTF8_SIZE1;
|
|
}
|
|
bool bValidB = (srcB <= remB);
|
|
if (bValidB)
|
|
{
|
|
for (size_t i = 1; i < srcB; i++)
|
|
{
|
|
if (UTF8_CONTINUE != utf8_FirstByte[static_cast<unsigned char>(p2[i])])
|
|
{
|
|
bValidB = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!bValidB)
|
|
{
|
|
srcB = UTF8_SIZE1;
|
|
}
|
|
UTF8 cpB[5];
|
|
for (size_t j = 0; j < srcB; j++)
|
|
{
|
|
cpB[j] = p2[j];
|
|
}
|
|
cpB[srcB] = '\0';
|
|
|
|
bool bXorB;
|
|
const string_desc *qB = bValidB ? mux_tolower(cpB, bXorB) : nullptr;
|
|
if (nullptr == qB)
|
|
{
|
|
nb = srcB;
|
|
for (size_t j = 0; j < nb; j++) lb[j] = cpB[j];
|
|
}
|
|
else
|
|
{
|
|
nb = qB->n_bytes;
|
|
if (bXorB && nb > srcB)
|
|
{
|
|
nb = srcB;
|
|
}
|
|
if (nb > remB)
|
|
{
|
|
nb = remB;
|
|
}
|
|
if (bXorB)
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = cpB[j] ^ qB->p[j];
|
|
}
|
|
else
|
|
{
|
|
for (size_t j = 0; j < nb; j++) lb[j] = qB->p[j];
|
|
}
|
|
}
|
|
|
|
size_t nMin = (na < nb) ? na : nb;
|
|
for (size_t j = 0; j < nMin; j++)
|
|
{
|
|
if (la[j] < lb[j]) return -1;
|
|
if (la[j] > lb[j]) return 1;
|
|
}
|
|
if (na < nb) return -1;
|
|
if (na > nb) return 1;
|
|
|
|
p1 += na;
|
|
p2 += nb;
|
|
}
|
|
|
|
if (p1 < p1End) return 1;
|
|
if (p2 < p2End) return -1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
// mux_strlwr - Convert string to all lower case.
|
|
//
|
|
UTF8 *mux_strlwr(const UTF8 *a, size_t &n)
|
|
{
|
|
static UTF8 Buffer[LBUF_SIZE];
|
|
|
|
n = 0;
|
|
while ('\0' != *a)
|
|
{
|
|
size_t j;
|
|
size_t src = utf8_FirstByte[static_cast<unsigned char>(*a)];
|
|
if (src >= UTF8_CONTINUE)
|
|
{
|
|
src = UTF8_SIZE1;
|
|
}
|
|
else
|
|
{
|
|
for (j = 1; j < src; j++)
|
|
{
|
|
if ( '\0' == a[j]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[static_cast<unsigned char>(a[j])])
|
|
{
|
|
src = UTF8_SIZE1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t out = src;
|
|
bool bXor;
|
|
const string_desc *qDesc = mux_tolower(a, bXor);
|
|
if (nullptr == qDesc)
|
|
{
|
|
if (LBUF_SIZE-1 < n + out)
|
|
{
|
|
break;
|
|
}
|
|
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = a[j];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
out = qDesc->n_bytes;
|
|
if ( bXor
|
|
&& out != src)
|
|
{
|
|
out = src;
|
|
qDesc = nullptr;
|
|
bXor = false;
|
|
}
|
|
if (LBUF_SIZE-1 < n + out)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (nullptr == qDesc)
|
|
{
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = a[j];
|
|
}
|
|
}
|
|
else if (bXor)
|
|
{
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = a[j] ^ qDesc->p[j];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = qDesc->p[j];
|
|
}
|
|
}
|
|
}
|
|
n += out;
|
|
a += src;
|
|
}
|
|
Buffer[n] = '\0';
|
|
return Buffer;
|
|
}
|
|
|
|
// mux_strupr - Convert string to all upper case.
|
|
//
|
|
UTF8 *mux_strupr(const UTF8 *a, size_t &n)
|
|
{
|
|
static UTF8 Buffer[LBUF_SIZE];
|
|
|
|
n = 0;
|
|
while ('\0' != *a)
|
|
{
|
|
size_t j;
|
|
size_t src = utf8_FirstByte[static_cast<unsigned char>(*a)];
|
|
if (src >= UTF8_CONTINUE)
|
|
{
|
|
src = UTF8_SIZE1;
|
|
}
|
|
else
|
|
{
|
|
for (j = 1; j < src; j++)
|
|
{
|
|
if ( '\0' == a[j]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[static_cast<unsigned char>(a[j])])
|
|
{
|
|
src = UTF8_SIZE1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t out = src;
|
|
bool bXor;
|
|
const string_desc *qDesc = mux_toupper(a, bXor);
|
|
if (nullptr == qDesc)
|
|
{
|
|
if (LBUF_SIZE-1 < n + out)
|
|
{
|
|
break;
|
|
}
|
|
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = a[j];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
out = qDesc->n_bytes;
|
|
if ( bXor
|
|
&& out != src)
|
|
{
|
|
out = src;
|
|
qDesc = nullptr;
|
|
bXor = false;
|
|
}
|
|
if (LBUF_SIZE-1 < n + out)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (nullptr == qDesc)
|
|
{
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = a[j];
|
|
}
|
|
}
|
|
else if (bXor)
|
|
{
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = a[j] ^ qDesc->p[j];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = qDesc->p[j];
|
|
}
|
|
}
|
|
}
|
|
n += out;
|
|
a += src;
|
|
}
|
|
Buffer[n] = '\0';
|
|
return Buffer;
|
|
}
|
|
|
|
// mux_toupper_first - Uppercase the first UTF-8 code point in-place in a
|
|
// buffer. buff points to the first byte to transform, bufc points to the
|
|
// current end-of-data pointer, nBufferTotal is the total buffer size.
|
|
//
|
|
// For XOR transforms (same byte length), overwrites in place.
|
|
// For literal transforms (may change byte length), shifts the remaining
|
|
// buffer contents via memmove and adjusts *bufc.
|
|
//
|
|
void mux_toupper_first(UTF8 *buff, UTF8 **bufc, size_t nBufferTotal)
|
|
{
|
|
if ( nullptr == buff
|
|
|| nullptr == bufc
|
|
|| nullptr == *bufc
|
|
|| nBufferTotal < 1
|
|
|| buff >= *bufc
|
|
|| '\0' == *buff)
|
|
{
|
|
return;
|
|
}
|
|
|
|
size_t nOld = utf8_FirstByte[static_cast<unsigned char>(*buff)];
|
|
if (nOld >= UTF8_CONTINUE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Validate that we have enough bytes.
|
|
//
|
|
size_t nUsed = *bufc - buff;
|
|
if (nOld > nUsed)
|
|
{
|
|
return;
|
|
}
|
|
for (size_t j = 1; j < nOld; j++)
|
|
{
|
|
if ( j >= nUsed
|
|
|| UTF8_CONTINUE != utf8_FirstByte[static_cast<unsigned char>(buff[j])])
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool bXor;
|
|
const string_desc *qDesc = mux_toupper(buff, bXor);
|
|
if (nullptr == qDesc)
|
|
{
|
|
// No transform for this code point — already uppercase or not a letter.
|
|
//
|
|
return;
|
|
}
|
|
|
|
size_t nNew = qDesc->n_bytes;
|
|
|
|
if (bXor)
|
|
{
|
|
// XOR transform: same byte length, overwrite in place.
|
|
//
|
|
if ( nNew != nOld
|
|
|| nNew > nUsed)
|
|
{
|
|
return;
|
|
}
|
|
for (size_t j = 0; j < nNew; j++)
|
|
{
|
|
buff[j] ^= qDesc->p[j];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Literal transform: byte length may differ.
|
|
//
|
|
size_t nTail = nUsed - nOld;
|
|
|
|
// Check that the result fits in the buffer.
|
|
//
|
|
size_t nBufferEnd = nBufferTotal - 1;
|
|
size_t nBuffStart = buff - (*bufc - nUsed); // offset of buff from buffer start
|
|
if (nBuffStart + nNew + nTail > nBufferEnd)
|
|
{
|
|
// Would overflow — truncate by not transforming.
|
|
//
|
|
return;
|
|
}
|
|
|
|
// Shift the tail to make room (or shrink).
|
|
//
|
|
if (nNew != nOld)
|
|
{
|
|
memmove(buff + nNew, buff + nOld, nTail + 1); // +1 for NUL
|
|
*bufc += (nNew - nOld);
|
|
}
|
|
|
|
// Write the transformed bytes.
|
|
//
|
|
for (size_t j = 0; j < nNew; j++)
|
|
{
|
|
buff[j] = qDesc->p[j];
|
|
}
|
|
}
|
|
}
|
|
|
|
// mux_foldmatch - alias for matching.
|
|
//
|
|
UTF8 *mux_foldmatch(const UTF8 *a, size_t &n, bool &fChanged)
|
|
{
|
|
static UTF8 Buffer[LBUF_SIZE];
|
|
|
|
n = 0;
|
|
fChanged = false;
|
|
while ('\0' != *a)
|
|
{
|
|
size_t j;
|
|
size_t src = utf8_FirstByte[static_cast<unsigned char>(*a)];
|
|
if (src >= UTF8_CONTINUE)
|
|
{
|
|
src = UTF8_SIZE1;
|
|
}
|
|
else
|
|
{
|
|
for (j = 1; j < src; j++)
|
|
{
|
|
if ( '\0' == a[j]
|
|
|| UTF8_CONTINUE != utf8_FirstByte[static_cast<unsigned char>(a[j])])
|
|
{
|
|
src = UTF8_SIZE1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t out = src;
|
|
bool bXor;
|
|
const string_desc *qDesc = mux_foldmatch(a, bXor);
|
|
if (nullptr == qDesc)
|
|
{
|
|
if (LBUF_SIZE-1 < n + out)
|
|
{
|
|
break;
|
|
}
|
|
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = a[j];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
out = qDesc->n_bytes;
|
|
if ( bXor
|
|
&& out != src)
|
|
{
|
|
out = src;
|
|
qDesc = nullptr;
|
|
bXor = false;
|
|
}
|
|
if (LBUF_SIZE-1 < n + out)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (nullptr == qDesc)
|
|
{
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = a[j];
|
|
}
|
|
}
|
|
else if (bXor)
|
|
{
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = a[j] ^ qDesc->p[j];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (j = 0; j < out; j++)
|
|
{
|
|
Buffer[n+j] = qDesc->p[j];
|
|
}
|
|
}
|
|
fChanged = true;
|
|
}
|
|
n += out;
|
|
a += src;
|
|
}
|
|
Buffer[n] = '\0';
|
|
return Buffer;
|
|
}
|
|
|
|
// Render a double in printf's %f / %e / %g shapes using David M. Gay's dtoa
|
|
// for the digits.
|
|
//
|
|
// Not snprintf: this keeps float rendering on the same correctly-rounded
|
|
// digit generator the rest of the tree already uses (mux_ftoa, fval,
|
|
// NearestPretty all go through mux_dtoa), rather than making output depend on
|
|
// the host libc. mux_ftoa itself is not usable here -- it is MUX's own float
|
|
// rendering and switches to exponent form once the decimal point passes 18,
|
|
// which %f never does.
|
|
//
|
|
// dtoa gives digits and a decimal-point position with trailing zeros
|
|
// suppressed, so the padding back out to the requested precision is ours.
|
|
// decpt == 9999 signals Inf/NaN.
|
|
//
|
|
// Returns the length written, or 0 with *pbOverflow set when the result will
|
|
// not fit nScratch. The caller treats that as truncation; before %f was
|
|
// implemented at all this path was a mux_assert(0), so truncating is strictly
|
|
// an improvement on aborting the process.
|
|
//
|
|
#define MUX_FLOAT_SCRATCH 512
|
|
|
|
static size_t mux_format_double(UTF8 *pScratch, size_t nScratch, double dval,
|
|
UTF8 chConv, int nPrec, bool *pbOverflow)
|
|
{
|
|
*pbOverflow = false;
|
|
|
|
bool bUpper = ( 'F' == chConv
|
|
|| 'E' == chConv
|
|
|| 'G' == chConv);
|
|
UTF8 chLower = static_cast<UTF8>(bUpper ? chConv - 'A' + 'a' : chConv);
|
|
|
|
int decpt = 0;
|
|
int bNeg = 0;
|
|
UTF8 *rve = nullptr;
|
|
UTF8 *pDigits = nullptr;
|
|
|
|
// %g selects between %e and %f on the exponent, so it has to see the
|
|
// significant digits before it can choose.
|
|
//
|
|
int nSig = 0;
|
|
if ('g' == chLower)
|
|
{
|
|
nSig = (0 == nPrec) ? 1 : nPrec;
|
|
pDigits = mux_dtoa(dval, 2, nSig, &decpt, &bNeg, &rve);
|
|
}
|
|
else if ('e' == chLower)
|
|
{
|
|
pDigits = mux_dtoa(dval, 2, nPrec + 1, &decpt, &bNeg, &rve);
|
|
}
|
|
else
|
|
{
|
|
pDigits = mux_dtoa(dval, 3, nPrec, &decpt, &bNeg, &rve);
|
|
}
|
|
|
|
if (nullptr == pDigits)
|
|
{
|
|
*pbOverflow = true;
|
|
return 0;
|
|
}
|
|
|
|
size_t nDigits = static_cast<size_t>(rve - pDigits);
|
|
size_t q = 0;
|
|
|
|
// Inf and NaN. printf spells these "inf"/"nan", uppercased for the
|
|
// uppercase conversions; a sign is carried on infinity only.
|
|
//
|
|
if (9999 == decpt)
|
|
{
|
|
const char *pWord = ('n' == pDigits[0] || 'N' == pDigits[0]) ? "nan" : "inf";
|
|
if ( bNeg
|
|
&& 'i' == pWord[0])
|
|
{
|
|
pScratch[q++] = '-';
|
|
}
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
pScratch[q++] = static_cast<UTF8>(bUpper ? pWord[i] - 'a' + 'A' : pWord[i]);
|
|
}
|
|
pScratch[q] = '\0';
|
|
return q;
|
|
}
|
|
|
|
// dtoa returns nothing for zero. Treat it as a single '0' digit sitting
|
|
// just left of the point, which is what the assembly below expects.
|
|
//
|
|
UTF8 chZero = '0';
|
|
if (0 == nDigits)
|
|
{
|
|
pDigits = &chZero;
|
|
nDigits = 1;
|
|
decpt = 1;
|
|
}
|
|
|
|
// Resolve %g to whichever of %e / %f it renders as. C's rule: use %e
|
|
// when the exponent is below -4 or at least the precision.
|
|
//
|
|
bool bStripTrailing = false;
|
|
int nExp = decpt - 1;
|
|
if ('g' == chLower)
|
|
{
|
|
bStripTrailing = true;
|
|
if ( nExp < -4
|
|
|| nSig <= nExp)
|
|
{
|
|
chLower = 'e';
|
|
nPrec = nSig - 1;
|
|
}
|
|
else
|
|
{
|
|
chLower = 'f';
|
|
nPrec = nSig - 1 - nExp;
|
|
if (nPrec < 0)
|
|
{
|
|
nPrec = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Worst case is %f of DBL_MAX: ~309 integer digits, plus the point, plus
|
|
// the precision. Bail rather than overrun.
|
|
//
|
|
size_t nWorst = (('f' == chLower) ? (decpt > 0 ? static_cast<size_t>(decpt) : 1)
|
|
: 1)
|
|
+ static_cast<size_t>(nPrec) + 16;
|
|
if (nScratch <= nWorst)
|
|
{
|
|
*pbOverflow = true;
|
|
return 0;
|
|
}
|
|
|
|
if (bNeg)
|
|
{
|
|
pScratch[q++] = '-';
|
|
}
|
|
|
|
// %g suppresses trailing zeros, but only inside the fraction: the strip
|
|
// must never reach back into the integer digits, or "%.1g" of 0 renders
|
|
// as the empty string instead of "0". iDot records where the fraction
|
|
// begins; bDot says whether there is one at all.
|
|
//
|
|
size_t iDot = 0;
|
|
bool bDot = false;
|
|
|
|
if ('e' == chLower)
|
|
{
|
|
pScratch[q++] = pDigits[0];
|
|
if (0 < nPrec)
|
|
{
|
|
iDot = q;
|
|
bDot = true;
|
|
pScratch[q++] = '.';
|
|
for (int i = 0; i < nPrec; i++)
|
|
{
|
|
size_t k = static_cast<size_t>(i) + 1;
|
|
pScratch[q++] = (k < nDigits) ? pDigits[k] : '0';
|
|
}
|
|
}
|
|
if ( bStripTrailing
|
|
&& bDot)
|
|
{
|
|
while ( iDot + 1 < q
|
|
&& '0' == pScratch[q-1]) q--;
|
|
if (iDot + 1 == q) q = iDot;
|
|
}
|
|
pScratch[q++] = static_cast<UTF8>(bUpper ? 'E' : 'e');
|
|
int nShow = nExp;
|
|
pScratch[q++] = static_cast<UTF8>((nShow < 0) ? '-' : '+');
|
|
if (nShow < 0) nShow = -nShow;
|
|
if (nShow < 10)
|
|
{
|
|
pScratch[q++] = '0';
|
|
pScratch[q++] = static_cast<UTF8>('0' + nShow);
|
|
}
|
|
else
|
|
{
|
|
q += mux_ltoa(nShow, pScratch + q);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Integer part.
|
|
//
|
|
if (decpt <= 0)
|
|
{
|
|
pScratch[q++] = '0';
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < decpt; i++)
|
|
{
|
|
size_t k = static_cast<size_t>(i);
|
|
pScratch[q++] = (k < nDigits) ? pDigits[k] : '0';
|
|
}
|
|
}
|
|
|
|
if (0 < nPrec)
|
|
{
|
|
iDot = q;
|
|
bDot = true;
|
|
pScratch[q++] = '.';
|
|
for (int i = 0; i < nPrec; i++)
|
|
{
|
|
int k = decpt + i;
|
|
pScratch[q++] = ( 0 <= k
|
|
&& static_cast<size_t>(k) < nDigits)
|
|
? pDigits[static_cast<size_t>(k)] : '0';
|
|
}
|
|
}
|
|
|
|
if ( bStripTrailing
|
|
&& bDot)
|
|
{
|
|
while ( iDot + 1 < q
|
|
&& '0' == pScratch[q-1]) q--;
|
|
if (iDot + 1 == q) q = iDot;
|
|
}
|
|
}
|
|
|
|
pScratch[q] = '\0';
|
|
return q;
|
|
}
|
|
|
|
// mux_vsnprintf - Is an sprintf-like function that will not overflow
|
|
// a buffer of specific size. The size is give by count, and count
|
|
// should be chosen to include the '\0' termination.
|
|
//
|
|
// Returns: A number from 0 to count-1 that is the string length of
|
|
// the returned (possibly truncated) buffer.
|
|
//
|
|
size_t DCL_CDECL mux_vsnprintf(UTF8 *pBuffer, size_t nBuffer, const UTF8 *pFmt, va_list va)
|
|
{
|
|
if ( nullptr == pBuffer
|
|
|| nBuffer < 1)
|
|
{
|
|
return 0;
|
|
}
|
|
size_t nLimit = nBuffer-1;
|
|
|
|
// Rather than copy a character at a time, some copies are deferred and performed in a single request.
|
|
//
|
|
size_t iFmtDeferred = 0;
|
|
size_t dDeferred = 0;
|
|
|
|
size_t iBuffer = 0;
|
|
size_t ncpFmt;
|
|
size_t iFmt = 0;
|
|
if ( nullptr != pFmt
|
|
&& utf8_strlen(pFmt, ncpFmt))
|
|
{
|
|
// Octal needs 22 digits for a 64-bit value plus the terminator, one
|
|
// more than I64BUF_SIZE allows for decimal. Floating point does not
|
|
// use this buffer at all -- see the 'f'/'e'/'g' branch, which formats
|
|
// straight into the output.
|
|
//
|
|
static UTF8 Buff[I64BUF_SIZE + 8];
|
|
|
|
while (0 != ncpFmt)
|
|
{
|
|
if ('%' != pFmt[iFmt])
|
|
{
|
|
// Ordinary character.
|
|
//
|
|
size_t d = utf8_FirstByte[pFmt[iFmt]];
|
|
size_t dProposed = dDeferred + d;
|
|
if (nLimit < iBuffer + dProposed)
|
|
{
|
|
if (0 < dDeferred)
|
|
{
|
|
// Unravel the deferred copy.
|
|
//
|
|
memcpy(pBuffer + iBuffer, pFmt + iFmtDeferred, dDeferred);
|
|
iBuffer += dDeferred;
|
|
dDeferred = 0;
|
|
}
|
|
goto done;
|
|
}
|
|
else if (0 == dDeferred)
|
|
{
|
|
iFmtDeferred = iFmt;
|
|
}
|
|
dDeferred = dProposed;
|
|
|
|
iFmt += d;
|
|
ncpFmt--;
|
|
}
|
|
else
|
|
{
|
|
if (0 < dDeferred)
|
|
{
|
|
// Unravel the deferred copy.
|
|
//
|
|
memcpy(pBuffer + iBuffer, pFmt + iFmtDeferred, dDeferred);
|
|
iBuffer += dDeferred;
|
|
dDeferred = 0;
|
|
}
|
|
|
|
size_t cbBuff;
|
|
size_t cpBuff;
|
|
size_t nWidth = 0;
|
|
size_t nPrecision = 0;
|
|
bool bLeft = false;
|
|
bool bZeroPadded = false;
|
|
bool bWidth = false;
|
|
bool bSawPeriod = false;
|
|
bool bPrecision = false;
|
|
int nLongs = 0;
|
|
|
|
// Where this conversion spec starts, so an unimplemented one
|
|
// can be echoed literally rather than killing the process
|
|
// (#1429).
|
|
//
|
|
size_t iFmtSpec = iFmt;
|
|
|
|
iFmt++;
|
|
ncpFmt--;
|
|
|
|
while (0 != ncpFmt)
|
|
{
|
|
if ( 'd' == pFmt[iFmt]
|
|
|| 'i' == pFmt[iFmt]
|
|
|| 's' == pFmt[iFmt]
|
|
|| 'u' == pFmt[iFmt]
|
|
|| 'o' == pFmt[iFmt]
|
|
|| 'x' == pFmt[iFmt]
|
|
|| 'X' == pFmt[iFmt]
|
|
|| 'p' == pFmt[iFmt]
|
|
|| 'f' == pFmt[iFmt]
|
|
|| 'F' == pFmt[iFmt]
|
|
|| 'e' == pFmt[iFmt]
|
|
|| 'E' == pFmt[iFmt]
|
|
|| 'g' == pFmt[iFmt]
|
|
|| 'G' == pFmt[iFmt])
|
|
{
|
|
UTF8 *pBuff = Buff;
|
|
UTF8 FBuff[MUX_FLOAT_SCRATCH];
|
|
|
|
if ( 'd' == pFmt[iFmt]
|
|
|| 'i' == pFmt[iFmt])
|
|
{
|
|
// Obtain and validate argument.
|
|
//
|
|
if (0 == nLongs)
|
|
{
|
|
int i = va_arg(va, int);
|
|
cbBuff = cpBuff = mux_ltoa(i, Buff);
|
|
}
|
|
else if (1 == nLongs)
|
|
{
|
|
long int i = va_arg(va, long int);
|
|
cbBuff = cpBuff = mux_ltoa(i, Buff);
|
|
}
|
|
else if (2 == nLongs)
|
|
{
|
|
int64_t i = va_arg(va, int64_t);
|
|
cbBuff = cpBuff = mux_i64toa(i, Buff);
|
|
}
|
|
else
|
|
{
|
|
goto done;
|
|
}
|
|
}
|
|
else if ('s' == pFmt[iFmt])
|
|
{
|
|
// Obtain and validate argument.
|
|
//
|
|
pBuff = va_arg(va, UTF8 *);
|
|
if ( !utf8_strlen(pBuff, cpBuff)
|
|
|| 0 != nLongs)
|
|
{
|
|
goto done;
|
|
}
|
|
cbBuff = strlen(reinterpret_cast<char *>(pBuff));
|
|
|
|
if ( bPrecision
|
|
&& nPrecision < cpBuff)
|
|
{
|
|
// Need to walk cbBuff back to correspond to changes in cpBuff.
|
|
//
|
|
while (cpBuff != nPrecision)
|
|
{
|
|
do
|
|
{
|
|
cbBuff--;
|
|
} while (UTF8_CONTINUE <= utf8_FirstByte[pBuff[cbBuff]]);
|
|
cpBuff--;
|
|
}
|
|
}
|
|
}
|
|
else if ('p' == pFmt[iFmt])
|
|
{
|
|
if ( 0 != nLongs
|
|
|| bWidth)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
// Convert pointer to unsigned integer.
|
|
//
|
|
union
|
|
{
|
|
uintptr_t ui;
|
|
void *pv;
|
|
} u;
|
|
u.pv = va_arg(va, void *);
|
|
#if SIZEOF_UINT_PTR <= SIZEOF_UNSIGNED_LONG
|
|
cbBuff = cpBuff = mux_utox(u.ui, Buff, true);
|
|
#elif SIZEOF_UINT_PTR <= SIZEOF_UNSIGNED_LONG_LONG
|
|
cbBuff = cpBuff = mux_ui64tox(u.ui, Buff, true);
|
|
#else
|
|
#error Size of pointer is larger size of largest known integer.
|
|
#endif
|
|
bWidth = true;
|
|
nWidth = 2*sizeof(uintptr_t);
|
|
bZeroPadded = true;
|
|
}
|
|
else if ( 'f' == pFmt[iFmt]
|
|
|| 'F' == pFmt[iFmt]
|
|
|| 'e' == pFmt[iFmt]
|
|
|| 'E' == pFmt[iFmt]
|
|
|| 'g' == pFmt[iFmt]
|
|
|| 'G' == pFmt[iFmt])
|
|
{
|
|
// Floating point. Before this, %f and friends
|
|
// fell through to the mux_assert(0) below and took
|
|
// the process down -- a standard C conversion this
|
|
// function happened not to implement was a server
|
|
// abort with no warning at the call site (#1382,
|
|
// and again in @list).
|
|
//
|
|
// Digits come from mux_dtoa, the same correctly
|
|
// rounded generator mux_ftoa/fval/NearestPretty
|
|
// use, so float output does not depend on the host
|
|
// libc. nLongs is ignored: "%lf" is double in
|
|
// printf, and "%Lf" never reaches here because 'L'
|
|
// is not parsed as a length modifier.
|
|
//
|
|
double dval = va_arg(va, double);
|
|
int nPrec = bSawPeriod ? static_cast<int>(nPrecision) : 6;
|
|
|
|
bool bOverflow = false;
|
|
cbBuff = cpBuff = mux_format_double(FBuff,
|
|
sizeof(FBuff), dval, pFmt[iFmt], nPrec,
|
|
&bOverflow);
|
|
if (bOverflow)
|
|
{
|
|
goto done;
|
|
}
|
|
pBuff = FBuff;
|
|
}
|
|
else
|
|
{
|
|
bool bHex = ( 'x' == pFmt[iFmt]
|
|
|| 'X' == pFmt[iFmt]);
|
|
bool bOct = ('o' == pFmt[iFmt]);
|
|
bool bUpper = ('X' == pFmt[iFmt]);
|
|
|
|
// Obtain and validate argument.
|
|
//
|
|
if (0 == nLongs)
|
|
{
|
|
unsigned int ui = va_arg(va, unsigned int);
|
|
cbBuff = cpBuff = bOct?mux_utoo(ui, Buff):(bHex?mux_utox(ui, Buff, bUpper):mux_utoa(ui, Buff));
|
|
}
|
|
else if (1 == nLongs)
|
|
{
|
|
unsigned long int ui = va_arg(va, unsigned long int);
|
|
cbBuff = cpBuff = bOct?mux_utoo(ui, Buff):(bHex?mux_utox(ui, Buff, bUpper):mux_utoa(ui, Buff));
|
|
}
|
|
else if (2 == nLongs)
|
|
{
|
|
uint64_t ui = va_arg(va, uint64_t);
|
|
cbBuff = cpBuff = bOct?mux_ui64too(ui, Buff):(bHex?mux_ui64tox(ui, Buff, bUpper):mux_ui64toa(ui, Buff));
|
|
}
|
|
else
|
|
{
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
// Calculate and validate needed size. Numberic and
|
|
// string fields are at least the size of their width.
|
|
// String fields may have been truncated above by
|
|
// precision.
|
|
//
|
|
// Width is compared with the number of code points.
|
|
// Padding is always done with space or zero.
|
|
//
|
|
size_t nUsed = cbBuff;
|
|
size_t nPadding = 0;
|
|
if ( bWidth
|
|
&& cpBuff < nWidth)
|
|
{
|
|
nPadding = nWidth - cpBuff;
|
|
nUsed += nPadding;
|
|
}
|
|
|
|
if (nLimit < iBuffer + nUsed)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
// Apply leading padding if necessary.
|
|
//
|
|
if ( !bLeft
|
|
&& bWidth)
|
|
{
|
|
// Any signed conversion: the minus sign has to be
|
|
// laid down before zero-padding begins, or
|
|
// "%08.2f" of -3.5 renders as "0000-3.50".
|
|
//
|
|
if ( ( 'd' == pFmt[iFmt]
|
|
|| 'i' == pFmt[iFmt]
|
|
|| 'f' == pFmt[iFmt]
|
|
|| 'F' == pFmt[iFmt]
|
|
|| 'e' == pFmt[iFmt]
|
|
|| 'E' == pFmt[iFmt]
|
|
|| 'g' == pFmt[iFmt]
|
|
|| 'G' == pFmt[iFmt])
|
|
&& '-' == pBuff[0]
|
|
&& 0 < nPadding
|
|
&& bZeroPadded)
|
|
{
|
|
// The leading minus sign must be laid down before zero-padding begins.
|
|
//
|
|
pBuffer[iBuffer] = '-';
|
|
iBuffer++;
|
|
|
|
pBuff++;
|
|
cbBuff--;
|
|
cpBuff--;
|
|
}
|
|
|
|
while (0 < nPadding)
|
|
{
|
|
pBuffer[iBuffer] = bZeroPadded?'0':' ';
|
|
iBuffer++;
|
|
nPadding--;
|
|
}
|
|
}
|
|
|
|
// Apply string.
|
|
//
|
|
memcpy(pBuffer + iBuffer, pBuff, cbBuff);
|
|
iBuffer += cbBuff;
|
|
|
|
// Apply trailing padding if necessary.
|
|
//
|
|
if ( bLeft
|
|
&& bWidth)
|
|
{
|
|
while (0 < nPadding)
|
|
{
|
|
pBuffer[iBuffer] = bZeroPadded?'0':' ';
|
|
iBuffer++;
|
|
nPadding--;
|
|
}
|
|
}
|
|
|
|
iFmt++;
|
|
ncpFmt--;
|
|
break;
|
|
}
|
|
else if ('l' == pFmt[iFmt])
|
|
{
|
|
nLongs++;
|
|
iFmt++;
|
|
ncpFmt--;
|
|
}
|
|
else if ('z' == pFmt[iFmt])
|
|
{
|
|
// size_t/ssize_t length modifier. Map onto the
|
|
// existing nLongs tiers by actual width so both LP64
|
|
// (size_t == unsigned long) and LLP64 (size_t is
|
|
// 64-bit while long is 32-bit) marshal the va_arg
|
|
// type the caller actually pushed. Without this,
|
|
// "%zu" fell through to mux_assert(0) and aborted.
|
|
//
|
|
nLongs = (sizeof(size_t) == sizeof(unsigned long)) ? 1 : 2;
|
|
iFmt++;
|
|
ncpFmt--;
|
|
}
|
|
else if ( '0' <= pFmt[iFmt]
|
|
&& pFmt[iFmt] <= '9')
|
|
{
|
|
if (!bSawPeriod)
|
|
{
|
|
if (!bWidth)
|
|
{
|
|
if ('0' == pFmt[iFmt])
|
|
{
|
|
if (bZeroPadded)
|
|
{
|
|
goto done;
|
|
}
|
|
bZeroPadded = true;
|
|
}
|
|
else
|
|
{
|
|
nWidth = pFmt[iFmt] - '0';
|
|
bWidth = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nWidth = 10 * nWidth + pFmt[iFmt] - '0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!bPrecision)
|
|
{
|
|
nPrecision = pFmt[iFmt] - '0';
|
|
bPrecision = true;
|
|
}
|
|
else
|
|
{
|
|
nPrecision = 10 * nPrecision + pFmt[iFmt] - '0';
|
|
}
|
|
}
|
|
|
|
iFmt++;
|
|
ncpFmt--;
|
|
}
|
|
else if ('.' == pFmt[iFmt])
|
|
{
|
|
bSawPeriod = true;
|
|
|
|
iFmt++;
|
|
ncpFmt--;
|
|
}
|
|
else if ('-' == pFmt[iFmt])
|
|
{
|
|
if (bLeft)
|
|
{
|
|
goto done;
|
|
}
|
|
bLeft = true;
|
|
|
|
iFmt++;
|
|
ncpFmt--;
|
|
}
|
|
else if ('c' == pFmt[iFmt])
|
|
{
|
|
unsigned int ch = va_arg(va, unsigned int);
|
|
if (nLimit < iBuffer + 1)
|
|
{
|
|
goto done;
|
|
}
|
|
pBuffer[iBuffer] = static_cast<UTF8>(ch);
|
|
iBuffer++;
|
|
|
|
iFmt++;
|
|
ncpFmt--;
|
|
break;
|
|
}
|
|
else if ('%' == pFmt[iFmt])
|
|
{
|
|
// "%%"
|
|
//
|
|
if (nLimit < iBuffer + 1)
|
|
{
|
|
goto done;
|
|
}
|
|
pBuffer[iBuffer] = '%';
|
|
iBuffer++;
|
|
|
|
iFmt++;
|
|
ncpFmt--;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// An unimplemented conversion. This was mux_assert(0),
|
|
// which is a hard abort() in the shipping build --
|
|
// mux_assert has no NDEBUG guard -- so an ordinary
|
|
// looking T("%+d") took the whole game down. #1382
|
|
// produced two wizard-triggerable aborts exactly that
|
|
// way (@list cache and astbench), and both were fixed
|
|
// at the call site rather than here (#1429).
|
|
//
|
|
// Echo the remainder of the format verbatim and STOP
|
|
// interpreting. A bounded formatter already truncates
|
|
// when it runs out of room, so callers are written
|
|
// against "imperfect output" and not against "no
|
|
// server"; emitting the text rather than dropping it
|
|
// leaves the evidence visible without a debugger.
|
|
//
|
|
// Stopping is the part that is not optional. No
|
|
// va_arg was consumed for this spec, so every LATER
|
|
// conversion in the same format string would read the
|
|
// wrong argument, and there is no way to resynchronise
|
|
// without knowing what the unknown spec would have
|
|
// taken. Continuing was measured (#1445):
|
|
//
|
|
// "%+d|%d" 11, 22 -> "%+d|11" wrong arg
|
|
// "%+d|%s" 11, "tail" -> SIGSEGV
|
|
//
|
|
// The second hands an int to the %s path as a UTF8*
|
|
// and dereferences it. That trades a clean abort for
|
|
// a wild pointer, which is not an improvement -- so
|
|
// recovery stops at the first spec it cannot parse.
|
|
//
|
|
// Echoing the whole remainder rather than just this
|
|
// spec keeps the evidence intact: the offending spec
|
|
// appears in full, with the text that followed it,
|
|
// while nothing further is interpreted.
|
|
//
|
|
size_t nRest =
|
|
strlen(reinterpret_cast<const char *>(pFmt) + iFmtSpec);
|
|
if (nLimit < iBuffer + nRest)
|
|
{
|
|
nRest = nLimit - iBuffer;
|
|
}
|
|
memcpy(pBuffer + iBuffer, pFmt + iFmtSpec, nRest);
|
|
iBuffer += nRest;
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 < dDeferred)
|
|
{
|
|
// Unravel the deferred copy.
|
|
//
|
|
memcpy(pBuffer + iBuffer, pFmt + iFmtDeferred, dDeferred);
|
|
iBuffer += dDeferred;
|
|
dDeferred = 0;
|
|
}
|
|
}
|
|
|
|
done:
|
|
pBuffer[iBuffer] = '\0';
|
|
return iBuffer;
|
|
}
|
|
|
|
void DCL_CDECL mux_sprintf(UTF8 *buff, size_t count, const UTF8 *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
(void)mux_vsnprintf(buff, count, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
void DCL_CDECL mux_fprintf(FILE *fp, const UTF8 *fmt, ...)
|
|
{
|
|
if (nullptr != fp)
|
|
{
|
|
UTF8 Buffer[MBUF_SIZE];
|
|
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
size_t nBuffer = mux_vsnprintf(Buffer, sizeof(Buffer), fmt, ap);
|
|
va_end(ap);
|
|
|
|
fwrite(Buffer, 1, nBuffer, fp);
|
|
}
|
|
}
|
|
|
|
// This function acts like fgets except that any data on the end of the
|
|
// line past the buffer size is truncated instead of being returned on
|
|
// the next call.
|
|
//
|
|
size_t GetLineTrunc(UTF8 *Buffer, size_t nBuffer, FILE *fp)
|
|
{
|
|
size_t lenBuffer = 0;
|
|
if (fgets(reinterpret_cast<char *>(Buffer), static_cast<int>(nBuffer), fp))
|
|
{
|
|
lenBuffer = strlen(reinterpret_cast<char *>(Buffer));
|
|
}
|
|
if (lenBuffer <= 0)
|
|
{
|
|
memcpy(Buffer, "\n", 2);
|
|
return 1;
|
|
}
|
|
if (Buffer[lenBuffer-1] != '\n')
|
|
{
|
|
// The line was too long for the buffer. Continue reading until the
|
|
// end of the line.
|
|
//
|
|
UTF8 TruncBuffer[SBUF_SIZE];
|
|
size_t lenTruncBuffer;
|
|
do
|
|
{
|
|
if (!fgets(reinterpret_cast<char *>(TruncBuffer), sizeof(TruncBuffer), fp))
|
|
{
|
|
break;
|
|
}
|
|
lenTruncBuffer = strlen(reinterpret_cast<char *>(TruncBuffer));
|
|
}
|
|
while (TruncBuffer[lenTruncBuffer-1] != '\n');
|
|
}
|
|
return lenBuffer;
|
|
}
|
|
|
|
// Method: Boyer-Moore-Horspool
|
|
//
|
|
// This method is a simplification of the Boyer-Moore String Searching
|
|
// Algorithm, but a useful one. It does not require as much temporary
|
|
// storage, and the setup costs are not as high as the full Boyer-Moore.
|
|
//
|
|
// If we were searching megabytes of data instead of 8KB at most, then
|
|
// the full Boyer-Moore would make more sense.
|
|
//
|
|
#define BMH_LARGE 32767
|
|
void BMH_Prepare(BMH_State *bmhs, size_t nPat, const UTF8 *pPat)
|
|
{
|
|
if (nPat <= 0)
|
|
{
|
|
return;
|
|
}
|
|
size_t k;
|
|
for (k = 0; k < 256; k++)
|
|
{
|
|
bmhs->m_d[k] = nPat;
|
|
}
|
|
|
|
UTF8 chLastPat = pPat[nPat-1];
|
|
bmhs->m_skip2 = nPat;
|
|
for (k = 0; k < nPat - 1; k++)
|
|
{
|
|
bmhs->m_d[static_cast<unsigned char>(pPat[k])] = nPat - k - 1;
|
|
if (pPat[k] == chLastPat)
|
|
{
|
|
bmhs->m_skip2 = nPat - k - 1;
|
|
}
|
|
}
|
|
bmhs->m_d[static_cast<unsigned char>(chLastPat)] = BMH_LARGE;
|
|
}
|
|
|
|
bool BMH_Execute(BMH_State *bmhs, size_t *pnMatched, size_t nPat, const UTF8 *pPat, size_t nSrc, const UTF8 *pSrc)
|
|
{
|
|
if (nPat <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
for (size_t i = nPat-1; i < nSrc; i += bmhs->m_skip2)
|
|
{
|
|
while ((i += bmhs->m_d[static_cast<unsigned char>(pSrc[i])]) < nSrc)
|
|
{
|
|
; // Nothing.
|
|
}
|
|
if (i < BMH_LARGE)
|
|
{
|
|
break;
|
|
}
|
|
i -= BMH_LARGE;
|
|
int j = static_cast<int>(nPat - 1);
|
|
const UTF8 *s = pSrc + (i - j);
|
|
while (--j >= 0 && s[j] == pPat[j])
|
|
{
|
|
; // Nothing.
|
|
}
|
|
if (j < 0)
|
|
{
|
|
*pnMatched = s-pSrc;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool BMH_StringSearch(size_t *pnMatched, size_t nPat, const UTF8 *pPat, size_t nSrc, const UTF8 *pSrc)
|
|
{
|
|
BMH_State bmhs;
|
|
BMH_Prepare(&bmhs, nPat, pPat);
|
|
return BMH_Execute(&bmhs, pnMatched, nPat, pPat, nSrc, pSrc);
|
|
}
|
|
|
|
// BMH_PrepareI - Pre-lowercase the pattern with mux_strlwr() (Unicode-aware)
|
|
// and prepare the case-sensitive BMH state on the lowered pattern.
|
|
//
|
|
// Note: For XOR transforms (the vast majority), byte length is preserved so
|
|
// offsets map directly. For the ~24 rare literal transforms that change byte
|
|
// count, the offset in the lowered source may differ from the original.
|
|
// Callers (grepi) use the offset to extract from the original text, so the
|
|
// result is correct when byte length is preserved.
|
|
//
|
|
void BMH_PrepareI(BMH_State *bmhs, size_t nPat, const UTF8 *pPat)
|
|
{
|
|
size_t nLower;
|
|
UTF8 *pLower = mux_strlwr(pPat, nLower);
|
|
|
|
// Use a persistent buffer since BMH_Execute needs the pattern later.
|
|
//
|
|
static UTF8 LoweredPattern[LBUF_SIZE];
|
|
if (nLower >= LBUF_SIZE)
|
|
{
|
|
nLower = LBUF_SIZE - 1;
|
|
}
|
|
memcpy(LoweredPattern, pLower, nLower);
|
|
LoweredPattern[nLower] = '\0';
|
|
|
|
BMH_Prepare(bmhs, nLower, LoweredPattern);
|
|
}
|
|
|
|
bool BMH_ExecuteI(BMH_State *bmhs, size_t *pnMatched, size_t nPat, const UTF8 *pPat, size_t nSrc, const UTF8 *pSrc)
|
|
{
|
|
// Lowercase both pattern and source, then delegate to case-sensitive.
|
|
//
|
|
size_t nLowerPat;
|
|
UTF8 *pLowerPat = mux_strlwr(pPat, nLowerPat);
|
|
|
|
// mux_strlwr uses a static buffer, so copy the lowered pattern first.
|
|
//
|
|
LBuf LowPat = LBuf_Src("BMH_ExecuteI");
|
|
if (nLowerPat >= LBUF_SIZE) nLowerPat = LBUF_SIZE - 1;
|
|
memcpy(LowPat, pLowerPat, nLowerPat);
|
|
LowPat[nLowerPat] = '\0';
|
|
|
|
size_t nLowerSrc;
|
|
UTF8 *pLowerSrc = mux_strlwr(pSrc, nLowerSrc);
|
|
|
|
// Re-prepare BMH state with lowered pattern since the state from
|
|
// BMH_PrepareI may have been invalidated.
|
|
//
|
|
BMH_State bmhsLocal;
|
|
BMH_Prepare(&bmhsLocal, nLowerPat, LowPat);
|
|
return BMH_Execute(&bmhsLocal, pnMatched, nLowerPat, LowPat, nLowerSrc, pLowerSrc);
|
|
}
|
|
|
|
bool BMH_StringSearchI(size_t *pnMatched, size_t nPat, const UTF8 *pPat, size_t nSrc, const UTF8 *pSrc)
|
|
{
|
|
// Lowercase pattern and source, then use case-sensitive search.
|
|
//
|
|
size_t nLowerPat;
|
|
UTF8 *pLowerPat = mux_strlwr(pPat, nLowerPat);
|
|
|
|
LBuf LowPat = LBuf_Src("BMH_StringSearchI");
|
|
if (nLowerPat >= LBUF_SIZE) nLowerPat = LBUF_SIZE - 1;
|
|
memcpy(LowPat, pLowerPat, nLowerPat);
|
|
LowPat[nLowerPat] = '\0';
|
|
|
|
size_t nLowerSrc;
|
|
UTF8 *pLowerSrc = mux_strlwr(pSrc, nLowerSrc);
|
|
|
|
return BMH_StringSearch(pnMatched, nLowerPat, LowPat, nLowerSrc, pLowerSrc);
|
|
}
|
|
|
|
// find_pattern_delimiter - Find the first ':' in a $-command or ^-listen
|
|
// pattern that is not part of a '::' escape. A '::' pair represents a literal
|
|
// ':' in the pattern (useful for regexp non-capturing groups, etc.). Returns
|
|
// a pointer to the delimiter ':', or nullptr if none is found.
|
|
//
|
|
UTF8 *find_pattern_delimiter(UTF8 *str)
|
|
{
|
|
UTF8 *p = str;
|
|
while (*p)
|
|
{
|
|
if (':' == *p)
|
|
{
|
|
if (':' == p[1])
|
|
{
|
|
p += 2;
|
|
continue;
|
|
}
|
|
return p;
|
|
}
|
|
p++;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// unescape_pattern_colons - Collapse '::' sequences to ':' in-place.
|
|
// Called on the pattern portion of a $-command or ^-listen after the
|
|
// delimiter has been found and the string split.
|
|
//
|
|
void unescape_pattern_colons(UTF8 *str)
|
|
{
|
|
UTF8 *r = str;
|
|
UTF8 *w = str;
|
|
while (*r)
|
|
{
|
|
if (':' == r[0] && ':' == r[1])
|
|
{
|
|
*w++ = ':';
|
|
r += 2;
|
|
continue;
|
|
}
|
|
*w++ = *r++;
|
|
}
|
|
*w = '\0';
|
|
}
|
|
|
|
// strip_fancy_quotes - Replace Unicode smart/curly quotes with ASCII equivalents
|
|
// in-place. The string can only shrink (3-byte UTF-8 sequences become 1 byte),
|
|
// so no additional buffer is needed.
|
|
//
|
|
// U+201C / U+201D (left/right double quotation mark) -> "
|
|
// U+2018 / U+2019 (left/right single quotation mark) -> '
|
|
//
|
|
void strip_fancy_quotes(UTF8 *str)
|
|
{
|
|
UTF8 *r = str;
|
|
UTF8 *w = str;
|
|
while (*r)
|
|
{
|
|
if ( 0xE2 == r[0]
|
|
&& 0x80 == r[1])
|
|
{
|
|
if (0x9C == r[2] || 0x9D == r[2])
|
|
{
|
|
*w++ = '"';
|
|
r += 3;
|
|
continue;
|
|
}
|
|
else if (0x98 == r[2] || 0x99 == r[2])
|
|
{
|
|
*w++ = '\'';
|
|
r += 3;
|
|
continue;
|
|
}
|
|
}
|
|
*w++ = *r++;
|
|
}
|
|
*w = '\0';
|
|
}
|
|
|
|
bool mux_fopen(FILE **pFile, const UTF8 *filename, const UTF8 *mode)
|
|
{
|
|
if (pFile)
|
|
{
|
|
*pFile = nullptr;
|
|
if ( nullptr != filename
|
|
&& nullptr != mode)
|
|
{
|
|
#if defined(WINDOWS_FILES) && !defined(__INTEL_COMPILER) && (_MSC_VER >= 1400)
|
|
// 1400 is Visual C++ 2005
|
|
//
|
|
return (fopen_s(pFile, reinterpret_cast<const char *>(filename), reinterpret_cast<const char *>(mode)) == 0);
|
|
#else
|
|
*pFile = fopen(reinterpret_cast<const char *>(filename), reinterpret_cast<const char *>(mode));
|
|
if (nullptr != *pFile)
|
|
{
|
|
return true;
|
|
}
|
|
#endif // WINDOWS_FILES
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void mux_fclose(FILE *fp)
|
|
{
|
|
if (nullptr != fp)
|
|
{
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
bool mux_open(int *pfh, const UTF8 *filename, int oflag)
|
|
{
|
|
if (nullptr != pfh)
|
|
{
|
|
*pfh = MUX_OPEN_INVALID_HANDLE_VALUE;
|
|
if (nullptr != filename)
|
|
{
|
|
#if defined(WINDOWS_FILES) && !defined(__INTEL_COMPILER) && (_MSC_VER >= 1400)
|
|
// 1400 is Visual C++ 2005
|
|
//
|
|
return (_sopen_s(pfh, reinterpret_cast<const char *>(filename), oflag, _SH_DENYNO, _S_IREAD|_S_IWRITE) == 0);
|
|
#elif defined(WINDOWS_FILES)
|
|
*pfh = _open(reinterpret_cast<const char *>(filename), oflag, _S_IREAD|_S_IWRITE);
|
|
return (0 <= *pfh);
|
|
#else
|
|
*pfh = open(reinterpret_cast<const char *>(filename), oflag, 0600);
|
|
return (0 <= *pfh);
|
|
#endif
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const UTF8 *mux_strerror(int errnum)
|
|
{
|
|
#if defined(WINDOWS_FILES) && !defined(__INTEL_COMPILER) && (_MSC_VER >= 1400)
|
|
// 1400 is Visual C++ 2005
|
|
//
|
|
static UTF8 buffer[80];
|
|
strerror_s(reinterpret_cast<char *>(buffer), sizeof(buffer), errnum);
|
|
return buffer;
|
|
#else
|
|
return reinterpret_cast<UTF8 *>(strerror(errnum));
|
|
#endif
|
|
}
|
|
|
|
size_t LeftJustifyString(UTF8 *field, size_t nWidth, const UTF8 *value)
|
|
{
|
|
size_t n = strlen(reinterpret_cast<const char *>(value));
|
|
if (n > nWidth)
|
|
{
|
|
n = nWidth;
|
|
}
|
|
memcpy(field, value, n);
|
|
memset(field+n, ' ', nWidth-n);
|
|
return nWidth;
|
|
}
|
|
|
|
size_t RightJustifyNumber(UTF8 *field, size_t nWidth, int64_t value, UTF8 chFill)
|
|
{
|
|
UTF8 buffer[I64BUF_SIZE];
|
|
size_t nReturn = 0;
|
|
if (nWidth < sizeof(buffer))
|
|
{
|
|
size_t n = mux_i64toa(value, buffer);
|
|
if (n < sizeof(buffer))
|
|
{
|
|
nReturn = n;
|
|
if (n < nWidth)
|
|
{
|
|
memset(field, chFill, nWidth-n);
|
|
field += nWidth-n;
|
|
nReturn = nWidth;
|
|
}
|
|
memcpy(field, buffer, n);
|
|
}
|
|
}
|
|
return nReturn;
|
|
}
|
|
|
|
// ConvertCRLFtoSpace — replace CRLF sequences with spaces.
|
|
// Returns a pointer to a static buffer.
|
|
//
|
|
UTF8 *ConvertCRLFtoSpace(const UTF8 *pString)
|
|
{
|
|
static UTF8 buf[LBUF_SIZE];
|
|
UTF8 *bp = buf;
|
|
|
|
// Skip any leading CRLF.
|
|
//
|
|
while ( '\r' == *pString
|
|
|| '\n' == *pString)
|
|
{
|
|
pString++;
|
|
}
|
|
|
|
bool bFirst = true;
|
|
while (*pString)
|
|
{
|
|
if (!bFirst)
|
|
{
|
|
safe_chr(' ', buf, &bp);
|
|
}
|
|
else
|
|
{
|
|
bFirst = false;
|
|
}
|
|
|
|
while ( *pString
|
|
&& '\r' != *pString
|
|
&& '\n' != *pString)
|
|
{
|
|
safe_chr(*pString, buf, &bp);
|
|
pString++;
|
|
}
|
|
|
|
// Skip any CRLF.
|
|
//
|
|
while ( '\r' == *pString
|
|
|| '\n' == *pString)
|
|
{
|
|
pString++;
|
|
}
|
|
}
|
|
*bp = '\0';
|
|
return buf;
|
|
}
|