Add colored text (not only colored chat).
Add documentation, move files to a proper place and avoid memory leaks. Make it work with most kind of texts, and allow backgrounds too.master
parent
1d40385d4a
commit
14ef2b445a
|
@ -102,7 +102,7 @@ core.register_chatcommand("help", {
|
||||||
description = "Get help for commands or list privileges",
|
description = "Get help for commands or list privileges",
|
||||||
func = function(name, param)
|
func = function(name, param)
|
||||||
local function format_help_line(cmd, def)
|
local function format_help_line(cmd, def)
|
||||||
local msg = core.colorize("00ffff", "/"..cmd)
|
local msg = core.colorize("#00ffff", "/"..cmd)
|
||||||
if def.params and def.params ~= "" then
|
if def.params and def.params ~= "" then
|
||||||
msg = msg .. " " .. def.params
|
msg = msg .. " " .. def.params
|
||||||
end
|
end
|
||||||
|
|
|
@ -198,19 +198,34 @@ function core.http_add_fetch(httpenv)
|
||||||
return httpenv
|
return httpenv
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.get_color_escape_sequence(color)
|
if minetest.setting_getbool("disable_escape_sequences") then
|
||||||
--if string.len(color) == 3 then
|
|
||||||
-- local r = string.sub(color, 1, 1)
|
function core.get_color_escape_sequence(color)
|
||||||
-- local g = string.sub(color, 2, 2)
|
return ""
|
||||||
-- local b = string.sub(color, 3, 3)
|
end
|
||||||
-- color = r .. r .. g .. g .. b .. b
|
|
||||||
--end
|
function core.get_background_escape_sequence(color)
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
function core.colorize(color, message)
|
||||||
|
return message
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
local ESCAPE_CHAR = string.char(0x1b)
|
||||||
|
function core.get_color_escape_sequence(color)
|
||||||
|
return ESCAPE_CHAR .. "(c@" .. color .. ")"
|
||||||
|
end
|
||||||
|
|
||||||
|
function core.get_background_escape_sequence(color)
|
||||||
|
return ESCAPE_CHAR .. "(b@" .. color .. ")"
|
||||||
|
end
|
||||||
|
|
||||||
|
function core.colorize(color, message)
|
||||||
|
return core.get_color_escape_sequence(color) .. message .. core.get_color_escape_sequence("#ffffff")
|
||||||
|
end
|
||||||
|
|
||||||
--assert(#color == 6, "Color must be six characters in length.")
|
|
||||||
--return "\v" .. color
|
|
||||||
return "\v(color;" .. color .. ")"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.colorize(color, message)
|
|
||||||
return core.get_color_escape_sequence(color) .. message .. core.get_color_escape_sequence("ffffff")
|
|
||||||
end
|
|
||||||
|
|
|
@ -615,6 +615,11 @@ server_announce (Announce server) bool false
|
||||||
# If you want to announce your ipv6 address, use serverlist_url = v6.servers.minetest.net.
|
# If you want to announce your ipv6 address, use serverlist_url = v6.servers.minetest.net.
|
||||||
serverlist_url (Serverlist URL) string servers.minetest.net
|
serverlist_url (Serverlist URL) string servers.minetest.net
|
||||||
|
|
||||||
|
# Disable escape sequences, e.g. chat coloring.
|
||||||
|
# Use this if you want to run a server with pre-0.4.14 clients and you want to disable
|
||||||
|
# the escape sequences generated by mods.
|
||||||
|
disable_escape_sequences (Disable escape sequences) bool false
|
||||||
|
|
||||||
[*Network]
|
[*Network]
|
||||||
|
|
||||||
# Network port to listen (UDP).
|
# Network port to listen (UDP).
|
||||||
|
|
|
@ -1701,6 +1701,24 @@ numerical form, the raw integer value of an ARGB8 quad:
|
||||||
or string form, a ColorString (defined above):
|
or string form, a ColorString (defined above):
|
||||||
`colorspec = "green"`
|
`colorspec = "green"`
|
||||||
|
|
||||||
|
Escape sequences
|
||||||
|
----------------
|
||||||
|
Most text can contain escape sequences, that can for example color the text.
|
||||||
|
There are a few exceptions: tab headers, dropdowns and vertical labels can't.
|
||||||
|
The following functions provide escape sequences:
|
||||||
|
* `core.get_color_escape_sequence(color)`:
|
||||||
|
* `color` is a ColorString
|
||||||
|
* The escape sequence sets the text color to `color`
|
||||||
|
* `core.colorize(color, message)`:
|
||||||
|
* Equivalent to:
|
||||||
|
`core.get_color_escape_sequence(color) ..
|
||||||
|
message ..
|
||||||
|
core.get_color_escape_sequence("#ffffff")`
|
||||||
|
* `color.get_background_escape_sequence(color)`
|
||||||
|
* `color` is a ColorString
|
||||||
|
* The escape sequence sets the background of the whole text element to
|
||||||
|
`color`. Only defined for item descriptions and tooltips.
|
||||||
|
|
||||||
Spatial Vectors
|
Spatial Vectors
|
||||||
---------------
|
---------------
|
||||||
* `vector.new(a[, b, c])`: returns a vector:
|
* `vector.new(a[, b, c])`: returns a vector:
|
||||||
|
|
|
@ -376,6 +376,7 @@ add_subdirectory(network)
|
||||||
add_subdirectory(script)
|
add_subdirectory(script)
|
||||||
add_subdirectory(unittest)
|
add_subdirectory(unittest)
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
|
add_subdirectory(irrlicht_changes)
|
||||||
|
|
||||||
set(common_SRCS
|
set(common_SRCS
|
||||||
ban.cpp
|
ban.cpp
|
||||||
|
@ -493,6 +494,7 @@ set(client_SRCS
|
||||||
${common_SRCS}
|
${common_SRCS}
|
||||||
${sound_SRCS}
|
${sound_SRCS}
|
||||||
${client_network_SRCS}
|
${client_network_SRCS}
|
||||||
|
${client_irrlicht_changes_SRCS}
|
||||||
camera.cpp
|
camera.cpp
|
||||||
client.cpp
|
client.cpp
|
||||||
clientmap.cpp
|
clientmap.cpp
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
CGUITTFont FreeType class for Irrlicht
|
CGUITTFont FreeType class for Irrlicht
|
||||||
Copyright (c) 2009-2010 John Norman
|
Copyright (c) 2009-2010 John Norman
|
||||||
|
Copyright (c) 2016 Nathanaël Courant
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any
|
warranty. In no event will the authors be held liable for any
|
||||||
|
@ -545,6 +546,13 @@ void CGUITTFont::setFontHinting(const bool enable, const bool enable_auto_hintin
|
||||||
|
|
||||||
void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip)
|
void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip)
|
||||||
{
|
{
|
||||||
|
draw(EnrichedString(std::wstring(text.c_str()), color), position, color, hcenter, vcenter, clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip)
|
||||||
|
{
|
||||||
|
std::vector<video::SColor> colors = text.getColors();
|
||||||
|
|
||||||
if (!Driver)
|
if (!Driver)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -572,7 +580,7 @@ void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to a unicode string.
|
// Convert to a unicode string.
|
||||||
core::ustring utext(text);
|
core::ustring utext = text.getString();
|
||||||
|
|
||||||
// Set up our render map.
|
// Set up our render map.
|
||||||
core::map<u32, CGUITTGlyphPage*> Render_Map;
|
core::map<u32, CGUITTGlyphPage*> Render_Map;
|
||||||
|
@ -581,6 +589,7 @@ void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position
|
||||||
u32 n;
|
u32 n;
|
||||||
uchar32_t previousChar = 0;
|
uchar32_t previousChar = 0;
|
||||||
core::ustring::const_iterator iter(utext);
|
core::ustring::const_iterator iter(utext);
|
||||||
|
std::vector<video::SColor> applied_colors;
|
||||||
while (!iter.atEnd())
|
while (!iter.atEnd())
|
||||||
{
|
{
|
||||||
uchar32_t currentChar = *iter;
|
uchar32_t currentChar = *iter;
|
||||||
|
@ -590,7 +599,7 @@ void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position
|
||||||
if (currentChar == L'\r') // Mac or Windows breaks
|
if (currentChar == L'\r') // Mac or Windows breaks
|
||||||
{
|
{
|
||||||
lineBreak = true;
|
lineBreak = true;
|
||||||
if (*(iter + 1) == (uchar32_t)'\n') // Windows line breaks.
|
if (*(iter + 1) == (uchar32_t)'\n') // Windows line breaks.
|
||||||
currentChar = *(++iter);
|
currentChar = *(++iter);
|
||||||
}
|
}
|
||||||
else if (currentChar == (uchar32_t)'\n') // Unix breaks
|
else if (currentChar == (uchar32_t)'\n') // Unix breaks
|
||||||
|
@ -627,6 +636,9 @@ void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position
|
||||||
page->render_positions.push_back(core::position2di(offset.X + offx, offset.Y + offy));
|
page->render_positions.push_back(core::position2di(offset.X + offx, offset.Y + offy));
|
||||||
page->render_source_rects.push_back(glyph.source_rect);
|
page->render_source_rects.push_back(glyph.source_rect);
|
||||||
Render_Map.set(glyph.glyph_page, page);
|
Render_Map.set(glyph.glyph_page, page);
|
||||||
|
u32 current_color = iter.getPos();
|
||||||
|
if (current_color < colors.size())
|
||||||
|
applied_colors.push_back(colors[current_color]);
|
||||||
}
|
}
|
||||||
offset.X += getWidthFromCharacter(currentChar);
|
offset.X += getWidthFromCharacter(currentChar);
|
||||||
|
|
||||||
|
@ -645,8 +657,6 @@ void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position
|
||||||
|
|
||||||
CGUITTGlyphPage* page = n->getValue();
|
CGUITTGlyphPage* page = n->getValue();
|
||||||
|
|
||||||
if (!use_transparency) color.color |= 0xff000000;
|
|
||||||
|
|
||||||
if (shadow_offset) {
|
if (shadow_offset) {
|
||||||
for (size_t i = 0; i < page->render_positions.size(); ++i)
|
for (size_t i = 0; i < page->render_positions.size(); ++i)
|
||||||
page->render_positions[i] += core::vector2di(shadow_offset, shadow_offset);
|
page->render_positions[i] += core::vector2di(shadow_offset, shadow_offset);
|
||||||
|
@ -654,7 +664,17 @@ void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position
|
||||||
for (size_t i = 0; i < page->render_positions.size(); ++i)
|
for (size_t i = 0; i < page->render_positions.size(); ++i)
|
||||||
page->render_positions[i] -= core::vector2di(shadow_offset, shadow_offset);
|
page->render_positions[i] -= core::vector2di(shadow_offset, shadow_offset);
|
||||||
}
|
}
|
||||||
Driver->draw2DImageBatch(page->texture, page->render_positions, page->render_source_rects, clip, color, true);
|
for (size_t i = 0; i < page->render_positions.size(); ++i) {
|
||||||
|
irr::video::SColor col;
|
||||||
|
if (!applied_colors.empty()) {
|
||||||
|
col = applied_colors[i < applied_colors.size() ? i : 0];
|
||||||
|
} else {
|
||||||
|
col = irr::video::SColor(255, 255, 255, 255);
|
||||||
|
}
|
||||||
|
if (!use_transparency)
|
||||||
|
col.color |= 0xff000000;
|
||||||
|
Driver->draw2DImage(page->texture, page->render_positions[i], page->render_source_rects[i], clip, col, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
CGUITTFont FreeType class for Irrlicht
|
CGUITTFont FreeType class for Irrlicht
|
||||||
Copyright (c) 2009-2010 John Norman
|
Copyright (c) 2009-2010 John Norman
|
||||||
|
Copyright (c) 2016 Nathanaël Courant
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any
|
warranty. In no event will the authors be held liable for any
|
||||||
|
@ -33,6 +34,8 @@
|
||||||
|
|
||||||
#include <irrlicht.h>
|
#include <irrlicht.h>
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "util/enriched_string.h"
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
|
@ -259,6 +262,10 @@ namespace gui
|
||||||
video::SColor color, bool hcenter=false, bool vcenter=false,
|
video::SColor color, bool hcenter=false, bool vcenter=false,
|
||||||
const core::rect<s32>* clip=0);
|
const core::rect<s32>* clip=0);
|
||||||
|
|
||||||
|
virtual void draw(const EnrichedString& text, const core::rect<s32>& position,
|
||||||
|
video::SColor color, bool hcenter=false, bool vcenter=false,
|
||||||
|
const core::rect<s32>* clip=0);
|
||||||
|
|
||||||
//! Returns the dimension of a character produced by this font.
|
//! Returns the dimension of a character produced by this font.
|
||||||
virtual core::dimension2d<u32> getCharDimension(const wchar_t ch) const;
|
virtual core::dimension2d<u32> getCharDimension(const wchar_t ch) const;
|
||||||
|
|
||||||
|
|
37
src/chat.cpp
37
src/chat.cpp
|
@ -267,28 +267,26 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
|
||||||
next_frags.push_back(temp_frag);
|
next_frags.push_back(temp_frag);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring name_sanitized = removeEscapes(line.name);
|
std::wstring name_sanitized = line.name.c_str();
|
||||||
|
|
||||||
// Choose an indentation level
|
// Choose an indentation level
|
||||||
if (line.name.empty()) {
|
if (line.name.empty()) {
|
||||||
// Server messages
|
// Server messages
|
||||||
hanging_indentation = 0;
|
hanging_indentation = 0;
|
||||||
}
|
} else if (name_sanitized.size() + 3 <= cols/2) {
|
||||||
else if (name_sanitized.size() + 3 <= cols/2) {
|
|
||||||
// Names shorter than about half the console width
|
// Names shorter than about half the console width
|
||||||
hanging_indentation = line.name.size() + 3;
|
hanging_indentation = line.name.size() + 3;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Very long names
|
// Very long names
|
||||||
hanging_indentation = 2;
|
hanging_indentation = 2;
|
||||||
}
|
}
|
||||||
ColoredString line_text(line.text);
|
//EnrichedString line_text(line.text);
|
||||||
|
|
||||||
next_line.first = true;
|
next_line.first = true;
|
||||||
bool text_processing = false;
|
bool text_processing = false;
|
||||||
|
|
||||||
// Produce fragments and layout them into lines
|
// Produce fragments and layout them into lines
|
||||||
while (!next_frags.empty() || in_pos < line_text.size())
|
while (!next_frags.empty() || in_pos < line.text.size())
|
||||||
{
|
{
|
||||||
// Layout fragments into lines
|
// Layout fragments into lines
|
||||||
while (!next_frags.empty())
|
while (!next_frags.empty())
|
||||||
|
@ -326,9 +324,9 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Produce fragment
|
// Produce fragment
|
||||||
if (in_pos < line_text.size())
|
if (in_pos < line.text.size())
|
||||||
{
|
{
|
||||||
u32 remaining_in_input = line_text.size() - in_pos;
|
u32 remaining_in_input = line.text.size() - in_pos;
|
||||||
u32 remaining_in_output = cols - out_column;
|
u32 remaining_in_output = cols - out_column;
|
||||||
|
|
||||||
// Determine a fragment length <= the minimum of
|
// Determine a fragment length <= the minimum of
|
||||||
|
@ -338,14 +336,14 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols,
|
||||||
while (frag_length < remaining_in_input &&
|
while (frag_length < remaining_in_input &&
|
||||||
frag_length < remaining_in_output)
|
frag_length < remaining_in_output)
|
||||||
{
|
{
|
||||||
if (isspace(line_text[in_pos + frag_length]))
|
if (isspace(line.text.getString()[in_pos + frag_length]))
|
||||||
space_pos = frag_length;
|
space_pos = frag_length;
|
||||||
++frag_length;
|
++frag_length;
|
||||||
}
|
}
|
||||||
if (space_pos != 0 && frag_length < remaining_in_input)
|
if (space_pos != 0 && frag_length < remaining_in_input)
|
||||||
frag_length = space_pos + 1;
|
frag_length = space_pos + 1;
|
||||||
|
|
||||||
temp_frag.text = line_text.substr(in_pos, frag_length);
|
temp_frag.text = line.text.substr(in_pos, frag_length);
|
||||||
temp_frag.column = 0;
|
temp_frag.column = 0;
|
||||||
//temp_frag.bold = 0;
|
//temp_frag.bold = 0;
|
||||||
next_frags.push_back(temp_frag);
|
next_frags.push_back(temp_frag);
|
||||||
|
@ -729,19 +727,22 @@ ChatBuffer& ChatBackend::getRecentBuffer()
|
||||||
return m_recent_buffer;
|
return m_recent_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring ChatBackend::getRecentChat()
|
EnrichedString ChatBackend::getRecentChat()
|
||||||
{
|
{
|
||||||
std::wostringstream stream;
|
EnrichedString result;
|
||||||
for (u32 i = 0; i < m_recent_buffer.getLineCount(); ++i)
|
for (u32 i = 0; i < m_recent_buffer.getLineCount(); ++i)
|
||||||
{
|
{
|
||||||
const ChatLine& line = m_recent_buffer.getLine(i);
|
const ChatLine& line = m_recent_buffer.getLine(i);
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
stream << L"\n";
|
result += L"\n";
|
||||||
if (!line.name.empty())
|
if (!line.name.empty()) {
|
||||||
stream << L"<" << line.name << L"> ";
|
result += L"<";
|
||||||
stream << line.text;
|
result += line.name;
|
||||||
|
result += L"> ";
|
||||||
|
}
|
||||||
|
result += line.text;
|
||||||
}
|
}
|
||||||
return stream.str();
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatPrompt& ChatBackend::getPrompt()
|
ChatPrompt& ChatBackend::getPrompt()
|
||||||
|
|
17
src/chat.h
17
src/chat.h
|
@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
#include "util/coloredstring.h"
|
#include "util/enriched_string.h"
|
||||||
|
|
||||||
// Chat console related classes
|
// Chat console related classes
|
||||||
|
|
||||||
|
@ -34,9 +34,9 @@ struct ChatLine
|
||||||
// age in seconds
|
// age in seconds
|
||||||
f32 age;
|
f32 age;
|
||||||
// name of sending player, or empty if sent by server
|
// name of sending player, or empty if sent by server
|
||||||
std::wstring name;
|
EnrichedString name;
|
||||||
// message text
|
// message text
|
||||||
ColoredString text;
|
EnrichedString text;
|
||||||
|
|
||||||
ChatLine(std::wstring a_name, std::wstring a_text):
|
ChatLine(std::wstring a_name, std::wstring a_text):
|
||||||
age(0.0),
|
age(0.0),
|
||||||
|
@ -44,12 +44,19 @@ struct ChatLine
|
||||||
text(a_text)
|
text(a_text)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatLine(EnrichedString a_name, EnrichedString a_text):
|
||||||
|
age(0.0),
|
||||||
|
name(a_name),
|
||||||
|
text(a_text)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChatFormattedFragment
|
struct ChatFormattedFragment
|
||||||
{
|
{
|
||||||
// text string
|
// text string
|
||||||
std::wstring text;
|
EnrichedString text;
|
||||||
// starting column
|
// starting column
|
||||||
u32 column;
|
u32 column;
|
||||||
// formatting
|
// formatting
|
||||||
|
@ -262,7 +269,7 @@ public:
|
||||||
// Get the recent messages buffer
|
// Get the recent messages buffer
|
||||||
ChatBuffer& getRecentBuffer();
|
ChatBuffer& getRecentBuffer();
|
||||||
// Concatenate all recent messages
|
// Concatenate all recent messages
|
||||||
std::wstring getRecentChat();
|
EnrichedString getRecentChat();
|
||||||
// Get the console prompt
|
// Get the console prompt
|
||||||
ChatPrompt& getPrompt();
|
ChatPrompt& getPrompt();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
set(client_SRCS
|
set(client_SRCS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/guiChatConsole.cpp
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
|
|
@ -202,6 +202,8 @@ void set_default_settings(Settings *settings)
|
||||||
settings->setDefault("server_name", "");
|
settings->setDefault("server_name", "");
|
||||||
settings->setDefault("server_description", "");
|
settings->setDefault("server_description", "");
|
||||||
|
|
||||||
|
settings->setDefault("disable_escape_sequences", "false");
|
||||||
|
|
||||||
#if USE_FREETYPE
|
#if USE_FREETYPE
|
||||||
settings->setDefault("freetype", "true");
|
settings->setDefault("freetype", "true");
|
||||||
settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "liberationsans.ttf"));
|
settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "liberationsans.ttf"));
|
||||||
|
|
53
src/game.cpp
53
src/game.cpp
|
@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
#include "client/guiChatConsole.h"
|
#include "guiChatConsole.h"
|
||||||
#include "guiFormSpecMenu.h"
|
#include "guiFormSpecMenu.h"
|
||||||
#include "guiKeyChangeMenu.h"
|
#include "guiKeyChangeMenu.h"
|
||||||
#include "guiPasswordChange.h"
|
#include "guiPasswordChange.h"
|
||||||
|
@ -55,14 +55,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "tool.h"
|
#include "tool.h"
|
||||||
#include "util/directiontables.h"
|
#include "util/directiontables.h"
|
||||||
#include "util/pointedthing.h"
|
#include "util/pointedthing.h"
|
||||||
|
#include "irrlicht_changes/static_text.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "minimap.h"
|
#include "minimap.h"
|
||||||
#include "mapblock_mesh.h"
|
#include "mapblock_mesh.h"
|
||||||
|
|
||||||
#if USE_FREETYPE
|
|
||||||
#include "util/statictext.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
|
|
||||||
#if USE_SOUND
|
#if USE_SOUND
|
||||||
|
@ -541,7 +538,7 @@ void update_profiler_gui(gui::IGUIStaticText *guitext_profiler, FontEngine *fe,
|
||||||
std::ostringstream os(std::ios_base::binary);
|
std::ostringstream os(std::ios_base::binary);
|
||||||
g_profiler->printPage(os, show_profiler, show_profiler_max);
|
g_profiler->printPage(os, show_profiler, show_profiler_max);
|
||||||
std::wstring text = utf8_to_wide(os.str());
|
std::wstring text = utf8_to_wide(os.str());
|
||||||
guitext_profiler->setText(text.c_str());
|
setStaticText(guitext_profiler, text.c_str());
|
||||||
guitext_profiler->setVisible(true);
|
guitext_profiler->setVisible(true);
|
||||||
|
|
||||||
s32 w = fe->getTextWidth(text.c_str());
|
s32 w = fe->getTextWidth(text.c_str());
|
||||||
|
@ -1244,7 +1241,11 @@ static void updateChat(Client &client, f32 dtime, bool show_debug,
|
||||||
|
|
||||||
// Get new messages from error log buffer
|
// Get new messages from error log buffer
|
||||||
while (!chat_log_error_buf.empty()) {
|
while (!chat_log_error_buf.empty()) {
|
||||||
chat_backend.addMessage(L"", utf8_to_wide(chat_log_error_buf.get()));
|
std::wstring error_message = utf8_to_wide(chat_log_error_buf.get());
|
||||||
|
if (!g_settings->getBool("disable_escape_sequences")) {
|
||||||
|
error_message = L"\x1b(c@red)" + error_message + L"\x1b(c@white)";
|
||||||
|
}
|
||||||
|
chat_backend.addMessage(L"", error_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get new messages from client
|
// Get new messages from client
|
||||||
|
@ -1259,10 +1260,10 @@ static void updateChat(Client &client, f32 dtime, bool show_debug,
|
||||||
|
|
||||||
// Display all messages in a static text element
|
// Display all messages in a static text element
|
||||||
unsigned int recent_chat_count = chat_backend.getRecentBuffer().getLineCount();
|
unsigned int recent_chat_count = chat_backend.getRecentBuffer().getLineCount();
|
||||||
std::wstring recent_chat = chat_backend.getRecentChat();
|
EnrichedString recent_chat = chat_backend.getRecentChat();
|
||||||
unsigned int line_height = g_fontengine->getLineHeight();
|
unsigned int line_height = g_fontengine->getLineHeight();
|
||||||
|
|
||||||
guitext_chat->setText(recent_chat.c_str());
|
setStaticText(guitext_chat, recent_chat);
|
||||||
|
|
||||||
// Update gui element size and position
|
// Update gui element size and position
|
||||||
s32 chat_y = 5 + line_height;
|
s32 chat_y = 5 + line_height;
|
||||||
|
@ -1271,7 +1272,7 @@ static void updateChat(Client &client, f32 dtime, bool show_debug,
|
||||||
chat_y += line_height;
|
chat_y += line_height;
|
||||||
|
|
||||||
// first pass to calculate height of text to be set
|
// first pass to calculate height of text to be set
|
||||||
s32 width = std::min(g_fontengine->getTextWidth(recent_chat) + 10,
|
s32 width = std::min(g_fontengine->getTextWidth(recent_chat.c_str()) + 10,
|
||||||
porting::getWindowSize().X - 20);
|
porting::getWindowSize().X - 20);
|
||||||
core::rect<s32> rect(10, chat_y, width, chat_y + porting::getWindowSize().Y);
|
core::rect<s32> rect(10, chat_y, width, chat_y + porting::getWindowSize().Y);
|
||||||
guitext_chat->setRelativePosition(rect);
|
guitext_chat->setRelativePosition(rect);
|
||||||
|
@ -2218,45 +2219,39 @@ bool Game::createClient(const std::string &playername,
|
||||||
bool Game::initGui()
|
bool Game::initGui()
|
||||||
{
|
{
|
||||||
// First line of debug text
|
// First line of debug text
|
||||||
guitext = guienv->addStaticText(
|
guitext = addStaticText(guienv,
|
||||||
utf8_to_wide(PROJECT_NAME_C).c_str(),
|
utf8_to_wide(PROJECT_NAME_C).c_str(),
|
||||||
core::rect<s32>(0, 0, 0, 0),
|
core::rect<s32>(0, 0, 0, 0),
|
||||||
false, false, guiroot);
|
false, false, guiroot);
|
||||||
|
|
||||||
// Second line of debug text
|
// Second line of debug text
|
||||||
guitext2 = guienv->addStaticText(
|
guitext2 = addStaticText(guienv,
|
||||||
L"",
|
L"",
|
||||||
core::rect<s32>(0, 0, 0, 0),
|
core::rect<s32>(0, 0, 0, 0),
|
||||||
false, false, guiroot);
|
false, false, guiroot);
|
||||||
|
|
||||||
// At the middle of the screen
|
// At the middle of the screen
|
||||||
// Object infos are shown in this
|
// Object infos are shown in this
|
||||||
guitext_info = guienv->addStaticText(
|
guitext_info = addStaticText(guienv,
|
||||||
L"",
|
L"",
|
||||||
core::rect<s32>(0, 0, 400, g_fontengine->getTextHeight() * 5 + 5) + v2s32(100, 200),
|
core::rect<s32>(0, 0, 400, g_fontengine->getTextHeight() * 5 + 5) + v2s32(100, 200),
|
||||||
false, true, guiroot);
|
false, true, guiroot);
|
||||||
|
|
||||||
// Status text (displays info when showing and hiding GUI stuff, etc.)
|
// Status text (displays info when showing and hiding GUI stuff, etc.)
|
||||||
guitext_status = guienv->addStaticText(
|
guitext_status = addStaticText(guienv,
|
||||||
L"<Status>",
|
L"<Status>",
|
||||||
core::rect<s32>(0, 0, 0, 0),
|
core::rect<s32>(0, 0, 0, 0),
|
||||||
false, false, guiroot);
|
false, false, guiroot);
|
||||||
guitext_status->setVisible(false);
|
guitext_status->setVisible(false);
|
||||||
|
|
||||||
#if USE_FREETYPE
|
|
||||||
// Colored chat support when using FreeType
|
|
||||||
guitext_chat = new gui::StaticText(L"", false, guienv, guiroot, -1, core::rect<s32>(0, 0, 0, 0), false);
|
|
||||||
guitext_chat->setWordWrap(true);
|
|
||||||
guitext_chat->drop();
|
|
||||||
#else
|
|
||||||
// Standard chat when FreeType is disabled
|
|
||||||
// Chat text
|
// Chat text
|
||||||
guitext_chat = guienv->addStaticText(
|
guitext_chat = addStaticText(
|
||||||
|
guienv,
|
||||||
L"",
|
L"",
|
||||||
core::rect<s32>(0, 0, 0, 0),
|
core::rect<s32>(0, 0, 0, 0),
|
||||||
//false, false); // Disable word wrap as of now
|
//false, false); // Disable word wrap as of now
|
||||||
false, true, guiroot);
|
false, true, guiroot);
|
||||||
#endif
|
|
||||||
// Remove stale "recent" chat messages from previous connections
|
// Remove stale "recent" chat messages from previous connections
|
||||||
chat_backend->clearRecentChat();
|
chat_backend->clearRecentChat();
|
||||||
|
|
||||||
|
@ -2270,7 +2265,7 @@ bool Game::initGui()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Profiler text (size is updated when text is updated)
|
// Profiler text (size is updated when text is updated)
|
||||||
guitext_profiler = guienv->addStaticText(
|
guitext_profiler = addStaticText(guienv,
|
||||||
L"<Profiler>",
|
L"<Profiler>",
|
||||||
core::rect<s32>(0, 0, 0, 0),
|
core::rect<s32>(0, 0, 0, 0),
|
||||||
false, false, guiroot);
|
false, false, guiroot);
|
||||||
|
@ -4308,12 +4303,12 @@ void Game::updateGui(float *statustext_time, const RunStats &stats,
|
||||||
<< ", v_range = " << draw_control->wanted_range
|
<< ", v_range = " << draw_control->wanted_range
|
||||||
<< std::setprecision(3)
|
<< std::setprecision(3)
|
||||||
<< ", RTT = " << client->getRTT();
|
<< ", RTT = " << client->getRTT();
|
||||||
guitext->setText(utf8_to_wide(os.str()).c_str());
|
setStaticText(guitext, utf8_to_wide(os.str()).c_str());
|
||||||
guitext->setVisible(true);
|
guitext->setVisible(true);
|
||||||
} else if (flags.show_hud || flags.show_chat) {
|
} else if (flags.show_hud || flags.show_chat) {
|
||||||
std::ostringstream os(std::ios_base::binary);
|
std::ostringstream os(std::ios_base::binary);
|
||||||
os << PROJECT_NAME_C " " << g_version_hash;
|
os << PROJECT_NAME_C " " << g_version_hash;
|
||||||
guitext->setText(utf8_to_wide(os.str()).c_str());
|
setStaticText(guitext, utf8_to_wide(os.str()).c_str());
|
||||||
guitext->setVisible(true);
|
guitext->setVisible(true);
|
||||||
} else {
|
} else {
|
||||||
guitext->setVisible(false);
|
guitext->setVisible(false);
|
||||||
|
@ -4350,7 +4345,7 @@ void Game::updateGui(float *statustext_time, const RunStats &stats,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
guitext2->setText(utf8_to_wide(os.str()).c_str());
|
setStaticText(guitext2, utf8_to_wide(os.str()).c_str());
|
||||||
guitext2->setVisible(true);
|
guitext2->setVisible(true);
|
||||||
|
|
||||||
core::rect<s32> rect(
|
core::rect<s32> rect(
|
||||||
|
@ -4362,7 +4357,7 @@ void Game::updateGui(float *statustext_time, const RunStats &stats,
|
||||||
guitext2->setVisible(false);
|
guitext2->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
guitext_info->setText(infotext.c_str());
|
setStaticText(guitext_info, infotext.c_str());
|
||||||
guitext_info->setVisible(flags.show_hud && g_menumgr.menuCount() == 0);
|
guitext_info->setVisible(flags.show_hud && g_menumgr.menuCount() == 0);
|
||||||
|
|
||||||
float statustext_time_max = 1.5;
|
float statustext_time_max = 1.5;
|
||||||
|
@ -4376,7 +4371,7 @@ void Game::updateGui(float *statustext_time, const RunStats &stats,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
guitext_status->setText(statustext.c_str());
|
setStaticText(guitext_status, statustext.c_str());
|
||||||
guitext_status->setVisible(!statustext.empty());
|
guitext_status->setVisible(!statustext.empty());
|
||||||
|
|
||||||
if (!statustext.empty()) {
|
if (!statustext.empty()) {
|
||||||
|
|
|
@ -346,9 +346,9 @@ void GUIChatConsole::drawText()
|
||||||
// Draw colored text if FreeType is enabled
|
// Draw colored text if FreeType is enabled
|
||||||
irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(m_font);
|
irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(m_font);
|
||||||
tmp->draw(
|
tmp->draw(
|
||||||
fragment.text.c_str(),
|
fragment.text,
|
||||||
destrect,
|
destrect,
|
||||||
fragment.text.getColors(),
|
video::SColor(255, 255, 255, 255),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
&AbsoluteClippingRect);
|
&AbsoluteClippingRect);
|
|
@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "fontengine.h"
|
#include "fontengine.h"
|
||||||
#include "guiscalingfilter.h"
|
#include "guiscalingfilter.h"
|
||||||
|
#include "irrlicht_changes/static_text.h"
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
#include "client/tile.h"
|
#include "client/tile.h"
|
||||||
|
@ -172,15 +173,16 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev,
|
||||||
m_sound_manager = &dummySoundManager;
|
m_sound_manager = &dummySoundManager;
|
||||||
|
|
||||||
//create topleft header
|
//create topleft header
|
||||||
std::wstring t = utf8_to_wide(std::string(PROJECT_NAME_C " ") +
|
m_toplefttext = utf8_to_wide(std::string(PROJECT_NAME_C " ") +
|
||||||
g_version_hash);
|
g_version_hash);
|
||||||
|
|
||||||
core::rect<s32> rect(0, 0, g_fontengine->getTextWidth(t), g_fontengine->getTextHeight());
|
core::rect<s32> rect(0, 0, g_fontengine->getTextWidth(m_toplefttext.c_str()),
|
||||||
|
g_fontengine->getTextHeight());
|
||||||
rect += v2s32(4, 0);
|
rect += v2s32(4, 0);
|
||||||
|
|
||||||
m_irr_toplefttext =
|
m_irr_toplefttext =
|
||||||
m_device->getGUIEnvironment()->addStaticText(t.c_str(),
|
addStaticText(m_device->getGUIEnvironment(), m_toplefttext,
|
||||||
rect,false,true,0,-1);
|
rect, false, true, 0, -1);
|
||||||
|
|
||||||
//create formspecsource
|
//create formspecsource
|
||||||
m_formspecgui = new FormspecFormSource("");
|
m_formspecgui = new FormspecFormSource("");
|
||||||
|
@ -578,7 +580,7 @@ void GUIEngine::setTopleftText(std::string append)
|
||||||
toset += utf8_to_wide(append);
|
toset += utf8_to_wide(append);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_irr_toplefttext->setText(toset.c_str());
|
m_toplefttext = toset;
|
||||||
|
|
||||||
updateTopLeftTextSize();
|
updateTopLeftTextSize();
|
||||||
}
|
}
|
||||||
|
@ -586,15 +588,14 @@ void GUIEngine::setTopleftText(std::string append)
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
void GUIEngine::updateTopLeftTextSize()
|
void GUIEngine::updateTopLeftTextSize()
|
||||||
{
|
{
|
||||||
std::wstring text = m_irr_toplefttext->getText();
|
core::rect<s32> rect(0, 0, g_fontengine->getTextWidth(m_toplefttext.c_str()),
|
||||||
|
g_fontengine->getTextHeight());
|
||||||
core::rect<s32> rect(0, 0, g_fontengine->getTextWidth(text), g_fontengine->getTextHeight());
|
rect += v2s32(4, 0);
|
||||||
rect += v2s32(4, 0);
|
|
||||||
|
|
||||||
m_irr_toplefttext->remove();
|
m_irr_toplefttext->remove();
|
||||||
m_irr_toplefttext =
|
m_irr_toplefttext =
|
||||||
m_device->getGUIEnvironment()->addStaticText(text.c_str(),
|
addStaticText(m_device->getGUIEnvironment(), m_toplefttext,
|
||||||
rect,false,true,0,-1);
|
rect, false, true, 0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
|
@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "guiFormSpecMenu.h"
|
#include "guiFormSpecMenu.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "client/tile.h"
|
#include "client/tile.h"
|
||||||
|
#include "util/enriched_string.h"
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Typedefs and macros */
|
/* Typedefs and macros */
|
||||||
|
@ -275,6 +276,8 @@ private:
|
||||||
|
|
||||||
/** pointer to gui element shown at topleft corner */
|
/** pointer to gui element shown at topleft corner */
|
||||||
irr::gui::IGUIStaticText* m_irr_toplefttext;
|
irr::gui::IGUIStaticText* m_irr_toplefttext;
|
||||||
|
/** and text that is in it */
|
||||||
|
EnrichedString m_toplefttext;
|
||||||
|
|
||||||
/** initialize cloud subsystem */
|
/** initialize cloud subsystem */
|
||||||
void cloudInit();
|
void cloudInit();
|
||||||
|
|
|
@ -50,6 +50,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "util/hex.h"
|
#include "util/hex.h"
|
||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
#include "util/string.h" // for parseColorString()
|
#include "util/string.h" // for parseColorString()
|
||||||
|
#include "irrlicht_changes/static_text.h"
|
||||||
#include "guiscalingfilter.h"
|
#include "guiscalingfilter.h"
|
||||||
|
|
||||||
#if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9
|
#if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9
|
||||||
|
@ -249,37 +250,6 @@ std::vector<std::string>* GUIFormSpecMenu::getDropDownValues(const std::string &
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> split(const std::string &s, char delim)
|
|
||||||
{
|
|
||||||
std::vector<std::string> tokens;
|
|
||||||
|
|
||||||
std::string current = "";
|
|
||||||
bool last_was_escape = false;
|
|
||||||
for (unsigned int i = 0; i < s.size(); i++) {
|
|
||||||
char si = s.c_str()[i];
|
|
||||||
if (last_was_escape) {
|
|
||||||
current += '\\';
|
|
||||||
current += si;
|
|
||||||
last_was_escape = false;
|
|
||||||
} else {
|
|
||||||
if (si == delim) {
|
|
||||||
tokens.push_back(current);
|
|
||||||
current = "";
|
|
||||||
last_was_escape = false;
|
|
||||||
} else if (si == '\\') {
|
|
||||||
last_was_escape = true;
|
|
||||||
} else {
|
|
||||||
current += si;
|
|
||||||
last_was_escape = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//push last element
|
|
||||||
tokens.push_back(current);
|
|
||||||
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseSize(parserData* data,std::string element)
|
void GUIFormSpecMenu::parseSize(parserData* data,std::string element)
|
||||||
{
|
{
|
||||||
std::vector<std::string> parts = split(element,',');
|
std::vector<std::string> parts = split(element,',');
|
||||||
|
@ -966,7 +936,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element)
|
||||||
int font_height = g_fontengine->getTextHeight();
|
int font_height = g_fontengine->getTextHeight();
|
||||||
rect.UpperLeftCorner.Y -= font_height;
|
rect.UpperLeftCorner.Y -= font_height;
|
||||||
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;
|
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;
|
||||||
Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, 0);
|
addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
e->setPasswordBox(true,L'*');
|
e->setPasswordBox(true,L'*');
|
||||||
|
@ -1021,7 +991,7 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,
|
||||||
if (name == "")
|
if (name == "")
|
||||||
{
|
{
|
||||||
// spec field id to 0, this stops submit searching for a value that isn't there
|
// spec field id to 0, this stops submit searching for a value that isn't there
|
||||||
Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid);
|
addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, spec.fid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1056,7 +1026,7 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,
|
||||||
int font_height = g_fontengine->getTextHeight();
|
int font_height = g_fontengine->getTextHeight();
|
||||||
rect.UpperLeftCorner.Y -= font_height;
|
rect.UpperLeftCorner.Y -= font_height;
|
||||||
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;
|
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;
|
||||||
Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, 0);
|
addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1117,7 +1087,7 @@ void GUIFormSpecMenu::parseTextArea(parserData* data,
|
||||||
if (name == "")
|
if (name == "")
|
||||||
{
|
{
|
||||||
// spec field id to 0, this stops submit searching for a value that isn't there
|
// spec field id to 0, this stops submit searching for a value that isn't there
|
||||||
Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid);
|
addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, spec.fid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1161,7 +1131,7 @@ void GUIFormSpecMenu::parseTextArea(parserData* data,
|
||||||
int font_height = g_fontengine->getTextHeight();
|
int font_height = g_fontengine->getTextHeight();
|
||||||
rect.UpperLeftCorner.Y -= font_height;
|
rect.UpperLeftCorner.Y -= font_height;
|
||||||
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;
|
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height;
|
||||||
Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, 0);
|
addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
|
@ -1230,7 +1200,7 @@ void GUIFormSpecMenu::parseLabel(parserData* data,std::string element)
|
||||||
258+m_fields.size()
|
258+m_fields.size()
|
||||||
);
|
);
|
||||||
gui::IGUIStaticText *e =
|
gui::IGUIStaticText *e =
|
||||||
Environment->addStaticText(spec.flabel.c_str(),
|
addStaticText(Environment, spec.flabel.c_str(),
|
||||||
rect, false, false, this, spec.fid);
|
rect, false, false, this, spec.fid);
|
||||||
e->setTextAlignment(gui::EGUIA_UPPERLEFT,
|
e->setTextAlignment(gui::EGUIA_UPPERLEFT,
|
||||||
gui::EGUIA_CENTER);
|
gui::EGUIA_CENTER);
|
||||||
|
@ -1284,7 +1254,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element)
|
||||||
258+m_fields.size()
|
258+m_fields.size()
|
||||||
);
|
);
|
||||||
gui::IGUIStaticText *t =
|
gui::IGUIStaticText *t =
|
||||||
Environment->addStaticText(spec.flabel.c_str(), rect, false, false, this, spec.fid);
|
addStaticText(Environment, spec.flabel.c_str(), rect, false, false, this, spec.fid);
|
||||||
t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
|
t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
return;
|
return;
|
||||||
|
@ -1910,7 +1880,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||||
{
|
{
|
||||||
assert(m_tooltip_element == NULL);
|
assert(m_tooltip_element == NULL);
|
||||||
// Note: parent != this so that the tooltip isn't clipped by the menu rectangle
|
// Note: parent != this so that the tooltip isn't clipped by the menu rectangle
|
||||||
m_tooltip_element = Environment->addStaticText(L"",core::rect<s32>(0,0,110,18));
|
m_tooltip_element = addStaticText(Environment, L"",core::rect<s32>(0,0,110,18));
|
||||||
m_tooltip_element->enableOverrideColor(true);
|
m_tooltip_element->enableOverrideColor(true);
|
||||||
m_tooltip_element->setBackgroundColor(m_default_tooltip_bgcolor);
|
m_tooltip_element->setBackgroundColor(m_default_tooltip_bgcolor);
|
||||||
m_tooltip_element->setDrawBackground(true);
|
m_tooltip_element->setDrawBackground(true);
|
||||||
|
@ -2255,7 +2225,6 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase,
|
||||||
std::wstring tooltip_text = L"";
|
std::wstring tooltip_text = L"";
|
||||||
if (hovering && !m_selected_item) {
|
if (hovering && !m_selected_item) {
|
||||||
tooltip_text = utf8_to_wide(item.getDefinition(m_gamedef->idef()).description);
|
tooltip_text = utf8_to_wide(item.getDefinition(m_gamedef->idef()).description);
|
||||||
tooltip_text = unescape_enriched(tooltip_text);
|
|
||||||
}
|
}
|
||||||
if (tooltip_text != L"") {
|
if (tooltip_text != L"") {
|
||||||
std::vector<std::wstring> tt_rows = str_split(tooltip_text, L'\n');
|
std::vector<std::wstring> tt_rows = str_split(tooltip_text, L'\n');
|
||||||
|
@ -2263,7 +2232,7 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase,
|
||||||
m_tooltip_element->setOverrideColor(m_default_tooltip_color);
|
m_tooltip_element->setOverrideColor(m_default_tooltip_color);
|
||||||
m_tooltip_element->setVisible(true);
|
m_tooltip_element->setVisible(true);
|
||||||
this->bringToFront(m_tooltip_element);
|
this->bringToFront(m_tooltip_element);
|
||||||
m_tooltip_element->setText(tooltip_text.c_str());
|
setStaticText(m_tooltip_element, tooltip_text.c_str());
|
||||||
s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height;
|
s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height;
|
||||||
#if IRRLICHT_VERSION_MAJOR <= 1 && IRRLICHT_VERSION_MINOR <= 8 && IRRLICHT_VERSION_REVISION < 2
|
#if IRRLICHT_VERSION_MAJOR <= 1 && IRRLICHT_VERSION_MINOR <= 8 && IRRLICHT_VERSION_REVISION < 2
|
||||||
s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5;
|
s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5;
|
||||||
|
@ -2535,8 +2504,10 @@ void GUIFormSpecMenu::drawMenu()
|
||||||
iter != m_fields.end(); ++iter) {
|
iter != m_fields.end(); ++iter) {
|
||||||
if (iter->fid == id && m_tooltips[iter->fname].tooltip != L"") {
|
if (iter->fid == id && m_tooltips[iter->fname].tooltip != L"") {
|
||||||
if (m_old_tooltip != m_tooltips[iter->fname].tooltip) {
|
if (m_old_tooltip != m_tooltips[iter->fname].tooltip) {
|
||||||
|
m_tooltip_element->setBackgroundColor(m_tooltips[iter->fname].bgcolor);
|
||||||
|
m_tooltip_element->setOverrideColor(m_tooltips[iter->fname].color);
|
||||||
m_old_tooltip = m_tooltips[iter->fname].tooltip;
|
m_old_tooltip = m_tooltips[iter->fname].tooltip;
|
||||||
m_tooltip_element->setText(m_tooltips[iter->fname].tooltip.c_str());
|
setStaticText(m_tooltip_element, m_tooltips[iter->fname].tooltip.c_str());
|
||||||
std::vector<std::wstring> tt_rows = str_split(m_tooltips[iter->fname].tooltip, L'\n');
|
std::vector<std::wstring> tt_rows = str_split(m_tooltips[iter->fname].tooltip, L'\n');
|
||||||
s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height;
|
s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height;
|
||||||
s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5;
|
s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5;
|
||||||
|
@ -2558,8 +2529,6 @@ void GUIFormSpecMenu::drawMenu()
|
||||||
core::position2d<s32>(tooltip_x, tooltip_y),
|
core::position2d<s32>(tooltip_x, tooltip_y),
|
||||||
core::dimension2d<s32>(tooltip_width, tooltip_height)));
|
core::dimension2d<s32>(tooltip_width, tooltip_height)));
|
||||||
}
|
}
|
||||||
m_tooltip_element->setBackgroundColor(m_tooltips[iter->fname].bgcolor);
|
|
||||||
m_tooltip_element->setOverrideColor(m_tooltips[iter->fname].color);
|
|
||||||
m_tooltip_element->setVisible(true);
|
m_tooltip_element->setVisible(true);
|
||||||
this->bringToFront(m_tooltip_element);
|
this->bringToFront(m_tooltip_element);
|
||||||
break;
|
break;
|
||||||
|
@ -2568,6 +2537,8 @@ void GUIFormSpecMenu::drawMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_tooltip_element->draw();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Draw dragged item stack
|
Draw dragged item stack
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "guiTable.h"
|
#include "guiTable.h"
|
||||||
#include "network/networkprotocol.h"
|
#include "network/networkprotocol.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
#include "util/enriched_string.h"
|
||||||
|
|
||||||
class IGameDef;
|
class IGameDef;
|
||||||
class InventoryManager;
|
class InventoryManager;
|
||||||
|
@ -202,7 +203,8 @@ class GUIFormSpecMenu : public GUIModalMenu
|
||||||
fname(name),
|
fname(name),
|
||||||
fid(id)
|
fid(id)
|
||||||
{
|
{
|
||||||
flabel = unescape_enriched(label);
|
//flabel = unescape_enriched(label);
|
||||||
|
flabel = label;
|
||||||
fdefault = unescape_enriched(default_text);
|
fdefault = unescape_enriched(default_text);
|
||||||
send = false;
|
send = false;
|
||||||
ftype = f_Unknown;
|
ftype = f_Unknown;
|
||||||
|
@ -239,7 +241,8 @@ class GUIFormSpecMenu : public GUIModalMenu
|
||||||
bgcolor(a_bgcolor),
|
bgcolor(a_bgcolor),
|
||||||
color(a_color)
|
color(a_color)
|
||||||
{
|
{
|
||||||
tooltip = unescape_enriched(utf8_to_wide(a_tooltip));
|
//tooltip = unescape_enriched(utf8_to_wide(a_tooltip));
|
||||||
|
tooltip = utf8_to_wide(a_tooltip);
|
||||||
}
|
}
|
||||||
std::wstring tooltip;
|
std::wstring tooltip;
|
||||||
irr::video::SColor bgcolor;
|
irr::video::SColor bgcolor;
|
||||||
|
@ -256,7 +259,8 @@ class GUIFormSpecMenu : public GUIModalMenu
|
||||||
rect(a_rect),
|
rect(a_rect),
|
||||||
parent_button(NULL)
|
parent_button(NULL)
|
||||||
{
|
{
|
||||||
text = unescape_enriched(a_text);
|
//text = unescape_enriched(a_text);
|
||||||
|
text = a_text;
|
||||||
}
|
}
|
||||||
StaticTextSpec(const std::wstring &a_text,
|
StaticTextSpec(const std::wstring &a_text,
|
||||||
const core::rect<s32> &a_rect,
|
const core::rect<s32> &a_rect,
|
||||||
|
@ -264,7 +268,8 @@ class GUIFormSpecMenu : public GUIModalMenu
|
||||||
rect(a_rect),
|
rect(a_rect),
|
||||||
parent_button(a_parent_button)
|
parent_button(a_parent_button)
|
||||||
{
|
{
|
||||||
text = unescape_enriched(a_text);
|
//text = unescape_enriched(a_text);
|
||||||
|
text = a_text;
|
||||||
}
|
}
|
||||||
std::wstring text;
|
std::wstring text;
|
||||||
core::rect<s32> rect;
|
core::rect<s32> rect;
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
if (BUILD_CLIENT)
|
||||||
|
set(client_irrlicht_changes_SRCS
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/static_text.cpp
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||||
|
// Copyright (C) 2016 Nathanaël Courant:
|
||||||
|
// Modified the functions to use EnrichedText instead of string.
|
||||||
// This file is part of the "Irrlicht Engine".
|
// This file is part of the "Irrlicht Engine".
|
||||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||||
|
|
||||||
#include "statictext.h"
|
#include "static_text.h"
|
||||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||||
|
|
||||||
//Only compile this if freetype is enabled.
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -17,15 +17,21 @@
|
||||||
#include <rect.h>
|
#include <rect.h>
|
||||||
#include <SColor.h>
|
#include <SColor.h>
|
||||||
|
|
||||||
#include "cguittfont/xCGUITTFont.h"
|
#if USE_FREETYPE
|
||||||
|
#include "cguittfont/xCGUITTFont.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if USE_FREETYPE
|
||||||
|
|
||||||
namespace gui
|
namespace gui
|
||||||
{
|
{
|
||||||
//! constructor
|
//! constructor
|
||||||
StaticText::StaticText(const wchar_t* text, bool border,
|
StaticText::StaticText(const EnrichedString &text, bool border,
|
||||||
IGUIEnvironment* environment, IGUIElement* parent,
|
IGUIEnvironment* environment, IGUIElement* parent,
|
||||||
s32 id, const core::rect<s32>& rectangle,
|
s32 id, const core::rect<s32>& rectangle,
|
||||||
bool background)
|
bool background)
|
||||||
|
@ -40,7 +46,8 @@ StaticText::StaticText(const wchar_t* text, bool border,
|
||||||
setDebugName("StaticText");
|
setDebugName("StaticText");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Text = text;
|
Text = text.c_str();
|
||||||
|
cText = text;
|
||||||
if (environment && environment->getSkin())
|
if (environment && environment->getSkin())
|
||||||
{
|
{
|
||||||
BGColor = environment->getSkin()->getColor(gui::EGDC_3D_FACE);
|
BGColor = environment->getSkin()->getColor(gui::EGDC_3D_FACE);
|
||||||
|
@ -55,7 +62,6 @@ StaticText::~StaticText()
|
||||||
OverrideFont->drop();
|
OverrideFont->drop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! draws the element and its children
|
//! draws the element and its children
|
||||||
void StaticText::draw()
|
void StaticText::draw()
|
||||||
{
|
{
|
||||||
|
@ -88,7 +94,7 @@ void StaticText::draw()
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw the text
|
// draw the text
|
||||||
if (Text.size())
|
if (cText.size())
|
||||||
{
|
{
|
||||||
IGUIFont* font = getActiveFont();
|
IGUIFont* font = getActiveFont();
|
||||||
|
|
||||||
|
@ -105,10 +111,11 @@ void StaticText::draw()
|
||||||
if (HAlign == EGUIA_LOWERRIGHT)
|
if (HAlign == EGUIA_LOWERRIGHT)
|
||||||
{
|
{
|
||||||
frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
|
frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X -
|
||||||
font->getDimension(Text.c_str()).Width;
|
font->getDimension(cText.c_str()).Width;
|
||||||
}
|
}
|
||||||
|
|
||||||
font->draw(Text.c_str(), frameRect,
|
irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font);
|
||||||
|
tmp->draw(cText, frameRect,
|
||||||
OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
|
OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
|
||||||
HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
|
HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
|
||||||
}
|
}
|
||||||
|
@ -138,16 +145,17 @@ void StaticText::draw()
|
||||||
font->getDimension(BrokenText[i].c_str()).Width;
|
font->getDimension(BrokenText[i].c_str()).Width;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<irr::video::SColor> colors;
|
//std::vector<irr::video::SColor> colors;
|
||||||
std::wstring str;
|
//std::wstring str;
|
||||||
|
EnrichedString str = BrokenText[i];
|
||||||
|
|
||||||
str = colorizeText(BrokenText[i].c_str(), colors, previous_color);
|
//str = colorizeText(BrokenText[i].c_str(), colors, previous_color);
|
||||||
if (!colors.empty())
|
//if (!colors.empty())
|
||||||
previous_color = colors[colors.size() - 1];
|
// previous_color = colors[colors.size() - 1];
|
||||||
|
|
||||||
irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font);
|
irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font);
|
||||||
tmp->draw(str.c_str(), r,
|
tmp->draw(str, r,
|
||||||
colors,
|
previous_color, // FIXME
|
||||||
HAlign == EGUIA_CENTER, false, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
|
HAlign == EGUIA_CENTER, false, (RestrainTextInside ? &AbsoluteClippingRect : NULL));
|
||||||
|
|
||||||
r.LowerRightCorner.Y += height;
|
r.LowerRightCorner.Y += height;
|
||||||
|
@ -340,17 +348,17 @@ void StaticText::breakText()
|
||||||
|
|
||||||
LastBreakFont = font;
|
LastBreakFont = font;
|
||||||
|
|
||||||
core::stringw line;
|
EnrichedString line;
|
||||||
core::stringw word;
|
EnrichedString word;
|
||||||
core::stringw whitespace;
|
EnrichedString whitespace;
|
||||||
s32 size = Text.size();
|
s32 size = cText.size();
|
||||||
s32 length = 0;
|
s32 length = 0;
|
||||||
s32 elWidth = RelativeRect.getWidth();
|
s32 elWidth = RelativeRect.getWidth();
|
||||||
if (Border)
|
if (Border)
|
||||||
elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X);
|
elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X);
|
||||||
wchar_t c;
|
wchar_t c;
|
||||||
|
|
||||||
std::vector<irr::video::SColor> colors;
|
//std::vector<irr::video::SColor> colors;
|
||||||
|
|
||||||
// We have to deal with right-to-left and left-to-right differently
|
// We have to deal with right-to-left and left-to-right differently
|
||||||
// However, most parts of the following code is the same, it's just
|
// However, most parts of the following code is the same, it's just
|
||||||
|
@ -360,17 +368,17 @@ void StaticText::breakText()
|
||||||
// regular (left-to-right)
|
// regular (left-to-right)
|
||||||
for (s32 i=0; i<size; ++i)
|
for (s32 i=0; i<size; ++i)
|
||||||
{
|
{
|
||||||
c = Text[i];
|
c = cText.getString()[i];
|
||||||
bool lineBreak = false;
|
bool lineBreak = false;
|
||||||
|
|
||||||
if (c == L'\r') // Mac or Windows breaks
|
if (c == L'\r') // Mac or Windows breaks
|
||||||
{
|
{
|
||||||
lineBreak = true;
|
lineBreak = true;
|
||||||
if (Text[i+1] == L'\n') // Windows breaks
|
//if (Text[i+1] == L'\n') // Windows breaks
|
||||||
{
|
//{
|
||||||
Text.erase(i+1);
|
// Text.erase(i+1);
|
||||||
--size;
|
// --size;
|
||||||
}
|
//}
|
||||||
c = '\0';
|
c = '\0';
|
||||||
}
|
}
|
||||||
else if (c == L'\n') // Unix breaks
|
else if (c == L'\n') // Unix breaks
|
||||||
|
@ -383,7 +391,8 @@ void StaticText::breakText()
|
||||||
if ( !isWhitespace )
|
if ( !isWhitespace )
|
||||||
{
|
{
|
||||||
// part of a word
|
// part of a word
|
||||||
word += c;
|
//word += c;
|
||||||
|
word.addChar(cText, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isWhitespace || i == (size-1))
|
if ( isWhitespace || i == (size-1))
|
||||||
|
@ -393,20 +402,21 @@ void StaticText::breakText()
|
||||||
// here comes the next whitespace, look if
|
// here comes the next whitespace, look if
|
||||||
// we must break the last word to the next line.
|
// we must break the last word to the next line.
|
||||||
const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
|
const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
|
||||||
const std::wstring sanitized = removeEscapes(word.c_str());
|
//const std::wstring sanitized = removeEscapes(word.c_str());
|
||||||
const s32 wordlgth = font->getDimension(sanitized.c_str()).Width;
|
const s32 wordlgth = font->getDimension(word.c_str()).Width;
|
||||||
|
|
||||||
if (wordlgth > elWidth)
|
if (wordlgth > elWidth)
|
||||||
{
|
{
|
||||||
// This word is too long to fit in the available space, look for
|
// This word is too long to fit in the available space, look for
|
||||||
// the Unicode Soft HYphen (SHY / 00AD) character for a place to
|
// the Unicode Soft HYphen (SHY / 00AD) character for a place to
|
||||||
// break the word at
|
// break the word at
|
||||||
int where = word.findFirst( wchar_t(0x00AD) );
|
int where = core::stringw(word.c_str()).findFirst( wchar_t(0x00AD) );
|
||||||
if (where != -1)
|
if (where != -1)
|
||||||
{
|
{
|
||||||
core::stringw first = word.subString(0, where);
|
EnrichedString first = word.substr(0, where);
|
||||||
core::stringw second = word.subString(where, word.size() - where);
|
EnrichedString second = word.substr(where, word.size() - where);
|
||||||
BrokenText.push_back(line + first + L"-");
|
first.addCharNoColor(L'-');
|
||||||
|
BrokenText.push_back(line + first);
|
||||||
const s32 secondLength = font->getDimension(second.c_str()).Width;
|
const s32 secondLength = font->getDimension(second.c_str()).Width;
|
||||||
|
|
||||||
length = secondLength;
|
length = secondLength;
|
||||||
|
@ -437,13 +447,13 @@ void StaticText::breakText()
|
||||||
length += whitelgth + wordlgth;
|
length += whitelgth + wordlgth;
|
||||||
}
|
}
|
||||||
|
|
||||||
word = L"";
|
word.clear();
|
||||||
whitespace = L"";
|
whitespace.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isWhitespace )
|
if ( isWhitespace && c != 0)
|
||||||
{
|
{
|
||||||
whitespace += c;
|
whitespace.addChar(cText, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute line break
|
// compute line break
|
||||||
|
@ -452,9 +462,9 @@ void StaticText::breakText()
|
||||||
line += whitespace;
|
line += whitespace;
|
||||||
line += word;
|
line += word;
|
||||||
BrokenText.push_back(line);
|
BrokenText.push_back(line);
|
||||||
line = L"";
|
line.clear();
|
||||||
word = L"";
|
word.clear();
|
||||||
whitespace = L"";
|
whitespace.clear();
|
||||||
length = 0;
|
length = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,17 +479,17 @@ void StaticText::breakText()
|
||||||
// right-to-left
|
// right-to-left
|
||||||
for (s32 i=size; i>=0; --i)
|
for (s32 i=size; i>=0; --i)
|
||||||
{
|
{
|
||||||
c = Text[i];
|
c = cText.getString()[i];
|
||||||
bool lineBreak = false;
|
bool lineBreak = false;
|
||||||
|
|
||||||
if (c == L'\r') // Mac or Windows breaks
|
if (c == L'\r') // Mac or Windows breaks
|
||||||
{
|
{
|
||||||
lineBreak = true;
|
lineBreak = true;
|
||||||
if ((i>0) && Text[i-1] == L'\n') // Windows breaks
|
//if ((i>0) && Text[i-1] == L'\n') // Windows breaks
|
||||||
{
|
//{
|
||||||
Text.erase(i-1);
|
// Text.erase(i-1);
|
||||||
--size;
|
// --size;
|
||||||
}
|
//}
|
||||||
c = '\0';
|
c = '\0';
|
||||||
}
|
}
|
||||||
else if (c == L'\n') // Unix breaks
|
else if (c == L'\n') // Unix breaks
|
||||||
|
@ -512,12 +522,13 @@ void StaticText::breakText()
|
||||||
length += whitelgth + wordlgth;
|
length += whitelgth + wordlgth;
|
||||||
}
|
}
|
||||||
|
|
||||||
word = L"";
|
word.clear();
|
||||||
whitespace = L"";
|
whitespace.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c != 0)
|
if (c != 0)
|
||||||
whitespace = core::stringw(&c, 1) + whitespace;
|
// whitespace = core::stringw(&c, 1) + whitespace;
|
||||||
|
whitespace = cText.substr(i, 1) + whitespace;
|
||||||
|
|
||||||
// compute line break
|
// compute line break
|
||||||
if (lineBreak)
|
if (lineBreak)
|
||||||
|
@ -525,16 +536,17 @@ void StaticText::breakText()
|
||||||
line = whitespace + line;
|
line = whitespace + line;
|
||||||
line = word + line;
|
line = word + line;
|
||||||
BrokenText.push_back(line);
|
BrokenText.push_back(line);
|
||||||
line = L"";
|
line.clear();
|
||||||
word = L"";
|
word.clear();
|
||||||
whitespace = L"";
|
whitespace.clear();
|
||||||
length = 0;
|
length = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// yippee this is a word..
|
// yippee this is a word..
|
||||||
word = core::stringw(&c, 1) + word;
|
//word = core::stringw(&c, 1) + word;
|
||||||
|
word = cText.substr(i, 1) + word;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,7 +560,17 @@ void StaticText::breakText()
|
||||||
//! Sets the new caption of this element.
|
//! Sets the new caption of this element.
|
||||||
void StaticText::setText(const wchar_t* text)
|
void StaticText::setText(const wchar_t* text)
|
||||||
{
|
{
|
||||||
IGUIElement::setText(text);
|
setText(EnrichedString(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Sets the new caption of this element.
|
||||||
|
void StaticText::setText(const EnrichedString &text)
|
||||||
|
{
|
||||||
|
IGUIElement::setText(text.c_str());
|
||||||
|
cText = text;
|
||||||
|
if (text.hasBackground()) {
|
||||||
|
setBackgroundColor(text.getBackground());
|
||||||
|
}
|
||||||
breakText();
|
breakText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +620,7 @@ s32 StaticText::getTextWidth() const
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return font->getDimension(Text.c_str()).Width;
|
return font->getDimension(cText.c_str()).Width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,6 +670,9 @@ void StaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWr
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace gui
|
} // end namespace gui
|
||||||
|
|
||||||
|
#endif // USE_FREETYPE
|
||||||
|
|
||||||
} // end namespace irr
|
} // end namespace irr
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||||
|
// Copyright (C) 2016 Nathanaël Courant
|
||||||
|
// Modified this class to work with EnrichedStrings too
|
||||||
// This file is part of the "Irrlicht Engine".
|
// This file is part of the "Irrlicht Engine".
|
||||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||||
|
|
||||||
|
@ -11,18 +13,30 @@
|
||||||
#include "IGUIStaticText.h"
|
#include "IGUIStaticText.h"
|
||||||
#include "irrArray.h"
|
#include "irrArray.h"
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "util/enriched_string.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include <IGUIEnvironment.h>
|
||||||
|
|
||||||
|
#if USE_FREETYPE
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace gui
|
namespace gui
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const EGUI_ELEMENT_TYPE EGUIET_ENRICHED_STATIC_TEXT = (EGUI_ELEMENT_TYPE)(0x1000);
|
||||||
|
|
||||||
class StaticText : public IGUIStaticText
|
class StaticText : public IGUIStaticText
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! constructor
|
//! constructor
|
||||||
StaticText(const wchar_t* text, bool border, IGUIEnvironment* environment,
|
StaticText(const EnrichedString &text, bool border, IGUIEnvironment* environment,
|
||||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle,
|
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle,
|
||||||
bool background = false);
|
bool background = false);
|
||||||
|
|
||||||
|
@ -121,6 +135,16 @@ namespace gui
|
||||||
//! Reads attributes of the element
|
//! Reads attributes of the element
|
||||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||||
|
|
||||||
|
virtual bool hasType(EGUI_ELEMENT_TYPE t) const {
|
||||||
|
return (t == EGUIET_ENRICHED_STATIC_TEXT) || (t == EGUIET_STATIC_TEXT);
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual bool hasType(EGUI_ELEMENT_TYPE t) {
|
||||||
|
return (t == EGUIET_ENRICHED_STATIC_TEXT) || (t == EGUIET_STATIC_TEXT);
|
||||||
|
};
|
||||||
|
|
||||||
|
void setText(const EnrichedString &text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//! Breaks the single text line.
|
//! Breaks the single text line.
|
||||||
|
@ -139,12 +163,106 @@ namespace gui
|
||||||
gui::IGUIFont* OverrideFont;
|
gui::IGUIFont* OverrideFont;
|
||||||
gui::IGUIFont* LastBreakFont; // stored because: if skin changes, line break must be recalculated.
|
gui::IGUIFont* LastBreakFont; // stored because: if skin changes, line break must be recalculated.
|
||||||
|
|
||||||
core::array< core::stringw > BrokenText;
|
EnrichedString cText;
|
||||||
|
core::array< EnrichedString > BrokenText;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // end namespace gui
|
} // end namespace gui
|
||||||
|
|
||||||
} // end namespace irr
|
} // end namespace irr
|
||||||
|
|
||||||
|
inline irr::gui::IGUIStaticText *addStaticText(
|
||||||
|
irr::gui::IGUIEnvironment *guienv,
|
||||||
|
const EnrichedString &text,
|
||||||
|
const core::rect< s32 > &rectangle,
|
||||||
|
bool border = false,
|
||||||
|
bool wordWrap = true,
|
||||||
|
irr::gui::IGUIElement *parent = NULL,
|
||||||
|
s32 id = -1,
|
||||||
|
bool fillBackground = false)
|
||||||
|
{
|
||||||
|
if (parent == NULL) {
|
||||||
|
// parent is NULL, so we must find one, or we need not to drop
|
||||||
|
// result, but then there will be a memory leak.
|
||||||
|
//
|
||||||
|
// What Irrlicht does is to use guienv as a parent, but the problem
|
||||||
|
// is that guienv is here only an IGUIEnvironment, while it is a
|
||||||
|
// CGUIEnvironment in Irrlicht, which inherits from both IGUIElement
|
||||||
|
// and IGUIEnvironment.
|
||||||
|
//
|
||||||
|
// A solution would be to dynamic_cast guienv to a
|
||||||
|
// IGUIElement*, but Irrlicht is shipped without rtti support
|
||||||
|
// in some distributions, causing the dymanic_cast to segfault.
|
||||||
|
//
|
||||||
|
// Thus, to find the parent, we create a dummy StaticText and ask
|
||||||
|
// for its parent, and then remove it.
|
||||||
|
irr::gui::IGUIStaticText *dummy_text =
|
||||||
|
guienv->addStaticText(L"", rectangle, border, wordWrap,
|
||||||
|
parent, id, fillBackground);
|
||||||
|
parent = dummy_text->getParent();
|
||||||
|
dummy_text->remove();
|
||||||
|
}
|
||||||
|
irr::gui::IGUIStaticText *result = new irr::gui::StaticText(
|
||||||
|
text, border, guienv, parent,
|
||||||
|
id, rectangle, fillBackground);
|
||||||
|
|
||||||
|
result->setWordWrap(wordWrap);
|
||||||
|
result->drop();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setStaticText(irr::gui::IGUIStaticText *static_text, const EnrichedString &text)
|
||||||
|
{
|
||||||
|
// dynamic_cast not possible due to some distributions shipped
|
||||||
|
// without rtti support in irrlicht
|
||||||
|
if (static_text->hasType(irr::gui::EGUIET_ENRICHED_STATIC_TEXT)) {
|
||||||
|
irr::gui::StaticText* stext = static_cast<irr::gui::StaticText*>(static_text);
|
||||||
|
stext->setText(text);
|
||||||
|
} else {
|
||||||
|
static_text->setText(text.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // USE_FREETYPE
|
||||||
|
|
||||||
|
inline irr::gui::IGUIStaticText *addStaticText(
|
||||||
|
irr::gui::IGUIEnvironment *guienv,
|
||||||
|
const EnrichedString &text,
|
||||||
|
const core::rect< s32 > &rectangle,
|
||||||
|
bool border = false,
|
||||||
|
bool wordWrap = true,
|
||||||
|
irr::gui::IGUIElement *parent = NULL,
|
||||||
|
s32 id = -1,
|
||||||
|
bool fillBackground = false)
|
||||||
|
{
|
||||||
|
return guienv->addStaticText(text.c_str(), rectangle, border, wordWrap, parent, id, fillBackground);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setStaticText(irr::gui::IGUIStaticText *static_text, const EnrichedString &text)
|
||||||
|
{
|
||||||
|
static_text->setText(text.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline irr::gui::IGUIStaticText *addStaticText(
|
||||||
|
irr::gui::IGUIEnvironment *guienv,
|
||||||
|
const wchar_t *text,
|
||||||
|
const core::rect< s32 > &rectangle,
|
||||||
|
bool border = false,
|
||||||
|
bool wordWrap = true,
|
||||||
|
irr::gui::IGUIElement *parent = NULL,
|
||||||
|
s32 id = -1,
|
||||||
|
bool fillBackground = false) {
|
||||||
|
return addStaticText(guienv, EnrichedString(text), rectangle, border, wordWrap, parent, id, fillBackground);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setStaticText(irr::gui::IGUIStaticText *static_text, const wchar_t *text)
|
||||||
|
{
|
||||||
|
setStaticText(static_text, EnrichedString(text));
|
||||||
|
}
|
||||||
|
|
||||||
#endif // _IRR_COMPILE_WITH_GUI_
|
#endif // _IRR_COMPILE_WITH_GUI_
|
||||||
|
|
||||||
#endif // C_GUI_STATIC_TEXT_H_INCLUDED
|
#endif // C_GUI_STATIC_TEXT_H_INCLUDED
|
|
@ -345,9 +345,11 @@ void TerminalChatConsole::step(int ch)
|
||||||
if (p.first > m_log_level)
|
if (p.first > m_log_level)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
m_chat_backend.addMessage(
|
std::wstring error_message = utf8_to_wide(Logger::getLevelLabel(p.first));
|
||||||
utf8_to_wide(Logger::getLevelLabel(p.first)),
|
if (!g_settings->getBool("disable_escape_sequences")) {
|
||||||
utf8_to_wide(p.second));
|
error_message = L"\x1b(c@red)" + error_message + L"\x1b(c@white)";
|
||||||
|
}
|
||||||
|
m_chat_backend.addMessage(error_message, utf8_to_wide(p.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle input
|
// handle input
|
||||||
|
@ -438,7 +440,7 @@ void TerminalChatConsole::draw_text()
|
||||||
continue;
|
continue;
|
||||||
for (u32 i = 0; i < line.fragments.size(); ++i) {
|
for (u32 i = 0; i < line.fragments.size(); ++i) {
|
||||||
const ChatFormattedFragment& fragment = line.fragments[i];
|
const ChatFormattedFragment& fragment = line.fragments[i];
|
||||||
addstr(wide_to_utf8(fragment.text).c_str());
|
addstr(wide_to_utf8(fragment.text.getString()).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
if(USE_FREETYPE)
|
|
||||||
set(UTIL_FREETYPEDEP_SRCS
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/statictext.cpp
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
set(UTIL_FREETYPEDEP_SRCS )
|
|
||||||
endif(USE_FREETYPE)
|
|
||||||
|
|
||||||
set(UTIL_SRCS
|
set(UTIL_SRCS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/areastore.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/areastore.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/auth.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/auth.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/coloredstring.cpp
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/enriched_string.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/serialize.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/serialize.cpp
|
||||||
|
@ -20,6 +12,5 @@ set(UTIL_SRCS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/string.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/string.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/srp.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/srp.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/timetaker.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/timetaker.cpp
|
||||||
${UTIL_FREETYPEDEP_SRCS}
|
|
||||||
PARENT_SCOPE)
|
PARENT_SCOPE)
|
||||||
|
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "coloredstring.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
|
|
||||||
ColoredString::ColoredString()
|
|
||||||
{}
|
|
||||||
|
|
||||||
ColoredString::ColoredString(const std::wstring &string, const std::vector<SColor> &colors):
|
|
||||||
m_string(string),
|
|
||||||
m_colors(colors)
|
|
||||||
{}
|
|
||||||
|
|
||||||
ColoredString::ColoredString(const std::wstring &s) {
|
|
||||||
m_string = colorizeText(s, m_colors, SColor(255, 255, 255, 255));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ColoredString::operator=(const wchar_t *str) {
|
|
||||||
m_string = colorizeText(str, m_colors, SColor(255, 255, 255, 255));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ColoredString::size() const {
|
|
||||||
return m_string.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
ColoredString ColoredString::substr(size_t pos, size_t len) const {
|
|
||||||
if (pos == m_string.length())
|
|
||||||
return ColoredString();
|
|
||||||
if (len == std::string::npos || pos + len > m_string.length()) {
|
|
||||||
return ColoredString(
|
|
||||||
m_string.substr(pos, std::string::npos),
|
|
||||||
std::vector<SColor>(m_colors.begin() + pos, m_colors.end())
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return ColoredString(
|
|
||||||
m_string.substr(pos, len),
|
|
||||||
std::vector<SColor>(m_colors.begin() + pos, m_colors.begin() + pos + len)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const wchar_t *ColoredString::c_str() const {
|
|
||||||
return m_string.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<SColor> &ColoredString::getColors() const {
|
|
||||||
return m_colors;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::wstring &ColoredString::getString() const {
|
|
||||||
return m_string;
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef COLOREDSTRING_HEADER
|
|
||||||
#define COLOREDSTRING_HEADER
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <SColor.h>
|
|
||||||
|
|
||||||
using namespace irr::video;
|
|
||||||
|
|
||||||
class ColoredString {
|
|
||||||
public:
|
|
||||||
ColoredString();
|
|
||||||
ColoredString(const std::wstring &s);
|
|
||||||
ColoredString(const std::wstring &string, const std::vector<SColor> &colors);
|
|
||||||
void operator=(const wchar_t *str);
|
|
||||||
size_t size() const;
|
|
||||||
ColoredString substr(size_t pos = 0, size_t len = std::string::npos) const;
|
|
||||||
const wchar_t *c_str() const;
|
|
||||||
const std::vector<SColor> &getColors() const;
|
|
||||||
const std::wstring &getString() const;
|
|
||||||
private:
|
|
||||||
std::wstring m_string;
|
|
||||||
std::vector<SColor> m_colors;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is>
|
||||||
|
Copyright (C) 2016 Nore, Nathanaël Courant <nore@mesecons.net>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "enriched_string.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
#include "log.h"
|
||||||
|
using namespace irr::video;
|
||||||
|
|
||||||
|
EnrichedString::EnrichedString()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
EnrichedString::EnrichedString(const std::wstring &string,
|
||||||
|
const std::vector<SColor> &colors):
|
||||||
|
m_string(string),
|
||||||
|
m_colors(colors),
|
||||||
|
m_has_background(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
EnrichedString::EnrichedString(const std::wstring &s, const SColor &color)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
addAtEnd(s, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnrichedString::EnrichedString(const wchar_t *str, const SColor &color)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
addAtEnd(std::wstring(str), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnrichedString::operator=(const wchar_t *str)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
addAtEnd(std::wstring(str), SColor(255, 255, 255, 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnrichedString::addAtEnd(const std::wstring &s, const SColor &initial_color)
|
||||||
|
{
|
||||||
|
SColor color(initial_color);
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < s.length()) {
|
||||||
|
if (s[i] != L'\x1b') {
|
||||||
|
m_string += s[i];
|
||||||
|
m_colors.push_back(color);
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
size_t start_index = i;
|
||||||
|
size_t length;
|
||||||
|
if (i == s.length()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (s[i] == L'(') {
|
||||||
|
++i;
|
||||||
|
++start_index;
|
||||||
|
while (i < s.length() && s[i] != L')') {
|
||||||
|
if (s[i] == L'\\') {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
length = i - start_index;
|
||||||
|
++i;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
length = 1;
|
||||||
|
}
|
||||||
|
std::wstring escape_sequence(s, start_index, length);
|
||||||
|
std::vector<std::wstring> parts = split(escape_sequence, L'@');
|
||||||
|
if (parts[0] == L"c") {
|
||||||
|
if (parts.size() < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parseColorString(wide_to_utf8(parts[1]), color, true);
|
||||||
|
} else if (parts[0] == L"b") {
|
||||||
|
if (parts.size() < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parseColorString(wide_to_utf8(parts[1]), m_background, true);
|
||||||
|
m_has_background = true;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnrichedString::addChar(const EnrichedString &source, size_t i)
|
||||||
|
{
|
||||||
|
m_string += source.m_string[i];
|
||||||
|
m_colors.push_back(source.m_colors[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnrichedString::addCharNoColor(wchar_t c)
|
||||||
|
{
|
||||||
|
m_string += c;
|
||||||
|
if (m_colors.empty()) {
|
||||||
|
m_colors.push_back(SColor(255, 255, 255, 255));
|
||||||
|
} else {
|
||||||
|
m_colors.push_back(m_colors[m_colors.size() - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EnrichedString EnrichedString::operator+(const EnrichedString &other) const
|
||||||
|
{
|
||||||
|
std::vector<SColor> result;
|
||||||
|
result.insert(result.end(), m_colors.begin(), m_colors.end());
|
||||||
|
result.insert(result.end(), other.m_colors.begin(), other.m_colors.end());
|
||||||
|
return EnrichedString(m_string + other.m_string, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnrichedString::operator+=(const EnrichedString &other)
|
||||||
|
{
|
||||||
|
m_string += other.m_string;
|
||||||
|
m_colors.insert(m_colors.end(), other.m_colors.begin(), other.m_colors.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
EnrichedString EnrichedString::substr(size_t pos, size_t len) const
|
||||||
|
{
|
||||||
|
if (pos == m_string.length()) {
|
||||||
|
return EnrichedString();
|
||||||
|
}
|
||||||
|
if (len == std::string::npos || pos + len > m_string.length()) {
|
||||||
|
return EnrichedString(
|
||||||
|
m_string.substr(pos, std::string::npos),
|
||||||
|
std::vector<SColor>(m_colors.begin() + pos, m_colors.end())
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return EnrichedString(
|
||||||
|
m_string.substr(pos, len),
|
||||||
|
std::vector<SColor>(m_colors.begin() + pos, m_colors.begin() + pos + len)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wchar_t *EnrichedString::c_str() const
|
||||||
|
{
|
||||||
|
return m_string.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<SColor> &EnrichedString::getColors() const
|
||||||
|
{
|
||||||
|
return m_colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::wstring &EnrichedString::getString() const
|
||||||
|
{
|
||||||
|
return m_string;
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is>
|
||||||
|
Copyright (C) 2016 Nore, Nathanaël Courant <nore@mesecons.net>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ENRICHEDSTRING_HEADER
|
||||||
|
#define ENRICHEDSTRING_HEADER
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <SColor.h>
|
||||||
|
|
||||||
|
class EnrichedString {
|
||||||
|
public:
|
||||||
|
EnrichedString();
|
||||||
|
EnrichedString(const std::wstring &s,
|
||||||
|
const irr::video::SColor &color = irr::video::SColor(255, 255, 255, 255));
|
||||||
|
EnrichedString(const wchar_t *str,
|
||||||
|
const irr::video::SColor &color = irr::video::SColor(255, 255, 255, 255));
|
||||||
|
EnrichedString(const std::wstring &string,
|
||||||
|
const std::vector<irr::video::SColor> &colors);
|
||||||
|
void operator=(const wchar_t *str);
|
||||||
|
void addAtEnd(const std::wstring &s, const irr::video::SColor &color);
|
||||||
|
|
||||||
|
// Adds the character source[i] at the end.
|
||||||
|
// An EnrichedString should always be able to be copied
|
||||||
|
// to the end of an existing EnrichedString that way.
|
||||||
|
void addChar(const EnrichedString &source, size_t i);
|
||||||
|
|
||||||
|
// Adds a single character at the end, without specifying its
|
||||||
|
// color. The color used will be the one from the last character.
|
||||||
|
void addCharNoColor(wchar_t c);
|
||||||
|
|
||||||
|
EnrichedString substr(size_t pos = 0, size_t len = std::string::npos) const;
|
||||||
|
EnrichedString operator+(const EnrichedString &other) const;
|
||||||
|
void operator+=(const EnrichedString &other);
|
||||||
|
const wchar_t *c_str() const;
|
||||||
|
const std::vector<irr::video::SColor> &getColors() const;
|
||||||
|
const std::wstring &getString() const;
|
||||||
|
inline bool operator==(const EnrichedString &other) const
|
||||||
|
{
|
||||||
|
return (m_string == other.m_string && m_colors == other.m_colors);
|
||||||
|
}
|
||||||
|
inline bool operator!=(const EnrichedString &other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
inline void clear()
|
||||||
|
{
|
||||||
|
m_string.clear();
|
||||||
|
m_colors.clear();
|
||||||
|
m_has_background = false;
|
||||||
|
}
|
||||||
|
inline bool empty() const
|
||||||
|
{
|
||||||
|
return m_string.empty();
|
||||||
|
}
|
||||||
|
inline size_t size() const
|
||||||
|
{
|
||||||
|
return m_string.size();
|
||||||
|
}
|
||||||
|
inline bool hasBackground() const
|
||||||
|
{
|
||||||
|
return m_has_background;
|
||||||
|
}
|
||||||
|
inline irr::video::SColor getBackground() const
|
||||||
|
{
|
||||||
|
return m_background;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::wstring m_string;
|
||||||
|
std::vector<irr::video::SColor> m_colors;
|
||||||
|
bool m_has_background;
|
||||||
|
irr::video::SColor m_background;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -519,6 +519,38 @@ std::basic_string<T> unescape_enriched(const std::basic_string<T> &s)
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::vector<std::basic_string<T> > split(const std::basic_string<T> &s, T delim)
|
||||||
|
{
|
||||||
|
std::vector<std::basic_string<T> > tokens;
|
||||||
|
|
||||||
|
std::basic_string<T> current;
|
||||||
|
bool last_was_escape = false;
|
||||||
|
for (size_t i = 0; i < s.length(); i++) {
|
||||||
|
T si = s[i];
|
||||||
|
if (last_was_escape) {
|
||||||
|
current += '\\';
|
||||||
|
current += si;
|
||||||
|
last_was_escape = false;
|
||||||
|
} else {
|
||||||
|
if (si == delim) {
|
||||||
|
tokens.push_back(current);
|
||||||
|
current = std::basic_string<T>();
|
||||||
|
last_was_escape = false;
|
||||||
|
} else if (si == '\\') {
|
||||||
|
last_was_escape = true;
|
||||||
|
} else {
|
||||||
|
current += si;
|
||||||
|
last_was_escape = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//push last element
|
||||||
|
tokens.push_back(current);
|
||||||
|
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that all characters in \p to_check are a decimal digits.
|
* Checks that all characters in \p to_check are a decimal digits.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue