#include "print_string.h"
#include "core/core_globals.h"
#include "core/os/os.h"
static PrintHandlerList *print_handler_list = nullptr;
static thread_local bool is_printing = false;
static void __print_fallback(const String &p_string, bool p_err) {
fprintf(p_err ? stderr : stdout, "While attempting to print a message, another message was printed:\n%s\n", p_string.utf8().get_data());
}
void add_print_handler(PrintHandlerList *p_handler) {
_global_lock();
p_handler->next = print_handler_list;
print_handler_list = p_handler;
_global_unlock();
}
void remove_print_handler(const PrintHandlerList *p_handler) {
_global_lock();
PrintHandlerList *prev = nullptr;
PrintHandlerList *l = print_handler_list;
while (l) {
if (l == p_handler) {
if (prev) {
prev->next = l->next;
} else {
print_handler_list = l->next;
}
break;
}
prev = l;
l = l->next;
}
_global_unlock();
ERR_FAIL_NULL(l);
}
void __print_line(const String &p_string) {
if (!CoreGlobals::print_line_enabled) {
return;
}
if (is_printing) {
__print_fallback(p_string, false);
return;
}
is_printing = true;
OS::get_singleton()->print("%s\n", p_string.utf8().get_data());
_global_lock();
PrintHandlerList *l = print_handler_list;
while (l) {
l->printfunc(l->userdata, p_string, false, false);
l = l->next;
}
_global_unlock();
is_printing = false;
}
void __print_line_rich(const String &p_string) {
if (!CoreGlobals::print_line_enabled) {
return;
}
String output;
int pos = 0;
while (pos <= p_string.length()) {
int brk_pos = p_string.find_char('[', pos);
if (brk_pos < 0) {
brk_pos = p_string.length();
}
String txt = brk_pos > pos ? p_string.substr(pos, brk_pos - pos) : "";
if (brk_pos == p_string.length()) {
output += txt;
break;
}
int brk_end = p_string.find_char(']', brk_pos + 1);
if (brk_end == -1) {
txt += p_string.substr(brk_pos);
output += txt;
break;
}
pos = brk_end + 1;
output += txt;
String tag = p_string.substr(brk_pos + 1, brk_end - brk_pos - 1);
if (tag == "b") {
output += "\u001b[1m";
} else if (tag == "/b") {
output += "\u001b[22m";
} else if (tag == "i") {
output += "\u001b[3m";
} else if (tag == "/i") {
output += "\u001b[23m";
} else if (tag == "u") {
output += "\u001b[4m";
} else if (tag == "/u") {
output += "\u001b[24m";
} else if (tag == "s") {
output += "\u001b[9m";
} else if (tag == "/s") {
output += "\u001b[29m";
} else if (tag == "indent") {
output += " ";
} else if (tag == "/indent") {
output += "";
} else if (tag == "code") {
output += "\u001b[2m";
} else if (tag == "/code") {
output += "\u001b[22m";
} else if (tag == "url") {
output += "";
} else if (tag == "/url") {
output += "";
} else if (tag == "center") {
output += "\n\t\t\t";
} else if (tag == "/center") {
output += "";
} else if (tag == "right") {
output += "\n\t\t\t\t\t\t";
} else if (tag == "/right") {
output += "";
} else if (tag.begins_with("color=")) {
String color_name = tag.trim_prefix("color=");
if (color_name == "black") {
output += "\u001b[30m";
} else if (color_name == "red") {
output += "\u001b[91m";
} else if (color_name == "green") {
output += "\u001b[92m";
} else if (color_name == "lime") {
output += "\u001b[92m";
} else if (color_name == "yellow") {
output += "\u001b[93m";
} else if (color_name == "blue") {
output += "\u001b[94m";
} else if (color_name == "magenta") {
output += "\u001b[95m";
} else if (color_name == "pink") {
output += "\u001b[38;5;218m";
} else if (color_name == "purple") {
output += "\u001b[38;5;98m";
} else if (color_name == "cyan") {
output += "\u001b[96m";
} else if (color_name == "white") {
output += "\u001b[97m";
} else if (color_name == "orange") {
output += "\u001b[38;5;208m";
} else if (color_name == "gray") {
output += "\u001b[90m";
} else {
Color c = Color::from_string(color_name, Color());
output += vformat("\u001b[38;2;%d;%d;%dm", c.r * 255, c.g * 255, c.b * 255);
}
} else if (tag == "/color") {
output += "\u001b[39m";
} else if (tag.begins_with("bgcolor=")) {
String color_name = tag.trim_prefix("bgcolor=");
if (color_name == "black") {
output += "\u001b[40m";
} else if (color_name == "red") {
output += "\u001b[101m";
} else if (color_name == "green") {
output += "\u001b[102m";
} else if (color_name == "lime") {
output += "\u001b[102m";
} else if (color_name == "yellow") {
output += "\u001b[103m";
} else if (color_name == "blue") {
output += "\u001b[104m";
} else if (color_name == "magenta") {
output += "\u001b[105m";
} else if (color_name == "pink") {
output += "\u001b[48;5;218m";
} else if (color_name == "purple") {
output += "\u001b[48;5;98m";
} else if (color_name == "cyan") {
output += "\u001b[106m";
} else if (color_name == "white") {
output += "\u001b[107m";
} else if (color_name == "orange") {
output += "\u001b[48;5;208m";
} else if (color_name == "gray") {
output += "\u001b[100m";
} else {
Color c = Color::from_string(color_name, Color());
output += vformat("\u001b[48;2;%d;%d;%dm", c.r * 255, c.g * 255, c.b * 255);
}
} else if (tag == "/bgcolor") {
output += "\u001b[49m";
} else if (tag.begins_with("fgcolor=")) {
String color_name = tag.trim_prefix("fgcolor=");
if (color_name == "black") {
output += "\u001b[30;40m";
} else if (color_name == "red") {
output += "\u001b[91;101m";
} else if (color_name == "green") {
output += "\u001b[92;102m";
} else if (color_name == "lime") {
output += "\u001b[92;102m";
} else if (color_name == "yellow") {
output += "\u001b[93;103m";
} else if (color_name == "blue") {
output += "\u001b[94;104m";
} else if (color_name == "magenta") {
output += "\u001b[95;105m";
} else if (color_name == "pink") {
output += "\u001b[38;5;218;48;5;218m";
} else if (color_name == "purple") {
output += "\u001b[38;5;98;48;5;98m";
} else if (color_name == "cyan") {
output += "\u001b[96;106m";
} else if (color_name == "white") {
output += "\u001b[97;107m";
} else if (color_name == "orange") {
output += "\u001b[38;5;208;48;5;208m";
} else if (color_name == "gray") {
output += "\u001b[90;100m";
} else {
Color c = Color::from_string(color_name, Color());
output += vformat("\u001b[38;2;%d;%d;%d;48;2;%d;%d;%dm", c.r * 255, c.g * 255, c.b * 255, c.r * 255, c.g * 255, c.b * 255);
}
} else if (tag == "/fgcolor") {
output += "\u001b[39;49m";
} else {
output += "[";
pos = brk_pos + 1;
}
}
output += "\u001b[0m";
if (is_printing) {
__print_fallback(output, false);
return;
}
is_printing = true;
OS::get_singleton()->print_rich("%s\n", output.utf8().get_data());
_global_lock();
PrintHandlerList *l = print_handler_list;
while (l) {
l->printfunc(l->userdata, p_string, false, true);
l = l->next;
}
_global_unlock();
is_printing = false;
}
void print_raw(const String &p_string) {
if (is_printing) {
__print_fallback(p_string, true);
return;
}
is_printing = true;
OS::get_singleton()->print("%s", p_string.utf8().get_data());
is_printing = false;
}
void print_error(const String &p_string) {
if (!CoreGlobals::print_error_enabled) {
return;
}
if (is_printing) {
__print_fallback(p_string, true);
return;
}
is_printing = true;
OS::get_singleton()->printerr("%s\n", p_string.utf8().get_data());
_global_lock();
PrintHandlerList *l = print_handler_list;
while (l) {
l->printfunc(l->userdata, p_string, true, false);
l = l->next;
}
_global_unlock();
is_printing = false;
}
bool is_print_verbose_enabled() {
return OS::get_singleton()->is_stdout_verbose();
}
String stringify_variants(const Variant &p_var) {
return p_var.operator String();
}