|
|
|
@ -17,6 +17,15 @@ Terminal::Terminal() : Source::CommonView() { |
|
|
|
|
|
|
|
|
|
|
|
bold_tag = get_buffer()->create_tag(); |
|
|
|
bold_tag = get_buffer()->create_tag(); |
|
|
|
bold_tag->property_weight() = Pango::WEIGHT_BOLD; |
|
|
|
bold_tag->property_weight() = Pango::WEIGHT_BOLD; |
|
|
|
|
|
|
|
light_tag = get_buffer()->create_tag(); |
|
|
|
|
|
|
|
light_tag->property_weight() = Pango::WEIGHT_LIGHT; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
italic_tag = get_buffer()->create_tag(); |
|
|
|
|
|
|
|
italic_tag->property_style() = Pango::STYLE_ITALIC; |
|
|
|
|
|
|
|
underline_tag = get_buffer()->create_tag(); |
|
|
|
|
|
|
|
underline_tag->property_underline() = Pango::Underline::UNDERLINE_SINGLE; |
|
|
|
|
|
|
|
strikethrough_tag = get_buffer()->create_tag(); |
|
|
|
|
|
|
|
strikethrough_tag->property_strikethrough() = true; |
|
|
|
|
|
|
|
|
|
|
|
red_tag = get_buffer()->create_tag(); |
|
|
|
red_tag = get_buffer()->create_tag(); |
|
|
|
green_tag = get_buffer()->create_tag(); |
|
|
|
green_tag = get_buffer()->create_tag(); |
|
|
|
@ -24,7 +33,7 @@ Terminal::Terminal() : Source::CommonView() { |
|
|
|
blue_tag = get_buffer()->create_tag(); |
|
|
|
blue_tag = get_buffer()->create_tag(); |
|
|
|
magenta_tag = get_buffer()->create_tag(); |
|
|
|
magenta_tag = get_buffer()->create_tag(); |
|
|
|
cyan_tag = get_buffer()->create_tag(); |
|
|
|
cyan_tag = get_buffer()->create_tag(); |
|
|
|
gray_tag = get_buffer()->create_tag(); |
|
|
|
white_tag = get_buffer()->create_tag(); |
|
|
|
|
|
|
|
|
|
|
|
link_tag = get_buffer()->create_tag(); |
|
|
|
link_tag = get_buffer()->create_tag(); |
|
|
|
link_tag->property_underline() = Pango::Underline::UNDERLINE_SINGLE; |
|
|
|
link_tag->property_underline() = Pango::Underline::UNDERLINE_SINGLE; |
|
|
|
@ -110,7 +119,38 @@ Terminal::Terminal() : Source::CommonView() { |
|
|
|
return {}; |
|
|
|
return {}; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
get_buffer()->signal_insert().connect([this, detect_possible_link = DetectPossibleLink(), parse_ansi_escape_sequence = ParseAnsiEscapeSequence(), last_color = -1, last_color_sequence_mark = std::shared_ptr<Source::Mark>()](const Gtk::TextIter &iter, const Glib::ustring &text_, int /*bytes*/) mutable { |
|
|
|
class Code { |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
int code = -1; |
|
|
|
|
|
|
|
std::shared_ptr<Source::Mark> start_mark; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
auto code_to_color_tag = [this](int code) { |
|
|
|
|
|
|
|
if(code == 31) |
|
|
|
|
|
|
|
return red_tag; |
|
|
|
|
|
|
|
else if(code == 32) |
|
|
|
|
|
|
|
return green_tag; |
|
|
|
|
|
|
|
else if(code == 33) |
|
|
|
|
|
|
|
return yellow_tag; |
|
|
|
|
|
|
|
else if(code == 34) |
|
|
|
|
|
|
|
return blue_tag; |
|
|
|
|
|
|
|
else if(code == 35) |
|
|
|
|
|
|
|
return magenta_tag; |
|
|
|
|
|
|
|
else if(code == 36) |
|
|
|
|
|
|
|
return cyan_tag; |
|
|
|
|
|
|
|
else if(code == 37) |
|
|
|
|
|
|
|
return white_tag; |
|
|
|
|
|
|
|
return Glib::RefPtr<Gtk::TextTag>(); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
auto code_to_weight_tag = [this](int code) { |
|
|
|
|
|
|
|
if(code == 1) |
|
|
|
|
|
|
|
return bold_tag; |
|
|
|
|
|
|
|
else if(code == 2) |
|
|
|
|
|
|
|
return light_tag; |
|
|
|
|
|
|
|
return Glib::RefPtr<Gtk::TextTag>(); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
get_buffer()->signal_insert().connect([this, code_to_color_tag, code_to_weight_tag, |
|
|
|
|
|
|
|
detect_possible_link = DetectPossibleLink(), parse_ansi_escape_sequence = ParseAnsiEscapeSequence(), |
|
|
|
|
|
|
|
color_code = Code(), weight_code = Code(), italic_code = Code(), underline_code = Code(), strikethrough_code = Code()](const Gtk::TextIter &iter, const Glib::ustring &text_, int /*bytes*/) mutable { |
|
|
|
boost::optional<Gtk::TextIter> start_of_text; |
|
|
|
boost::optional<Gtk::TextIter> start_of_text; |
|
|
|
int line_nr_offset = 0; |
|
|
|
int line_nr_offset = 0; |
|
|
|
auto get_line_nr = [&] { |
|
|
|
auto get_line_nr = [&] { |
|
|
|
@ -144,9 +184,31 @@ Terminal::Terminal() : Source::CommonView() { |
|
|
|
start.backward_chars(sequence->length); |
|
|
|
start.backward_chars(sequence->length); |
|
|
|
get_buffer()->apply_tag(invisible_tag, start, end); |
|
|
|
get_buffer()->apply_tag(invisible_tag, start, end); |
|
|
|
if(sequence->command == 'm') { |
|
|
|
if(sequence->command == 'm') { |
|
|
|
int color = -1; |
|
|
|
auto reset = [&] { |
|
|
|
if(sequence->arguments.empty()) |
|
|
|
if(color_code.start_mark) { |
|
|
|
color = 0; |
|
|
|
auto tag = code_to_color_tag(color_code.code); |
|
|
|
|
|
|
|
if(tag) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(tag, (*color_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(weight_code.start_mark) { |
|
|
|
|
|
|
|
auto tag = code_to_weight_tag(weight_code.code); |
|
|
|
|
|
|
|
if(tag) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(tag, (*weight_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(italic_code.start_mark) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(italic_tag, (*italic_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
if(underline_code.start_mark) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(underline_tag, (*underline_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
if(strikethrough_code.start_mark) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(strikethrough_tag, (*strikethrough_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
color_code = {}; |
|
|
|
|
|
|
|
weight_code = {}; |
|
|
|
|
|
|
|
italic_code = {}; |
|
|
|
|
|
|
|
underline_code = {}; |
|
|
|
|
|
|
|
strikethrough_code = {}; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
if(sequence->arguments.empty()) // Reset
|
|
|
|
|
|
|
|
reset(); |
|
|
|
else { |
|
|
|
else { |
|
|
|
size_t pos = 0; |
|
|
|
size_t pos = 0; |
|
|
|
size_t start_pos = pos; |
|
|
|
size_t start_pos = pos; |
|
|
|
@ -154,16 +216,74 @@ Terminal::Terminal() : Source::CommonView() { |
|
|
|
pos = sequence->arguments.find(";", pos); |
|
|
|
pos = sequence->arguments.find(";", pos); |
|
|
|
try { |
|
|
|
try { |
|
|
|
auto code = std::stoi(sequence->arguments.substr(start_pos, pos != std::string::npos ? pos - start_pos : pos)); |
|
|
|
auto code = std::stoi(sequence->arguments.substr(start_pos, pos != std::string::npos ? pos - start_pos : pos)); |
|
|
|
if(code == 39) |
|
|
|
if(code == 0) // Reset
|
|
|
|
color = 0; |
|
|
|
reset(); |
|
|
|
else if(code == 38) { |
|
|
|
else if(code == 1 || code == 2) { // Bold or faint
|
|
|
|
color = 0; |
|
|
|
if(weight_code.start_mark) { |
|
|
|
break; // Do not read next arguments
|
|
|
|
auto tag = code_to_weight_tag(weight_code.code); |
|
|
|
|
|
|
|
if(tag) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(tag, (*weight_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
weight_code = {code, std::make_shared<Source::Mark>(end)}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if(code == 3) // Italic
|
|
|
|
|
|
|
|
italic_code = {code, std::make_shared<Source::Mark>(end)}; |
|
|
|
|
|
|
|
else if(code == 4) // Underline
|
|
|
|
|
|
|
|
underline_code = {code, std::make_shared<Source::Mark>(end)}; |
|
|
|
|
|
|
|
else if(code == 9) // Strikethrough
|
|
|
|
|
|
|
|
strikethrough_code = {code, std::make_shared<Source::Mark>(end)}; |
|
|
|
|
|
|
|
else if(code == 22) { // Normal intensity
|
|
|
|
|
|
|
|
if(weight_code.start_mark) { |
|
|
|
|
|
|
|
auto tag = code_to_weight_tag(weight_code.code); |
|
|
|
|
|
|
|
if(tag) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(tag, (*weight_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
weight_code = {}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if(code == 23) { // No italic
|
|
|
|
|
|
|
|
if(italic_code.start_mark) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(italic_tag, (*italic_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
italic_code = {}; |
|
|
|
} |
|
|
|
} |
|
|
|
else if(code == 48 || code == 58) |
|
|
|
else if(code == 24) { // No underline
|
|
|
|
break; // Do not read next arguments
|
|
|
|
if(underline_code.start_mark) |
|
|
|
else if(code == 0 || code == 2 || code == 22 || (code >= 30 && code <= 37)) |
|
|
|
get_buffer()->apply_tag(underline_tag, (*underline_code.start_mark)->get_iter(), start); |
|
|
|
color = code; |
|
|
|
underline_code = {}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if(code == 29) { // No strikethrough
|
|
|
|
|
|
|
|
if(strikethrough_code.start_mark) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(strikethrough_tag, (*strikethrough_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
strikethrough_code = {}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if(code >= 30 && code <= 37) { // Foreground color
|
|
|
|
|
|
|
|
if(color_code.start_mark) { |
|
|
|
|
|
|
|
auto tag = code_to_color_tag(color_code.code); |
|
|
|
|
|
|
|
if(tag) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(tag, (*color_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
color_code = {code, std::make_shared<Source::Mark>(end)}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if(code == 38) { // Set specific color not supported
|
|
|
|
|
|
|
|
if(color_code.start_mark) { |
|
|
|
|
|
|
|
auto tag = code_to_color_tag(color_code.code); |
|
|
|
|
|
|
|
if(tag) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(tag, (*color_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
color_code = {}; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if(code == 39) { // Default color
|
|
|
|
|
|
|
|
if(color_code.start_mark) { |
|
|
|
|
|
|
|
auto tag = code_to_color_tag(color_code.code); |
|
|
|
|
|
|
|
if(tag) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(tag, (*color_code.start_mark)->get_iter(), start); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
color_code = {}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if(code == 48) // Set specific background color not supported
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
else if(code == 58) // Set specific underline color not supported
|
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
catch(...) { |
|
|
|
catch(...) { |
|
|
|
} |
|
|
|
} |
|
|
|
@ -173,27 +293,6 @@ Terminal::Terminal() : Source::CommonView() { |
|
|
|
start_pos = pos; |
|
|
|
start_pos = pos; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if(last_color >= 0) { |
|
|
|
|
|
|
|
if(last_color == 31) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(red_tag, (*last_color_sequence_mark)->get_iter(), start); |
|
|
|
|
|
|
|
else if(last_color == 32) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(green_tag, (*last_color_sequence_mark)->get_iter(), start); |
|
|
|
|
|
|
|
else if(last_color == 33) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(yellow_tag, (*last_color_sequence_mark)->get_iter(), start); |
|
|
|
|
|
|
|
else if(last_color == 34) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(blue_tag, (*last_color_sequence_mark)->get_iter(), start); |
|
|
|
|
|
|
|
else if(last_color == 35) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(magenta_tag, (*last_color_sequence_mark)->get_iter(), start); |
|
|
|
|
|
|
|
else if(last_color == 36) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(cyan_tag, (*last_color_sequence_mark)->get_iter(), start); |
|
|
|
|
|
|
|
else if(last_color == 37 || last_color == 2) |
|
|
|
|
|
|
|
get_buffer()->apply_tag(gray_tag, (*last_color_sequence_mark)->get_iter(), start); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(color >= 0) { |
|
|
|
|
|
|
|
last_color = color; |
|
|
|
|
|
|
|
last_color_sequence_mark = std::make_shared<Source::Mark>(end); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if(text[i] == '\n') |
|
|
|
if(text[i] == '\n') |
|
|
|
@ -540,11 +639,11 @@ void Terminal::configure() { |
|
|
|
cyan_tag->property_foreground_rgba() = rgba; |
|
|
|
cyan_tag->property_foreground_rgba() = rgba; |
|
|
|
|
|
|
|
|
|
|
|
rgba.set_rgba(0.5, 0.5, 0.5); |
|
|
|
rgba.set_rgba(0.5, 0.5, 0.5); |
|
|
|
factor = light_theme ? 0.6 : 0.4; |
|
|
|
factor = light_theme ? 0.7 : 0.4; |
|
|
|
rgba.set_red(normal_color.get_red() + factor * (rgba.get_red() - normal_color.get_red())); |
|
|
|
rgba.set_red(normal_color.get_red() + factor * (rgba.get_red() - normal_color.get_red())); |
|
|
|
rgba.set_green(normal_color.get_green() + factor * (rgba.get_green() - normal_color.get_green())); |
|
|
|
rgba.set_green(normal_color.get_green() + factor * (rgba.get_green() - normal_color.get_green())); |
|
|
|
rgba.set_blue(normal_color.get_blue() + factor * (rgba.get_blue() - normal_color.get_blue())); |
|
|
|
rgba.set_blue(normal_color.get_blue() + factor * (rgba.get_blue() - normal_color.get_blue())); |
|
|
|
gray_tag->property_foreground_rgba() = rgba; |
|
|
|
white_tag->property_foreground_rgba() = rgba; |
|
|
|
|
|
|
|
|
|
|
|
// Set search match style:
|
|
|
|
// Set search match style:
|
|
|
|
get_buffer()->get_tag_table()->foreach([](const Glib::RefPtr<Gtk::TextTag> &tag) { |
|
|
|
get_buffer()->get_tag_table()->foreach([](const Glib::RefPtr<Gtk::TextTag> &tag) { |
|
|
|
|