mirror of https://github.com/tstack/lnav.git
parent
db8a3c4d38
commit
f192cb7c3e
3
NEWS
3
NEWS
|
@ -20,6 +20,9 @@ lnav v0.9.1:
|
|||
* When copying log lines, the file name and time offset will be included
|
||||
in the copy if they are enabled.
|
||||
|
||||
Fixes:
|
||||
* Unicode text can now be entered in prompts.
|
||||
|
||||
lnav v0.9.0:
|
||||
Features:
|
||||
* Added support for themes and included a few as well: default, eldar,
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "base/lnav_log.hh"
|
||||
#include "base/string_util.hh"
|
||||
#include "base/intern_string.hh"
|
||||
|
||||
/**
|
||||
|
@ -464,6 +465,13 @@ public:
|
|||
return *this;
|
||||
};
|
||||
|
||||
attr_line_t &erase_utf8_chars(size_t start) {
|
||||
auto byte_index = utf8_char_to_byte_index(this->al_string, start);
|
||||
this->erase(byte_index);
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
attr_line_t &right_justify(unsigned long width) {
|
||||
long padding = width - this->length();
|
||||
if (padding > 0) {
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
#include "ww898/cp_utf8.hpp"
|
||||
|
||||
void scrub_to_utf8(char *buffer, size_t length);
|
||||
|
||||
inline bool is_line_ending(char ch) {
|
||||
|
@ -116,4 +118,20 @@ inline std::string toupper(const std::string &str)
|
|||
return toupper(str.c_str());
|
||||
}
|
||||
|
||||
inline ssize_t utf8_char_to_byte_index(const std::string &str, ssize_t ch_index)
|
||||
{
|
||||
ssize_t retval = 0;
|
||||
|
||||
while (ch_index > 0) {
|
||||
auto ch_len = ww898::utf::utf8::char_size([&str, retval]() {
|
||||
return str[retval];
|
||||
});
|
||||
|
||||
retval += ch_len;
|
||||
ch_index -= 1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,9 +50,12 @@
|
|||
#endif
|
||||
|
||||
#include "base/lnav_log.hh"
|
||||
#include "ww898/cp_utf8.hpp"
|
||||
#include "input_dispatcher.hh"
|
||||
#include "lnav_util.hh"
|
||||
|
||||
using namespace ww898;
|
||||
|
||||
template<typename A>
|
||||
static void to_key_seq(A &dst, const char *src)
|
||||
{
|
||||
|
@ -90,13 +93,9 @@ void input_dispatcher::new_input(const struct timeval ¤t_time, int ch)
|
|||
to_key_seq(keyseq, this->id_escape_buffer);
|
||||
switch (this->id_escape_matcher(keyseq.data())) {
|
||||
case escape_match_t::NONE: {
|
||||
if (this->id_escape_expected_size == -1) {
|
||||
for (int lpc = 0; this->id_escape_buffer[lpc]; lpc++) {
|
||||
handled = this->id_key_handler(
|
||||
this->id_escape_buffer[lpc]);
|
||||
}
|
||||
} else {
|
||||
handled = false;
|
||||
for (int lpc = 0; this->id_escape_buffer[lpc]; lpc++) {
|
||||
handled = this->id_key_handler(
|
||||
this->id_escape_buffer[lpc]);
|
||||
}
|
||||
this->id_escape_index = 0;
|
||||
break;
|
||||
|
@ -113,15 +112,15 @@ void input_dispatcher::new_input(const struct timeval ¤t_time, int ch)
|
|||
this->id_escape_index == this->id_escape_expected_size) {
|
||||
this->id_escape_index = 0;
|
||||
}
|
||||
} else if ((ch & 0xf8) == 0xf0) {
|
||||
this->reset_escape_buffer(ch, current_time, 4);
|
||||
} else if ((ch & 0xf0) == 0xe0) {
|
||||
this->reset_escape_buffer(ch, current_time, 3);
|
||||
} else if ((ch & 0xe0) == 0xc0) {
|
||||
this->reset_escape_buffer(ch, current_time, 2);
|
||||
} else {
|
||||
snprintf(keyseq.data(), keyseq.size(), "x%02x", ch & 0xff);
|
||||
handled = this->id_key_handler(ch);
|
||||
auto seq_size = utf::utf8::char_size([ch]() { return ch; });
|
||||
|
||||
if (seq_size == 1) {
|
||||
snprintf(keyseq.data(), keyseq.size(), "x%02x", ch & 0xff);
|
||||
handled = this->id_key_handler(ch);
|
||||
} else {
|
||||
this->reset_escape_buffer(ch, current_time, seq_size);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1471,16 +1471,19 @@ static void looper()
|
|||
auto encoded_name = (char *) alloca(enc_len);
|
||||
|
||||
log_info("unbound keyseq: %s", keyseq);
|
||||
json_ptr::encode(encoded_name, enc_len, lnav_config.lc_ui_keymap.c_str());
|
||||
json_ptr::encode(encoded_name, enc_len,
|
||||
lnav_config.lc_ui_keymap.c_str());
|
||||
// XXX we should have a hotkey for opening a prompt that is
|
||||
// pre-filled with a suggestion that the user can complete.
|
||||
// This quick-fix key could be used for other stuff as well
|
||||
lnav_data.ld_rl_view->set_value(fmt::format(
|
||||
ANSI_CSI ANSI_COLOR_PARAM(COLOR_YELLOW) ";" ANSI_BOLD_PARAM ANSI_CHAR_ATTR
|
||||
ANSI_CSI ANSI_COLOR_PARAM(COLOR_YELLOW)
|
||||
";" ANSI_BOLD_PARAM ANSI_CHAR_ATTR
|
||||
"Unrecognized key"
|
||||
ANSI_NORM
|
||||
", bind to a command using \u2014 "
|
||||
ANSI_BOLD(":config") " /ui/keymap-defs/{}/{}/command <cmd>",
|
||||
ANSI_BOLD(":config")
|
||||
" /ui/keymap-defs/{}/{}/command <cmd>",
|
||||
encoded_name, keyseq));
|
||||
alerter::singleton().chime();
|
||||
};
|
||||
|
|
|
@ -319,18 +319,12 @@ void view_curses::mvwattrline(WINDOW *window,
|
|||
break;
|
||||
|
||||
default: {
|
||||
int offset = 0;
|
||||
auto offset = 1 - (int) ww898::utf::utf8::char_size([ch]() {
|
||||
return ch;
|
||||
});
|
||||
|
||||
expanded_line[exp_index] = line[lpc];
|
||||
exp_index += 1;
|
||||
if ((ch & 0xf8) == 0xf0) {
|
||||
offset = -3;
|
||||
} else if ((ch & 0xf0) == 0xe0) {
|
||||
offset = -2;
|
||||
} else if ((ch & 0xe0) == 0xc0) {
|
||||
offset = -1;
|
||||
}
|
||||
|
||||
if (offset) {
|
||||
if (char_index < lr_chars.lr_start) {
|
||||
lr_bytes.lr_start += abs(offset);
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <map>
|
||||
|
@ -82,7 +81,7 @@ public:
|
|||
const char *operator[](int ch) const
|
||||
{
|
||||
map<int, const char *>::const_iterator iter;
|
||||
const char *retval = NULL;
|
||||
const char *retval = nullptr;
|
||||
|
||||
if ((iter = this->vem_map.find(ch)) != this->vem_map.end()) {
|
||||
retval = iter->second;
|
||||
|
@ -94,9 +93,9 @@ public:
|
|||
const char *operator[](const char *seq) const
|
||||
{
|
||||
map<string, const char *>::const_iterator iter;
|
||||
const char *retval = NULL;
|
||||
const char *retval = nullptr;
|
||||
|
||||
require(seq != NULL);
|
||||
require(seq != nullptr);
|
||||
|
||||
if ((iter = this->vem_input_map.find(seq)) !=
|
||||
this->vem_input_map.end()) {
|
||||
|
@ -114,7 +113,7 @@ private:
|
|||
static char area_buffer[1024];
|
||||
char * area = area_buffer;
|
||||
|
||||
if (tgetent(NULL, "vt52") == ERR) {
|
||||
if (tgetent(nullptr, "vt52") == ERR) {
|
||||
perror("tgetent");
|
||||
}
|
||||
this->vem_map[KEY_UP] = tgetstr((char *)"ku", &area);
|
||||
|
@ -122,7 +121,7 @@ private:
|
|||
this->vem_map[KEY_RIGHT] = tgetstr((char *)"kr", &area);
|
||||
this->vem_map[KEY_LEFT] = tgetstr((char *)"kl", &area);
|
||||
this->vem_map[KEY_HOME] = tgetstr((char *)"kh", &area);
|
||||
if (this->vem_map[KEY_HOME] == NULL) {
|
||||
if (this->vem_map[KEY_HOME] == nullptr) {
|
||||
this->vem_map[KEY_HOME] = "\x01";
|
||||
}
|
||||
this->vem_map[KEY_BACKSPACE] = "\010";
|
||||
|
@ -132,11 +131,11 @@ private:
|
|||
this->vem_map[KEY_END] = "\x05";
|
||||
|
||||
this->vem_map[KEY_SLEFT] = tgetstr((char *)"#4", &area);
|
||||
if (this->vem_map[KEY_SLEFT] == NULL) {
|
||||
if (this->vem_map[KEY_SLEFT] == nullptr) {
|
||||
this->vem_map[KEY_SLEFT] = "\033b";
|
||||
}
|
||||
this->vem_map[KEY_SRIGHT] = tgetstr((char *)"%i", &area);
|
||||
if (this->vem_map[KEY_SRIGHT] == NULL) {
|
||||
if (this->vem_map[KEY_SRIGHT] == nullptr) {
|
||||
this->vem_map[KEY_SRIGHT] = "\033f";
|
||||
}
|
||||
|
||||
|
@ -145,7 +144,7 @@ private:
|
|||
this->vem_input_map[tgetstr((char *)"ce", &area)] = "ce";
|
||||
this->vem_input_map[tgetstr((char *)"kl", &area)] = "kl";
|
||||
this->vem_input_map[tgetstr((char *)"kr", &area)] = "kr";
|
||||
tgetent(NULL, getenv("TERM"));
|
||||
tgetent(nullptr, getenv("TERM"));
|
||||
};
|
||||
|
||||
/** Map of ncurses keycodes to VT52 escape sequences. */
|
||||
|
@ -153,21 +152,12 @@ private:
|
|||
map<string, const char *> vem_input_map;
|
||||
};
|
||||
|
||||
vt52_curses::vt52_curses()
|
||||
: vc_window(NULL),
|
||||
vc_x(0),
|
||||
vc_y(0),
|
||||
vc_max_height(0),
|
||||
vc_escape_len(0),
|
||||
vc_map_buffer(0)
|
||||
{ }
|
||||
|
||||
const char *vt52_curses::map_input(int ch, int &len_out)
|
||||
{
|
||||
const char *esc, *retval;
|
||||
|
||||
/* Check for an escape sequence, otherwise just return the char. */
|
||||
if ((esc = vt52_escape_map::singleton()[ch]) != NULL) {
|
||||
if ((esc = vt52_escape_map::singleton()[ch]) != nullptr) {
|
||||
retval = esc;
|
||||
len_out = strlen(retval);
|
||||
}
|
||||
|
@ -182,7 +172,7 @@ const char *vt52_curses::map_input(int ch, int &len_out)
|
|||
len_out = 1;
|
||||
}
|
||||
|
||||
ensure(retval != NULL);
|
||||
ensure(retval != nullptr);
|
||||
ensure(len_out > 0);
|
||||
|
||||
return retval;
|
||||
|
@ -202,10 +192,26 @@ void vt52_curses::map_output(const char *output, int len)
|
|||
this->vc_escape_len += 1;
|
||||
this->vc_escape[this->vc_escape_len] = '\0';
|
||||
|
||||
if ((cap = vt52_escape_map::singleton()[this->vc_escape]) !=
|
||||
nullptr) {
|
||||
if (this->vc_expected_escape_len != -1) {
|
||||
if (this->vc_escape_len == this->vc_expected_escape_len) {
|
||||
auto& line_string = this->vc_line.get_string();
|
||||
auto x_byte_index = utf8_char_to_byte_index(line_string, this->vc_x);
|
||||
|
||||
for (int esc_index = 0; esc_index < this->vc_escape_len; esc_index++) {
|
||||
if (x_byte_index < this->vc_line.length()) {
|
||||
line_string[x_byte_index] = this->vc_escape[esc_index];
|
||||
} else {
|
||||
this->vc_line.append(1, this->vc_escape[esc_index]);
|
||||
}
|
||||
x_byte_index += 1;
|
||||
}
|
||||
this->vc_x += 1;
|
||||
this->vc_escape_len = 0;
|
||||
}
|
||||
} else if ((cap = vt52_escape_map::singleton()[this->vc_escape]) !=
|
||||
nullptr) {
|
||||
if (strcmp(cap, "ce") == 0) {
|
||||
this->vc_line.erase(this->vc_x);
|
||||
this->vc_line.erase_utf8_chars(this->vc_x);
|
||||
this->vc_escape_len = 0;
|
||||
}
|
||||
else if (strcmp(cap, "kl") == 0) {
|
||||
|
@ -222,7 +228,19 @@ void vt52_curses::map_output(const char *output, int len)
|
|||
}
|
||||
}
|
||||
else {
|
||||
switch (output[lpc]) {
|
||||
auto next_ch = output[lpc];
|
||||
auto seq_size = ww898::utf::utf8::char_size([next_ch]() {
|
||||
return next_ch;
|
||||
});
|
||||
|
||||
if (seq_size > 1) {
|
||||
this->vc_escape[0] = next_ch;
|
||||
this->vc_escape_len = 1;
|
||||
this->vc_expected_escape_len = seq_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (next_ch) {
|
||||
case STX:
|
||||
this->vc_x = 0;
|
||||
this->vc_line.clear();
|
||||
|
@ -239,6 +257,7 @@ void vt52_curses::map_output(const char *output, int len)
|
|||
case ESCAPE:
|
||||
this->vc_escape[0] = ESCAPE;
|
||||
this->vc_escape_len = 1;
|
||||
this->vc_expected_escape_len = -1;
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
|
@ -250,15 +269,19 @@ void vt52_curses::map_output(const char *output, int len)
|
|||
this->vc_x = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (this->vc_x < this->vc_line.length()) {
|
||||
this->vc_line.get_string()[this->vc_x] = output[lpc];
|
||||
default: {
|
||||
auto& line_string = this->vc_line.get_string();
|
||||
auto x_byte_index = utf8_char_to_byte_index(line_string, this->vc_x);
|
||||
|
||||
if (x_byte_index < this->vc_line.length()) {
|
||||
line_string[x_byte_index] = next_ch;
|
||||
} else {
|
||||
this->vc_line.append(1, output[lpc]);
|
||||
this->vc_line.append(1, next_ch);
|
||||
}
|
||||
this->vc_x += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -269,4 +292,5 @@ void vt52_curses::do_update()
|
|||
this->get_actual_y(), this->vc_left,
|
||||
this->vc_line,
|
||||
line_range{ 0, (int) this->vc_width });
|
||||
wmove(this->vc_window, this->get_actual_y(), this->vc_left + this->vc_x);
|
||||
}
|
||||
|
|
|
@ -54,8 +54,6 @@
|
|||
class vt52_curses
|
||||
: public view_curses {
|
||||
public:
|
||||
vt52_curses();
|
||||
|
||||
/** @param win The curses window this view is attached to. */
|
||||
void set_window(WINDOW *win) { this->vc_window = win; };
|
||||
|
||||
|
@ -145,14 +143,15 @@ protected:
|
|||
return retval;
|
||||
};
|
||||
|
||||
WINDOW *vc_window; /*< The window that contains this view. */
|
||||
WINDOW *vc_window{nullptr}; /*< The window that contains this view. */
|
||||
int vc_left{0};
|
||||
int vc_x; /*< The X position of the cursor. */
|
||||
int vc_y; /*< The Y position of the cursor. */
|
||||
int vc_max_height;
|
||||
int vc_x{0}; /*< The X position of the cursor. */
|
||||
int vc_y{0}; /*< The Y position of the cursor. */
|
||||
int vc_max_height{0};
|
||||
char vc_escape[16]; /*< Storage for escape sequences. */
|
||||
int vc_escape_len; /*< The number of chars in vc_escape. */
|
||||
char vc_map_buffer; /*<
|
||||
int vc_escape_len{0}; /*< The number of chars in vc_escape. */
|
||||
int vc_expected_escape_len{-1};
|
||||
char vc_map_buffer{0}; /*<
|
||||
* Buffer returned by map_input for trivial
|
||||
* translations (one-to-one).
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017-2019 Mikhail Pilin
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace ww898 {
|
||||
namespace utf {
|
||||
|
||||
// Supported combinations:
|
||||
// 0xxx_xxxx
|
||||
// 110x_xxxx 10xx_xxxx
|
||||
// 1110_xxxx 10xx_xxxx 10xx_xxxx
|
||||
// 1111_0xxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
// 1111_10xx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
// 1111_110x 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
struct utf8 final
|
||||
{
|
||||
static size_t const max_unicode_symbol_size = 4;
|
||||
static size_t const max_supported_symbol_size = 6;
|
||||
|
||||
static uint32_t const max_supported_code_point = 0x7FFFFFFF;
|
||||
|
||||
using char_type = uint8_t;
|
||||
|
||||
template<typename PeekFn>
|
||||
static size_t char_size(PeekFn && peek_fn)
|
||||
{
|
||||
char_type const ch0 = std::forward<PeekFn>(peek_fn)();
|
||||
if (ch0 < 0x80) // 0xxx_xxxx
|
||||
return 1;
|
||||
if (ch0 < 0xC0)
|
||||
throw std::runtime_error("The utf8 first char in sequence is incorrect");
|
||||
if (ch0 < 0xE0) // 110x_xxxx 10xx_xxxx
|
||||
return 2;
|
||||
if (ch0 < 0xF0) // 1110_xxxx 10xx_xxxx 10xx_xxxx
|
||||
return 3;
|
||||
if (ch0 < 0xF8) // 1111_0xxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
return 4;
|
||||
if (ch0 < 0xFC) // 1111_10xx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
return 5;
|
||||
if (ch0 < 0xFE) // 1111_110x 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
return 6;
|
||||
throw std::runtime_error("The utf8 first char in sequence is incorrect");
|
||||
}
|
||||
|
||||
template<typename ReadFn>
|
||||
static uint32_t read(ReadFn && read_fn)
|
||||
{
|
||||
char_type const ch0 = read_fn();
|
||||
if (ch0 < 0x80) // 0xxx_xxxx
|
||||
return ch0;
|
||||
if (ch0 < 0xC0)
|
||||
throw std::runtime_error("The utf8 first char in sequence is incorrect");
|
||||
if (ch0 < 0xE0) // 110x_xxxx 10xx_xxxx
|
||||
{
|
||||
char_type const ch1 = read_fn(); if (ch1 >> 6 != 2) goto _err;
|
||||
return (ch0 << 6) + ch1 - 0x3080;
|
||||
}
|
||||
if (ch0 < 0xF0) // 1110_xxxx 10xx_xxxx 10xx_xxxx
|
||||
{
|
||||
char_type const ch1 = read_fn(); if (ch1 >> 6 != 2) goto _err;
|
||||
char_type const ch2 = read_fn(); if (ch2 >> 6 != 2) goto _err;
|
||||
return (ch0 << 12) + (ch1 << 6) + ch2 - 0xE2080;
|
||||
}
|
||||
if (ch0 < 0xF8) // 1111_0xxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
{
|
||||
char_type const ch1 = read_fn(); if (ch1 >> 6 != 2) goto _err;
|
||||
char_type const ch2 = read_fn(); if (ch2 >> 6 != 2) goto _err;
|
||||
char_type const ch3 = read_fn(); if (ch3 >> 6 != 2) goto _err;
|
||||
return (ch0 << 18) + (ch1 << 12) + (ch2 << 6) + ch3 - 0x3C82080;
|
||||
}
|
||||
if (ch0 < 0xFC) // 1111_10xx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
{
|
||||
char_type const ch1 = read_fn(); if (ch1 >> 6 != 2) goto _err;
|
||||
char_type const ch2 = read_fn(); if (ch2 >> 6 != 2) goto _err;
|
||||
char_type const ch3 = read_fn(); if (ch3 >> 6 != 2) goto _err;
|
||||
char_type const ch4 = read_fn(); if (ch4 >> 6 != 2) goto _err;
|
||||
return (ch0 << 24) + (ch1 << 18) + (ch2 << 12) + (ch3 << 6) + ch4 - 0xFA082080;
|
||||
}
|
||||
if (ch0 < 0xFE) // 1111_110x 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
{
|
||||
char_type const ch1 = read_fn(); if (ch1 >> 6 != 2) goto _err;
|
||||
char_type const ch2 = read_fn(); if (ch2 >> 6 != 2) goto _err;
|
||||
char_type const ch3 = read_fn(); if (ch3 >> 6 != 2) goto _err;
|
||||
char_type const ch4 = read_fn(); if (ch4 >> 6 != 2) goto _err;
|
||||
char_type const ch5 = read_fn(); if (ch5 >> 6 != 2) goto _err;
|
||||
return (ch0 << 30) + (ch1 << 24) + (ch2 << 18) + (ch3 << 12) + (ch4 << 6) + ch5 - 0x82082080;
|
||||
}
|
||||
throw std::runtime_error("The utf8 first char in sequence is incorrect");
|
||||
_err: throw std::runtime_error("The utf8 slave char in sequence is incorrect");
|
||||
}
|
||||
|
||||
template<typename WriteFn>
|
||||
static void write(uint32_t const cp, WriteFn && write_fn)
|
||||
{
|
||||
if (cp < 0x80) // 0xxx_xxxx
|
||||
write_fn(static_cast<char_type>(cp));
|
||||
else if (cp < 0x800) // 110x_xxxx 10xx_xxxx
|
||||
{
|
||||
write_fn(static_cast<char_type>(0xC0 | cp >> 6));
|
||||
goto _1;
|
||||
}
|
||||
else if (cp < 0x10000) // 1110_xxxx 10xx_xxxx 10xx_xxxx
|
||||
{
|
||||
write_fn(static_cast<char_type>(0xE0 | cp >> 12));
|
||||
goto _2;
|
||||
}
|
||||
else if (cp < 0x200000) // 1111_0xxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
{
|
||||
write_fn(static_cast<char_type>(0xF0 | cp >> 18));
|
||||
goto _3;
|
||||
}
|
||||
else if (cp < 0x4000000) // 1111_10xx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
{
|
||||
write_fn(static_cast<char_type>(0xF8 | cp >> 24));
|
||||
goto _4;
|
||||
}
|
||||
else if (cp < 0x80000000) // 1111_110x 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx 10xx_xxxx
|
||||
{
|
||||
write_fn(static_cast<char_type>(0xFC | cp >> 30));
|
||||
goto _5;
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("Tool large UTF8 code point");
|
||||
return;
|
||||
_5: write_fn(static_cast<char_type>(0x80 | (cp >> 24 & 0x3F)));
|
||||
_4: write_fn(static_cast<char_type>(0x80 | (cp >> 18 & 0x3F)));
|
||||
_3: write_fn(static_cast<char_type>(0x80 | (cp >> 12 & 0x3F)));
|
||||
_2: write_fn(static_cast<char_type>(0x80 | (cp >> 6 & 0x3F)));
|
||||
_1: write_fn(static_cast<char_type>(0x80 | (cp & 0x3F)));
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
|
@ -330,12 +330,12 @@ TESTS = \
|
|||
test_sql_str_func.sh \
|
||||
test_sql_time_func.sh \
|
||||
test_data_parser.sh \
|
||||
test_pretty_print.sh
|
||||
test_pretty_print.sh \
|
||||
test_vt52_curses.sh
|
||||
|
||||
DISABLED_TESTS = \
|
||||
test_top_status \
|
||||
test_view_colors.sh \
|
||||
test_vt52_curses.sh
|
||||
test_view_colors.sh
|
||||
|
||||
if HAVE_LIBCURL
|
||||
TESTS += \
|
||||
|
|
|
@ -35,7 +35,9 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "base/lnav_log.hh"
|
||||
#include "view_curses.hh"
|
||||
#include "vt52_curses.hh"
|
||||
|
||||
|
@ -64,11 +66,14 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
int lpc, c, fd, retval = EXIT_SUCCESS;
|
||||
vt52_curses vt;
|
||||
|
||||
|
||||
setenv("LANG", "en_US.utf-8", 1);
|
||||
setlocale(LC_ALL, "");
|
||||
fd = open("/tmp/lnav.err", O_WRONLY|O_CREAT|O_APPEND, 0666);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
close(fd);
|
||||
fprintf(stderr, "startup\n");
|
||||
lnav_log_file = stderr;
|
||||
|
||||
while ((c = getopt(argc, argv, "y:")) != -1) {
|
||||
switch (c) {
|
||||
|
@ -81,16 +86,16 @@ int main(int argc, char *argv[])
|
|||
for (lpc = 0; lpc < 1000; lpc++) {
|
||||
int len;
|
||||
|
||||
assert(vt.map_input(random(), len) != NULL);
|
||||
assert(vt.map_input(random(), len) != nullptr);
|
||||
assert(len > 0);
|
||||
}
|
||||
|
||||
tgetent(NULL, "vt52");
|
||||
tgetent(nullptr, "vt52");
|
||||
{
|
||||
static const char *CANNED_INPUT[] = {
|
||||
"abc",
|
||||
"Gru\xC3\x9F",
|
||||
"\r",
|
||||
tgetstr((char *)"ce", NULL),
|
||||
tgetstr((char *)"ce", nullptr),
|
||||
"de",
|
||||
"\n",
|
||||
"1\n",
|
||||
|
@ -103,7 +108,7 @@ int main(int argc, char *argv[])
|
|||
"8\n",
|
||||
"9\n",
|
||||
"abc",
|
||||
"\x2",
|
||||
"\x02",
|
||||
"\a",
|
||||
"ab\bcdef",
|
||||
0
|
||||
|
|
|
@ -210,7 +210,7 @@ static void dump_memory(FILE *dst, const char *src, int len)
|
|||
int lpc;
|
||||
|
||||
for (lpc = 0; lpc < len; lpc++) {
|
||||
fprintf(dst, "%02x", src[lpc]);
|
||||
fprintf(dst, "%02x", src[lpc] & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#define _XOPEN_SOURCE_EXTENDED 1
|
||||
#include <locale.h>
|
||||
|
@ -19,6 +20,7 @@
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
setenv("LANG", "en_US.utf-8", 1);
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
WINDOW *stdscr = initscr();
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
sleep 2.051763
|
||||
write 31
|
||||
sleep 0.311858
|
||||
write 32
|
||||
sleep 0.295852
|
||||
write 33
|
||||
sleep 0.319916
|
||||
write 34
|
||||
sleep 0.327742
|
||||
write 35
|
||||
sleep 0.328183
|
||||
write 36
|
||||
sleep 0.335896
|
||||
write 37
|
||||
sleep 0.360085
|
||||
write 38
|
||||
sleep 0.336000
|
||||
write 39
|
||||
sleep 0.376058
|
||||
write 30
|
||||
sleep 0.840149
|
||||
write 61
|
||||
sleep 0.783892
|
||||
write 62
|
||||
sleep 0.415990
|
||||
write 63
|
||||
sleep 0.280001
|
||||
write 64
|
||||
sleep 0.191901
|
||||
write 65
|
||||
sleep 0.295949
|
||||
write 66
|
||||
sleep 0.775841
|
||||
write 67
|
||||
sleep 0.399883
|
||||
write 68
|
||||
sleep 0.304016
|
||||
write 69
|
||||
sleep 0.867286
|
||||
write 0d
|
||||
sleep 0.141596
|
||||
write 0d
|
||||
sleep 0.188837
|
||||
write 0d
|
||||
sleep 0.177586
|
||||
write 0d
|
||||
sleep 0.159950
|
||||
write 0d
|
||||
sleep 0.158958
|
||||
write 0d
|
||||
sleep 0.164105
|
||||
write 0d
|
||||
sleep 0.176968
|
||||
write 0d
|
||||
sleep 0.165942
|
||||
write 0d
|
||||
sleep 0.187011
|
||||
write 0d
|
||||
sleep 0.167987
|
||||
write 0d
|
||||
sleep 0.173959
|
||||
write 0d
|
||||
sleep 0.176091
|
||||
write 0d
|
||||
sleep 0.180728
|
||||
write 0d
|
||||
sleep 0.172983
|
||||
write 0d
|
||||
sleep 0.167819
|
||||
write 0d
|
||||
sleep 0.165876
|
||||
write 0d
|
||||
sleep 0.175857
|
||||
write 0d
|
||||
sleep 0.183068
|
||||
write 0d
|
||||
|
|
|
@ -1,38 +1,39 @@
|
|||
read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a616263
|
||||
# write 31
|
||||
read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a477275c39f
|
||||
# write 0d
|
||||
read 0d
|
||||
# write 32
|
||||
# write 0d
|
||||
read 1b5b4a
|
||||
# write 33
|
||||
# write 0d
|
||||
read 6465
|
||||
# write 34
|
||||
# write 0d
|
||||
read 0d1b5b4a
|
||||
# write 35
|
||||
# write 0d
|
||||
read
|
||||
# write 36
|
||||
# write 0d
|
||||
read
|
||||
# write 37
|
||||
# write 0d
|
||||
read
|
||||
# write 38
|
||||
# write 0d
|
||||
read
|
||||
# write 39
|
||||
# write 0d
|
||||
read
|
||||
# write 30
|
||||
# write 0d
|
||||
read
|
||||
# write 61
|
||||
# write 0d
|
||||
read
|
||||
# write 62
|
||||
# write 0d
|
||||
read
|
||||
# write 63
|
||||
# write 0d
|
||||
read
|
||||
# write 64
|
||||
# write 0d
|
||||
read 616263
|
||||
# write 65
|
||||
# write 0d
|
||||
read 0d1b5b4a
|
||||
# write 66
|
||||
# write 0d
|
||||
read 07
|
||||
# write 67
|
||||
# write 0d
|
||||
read 6163646566
|
||||
# write 68
|
||||
# write 0d
|
||||
read
|
||||
# write 69
|
||||
# write 0d
|
||||
read 1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e
|
||||
|
|
Loading…
Reference in New Issue