/* Minetest Copyright (C) 2013 celeron55, Perttu Ahola 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. */ #pragma once #include #include #include #include "irrlichttypes.h" #include "util/enriched_string.h" #include "settings.h" // Chat console related classes struct ChatLine { // age in seconds f32 age = 0.0f; // name of sending player, or empty if sent by server EnrichedString name; // message text EnrichedString text; ChatLine(const std::wstring &a_name, const std::wstring &a_text): name(a_name), text(a_text) { } ChatLine(const EnrichedString &a_name, const EnrichedString &a_text): name(a_name), text(a_text) { } }; struct ChatFormattedFragment { // text string EnrichedString text; // starting column u32 column; // formatting //u8 bold:1; }; struct ChatFormattedLine { // Array of text fragments std::vector fragments; // true if first line of one formatted ChatLine bool first; }; class ChatBuffer { public: ChatBuffer(u32 scrollback); ~ChatBuffer() = default; // Append chat line // Removes oldest chat line if scrollback size is reached void addLine(const std::wstring &name, const std::wstring &text); // Remove all chat lines void clear(); // Get number of lines currently in buffer. u32 getLineCount() const; // Get reference to i-th chat line. const ChatLine& getLine(u32 index) const; // Increase each chat line's age by dtime. void step(f32 dtime); // Delete oldest N chat lines. void deleteOldest(u32 count); // Delete lines older than maxAge. void deleteByAge(f32 maxAge); // Get number of columns, 0 if reformat has not been called yet. u32 getColumns() const; // Get number of rows, 0 if reformat has not been called yet. u32 getRows() const; // Update console size and reformat all formatted lines. void reformat(u32 cols, u32 rows); // Get formatted line for a given row (0 is top of screen). // Only valid after reformat has been called at least once const ChatFormattedLine& getFormattedLine(u32 row) const; // Scrolling in formatted buffer (relative) // positive rows == scroll up, negative rows == scroll down void scroll(s32 rows); // Scrolling in formatted buffer (absolute) void scrollAbsolute(s32 scroll); // Scroll to bottom of buffer (newest) void scrollBottom(); // Scroll to top of buffer (oldest) void scrollTop(); // Format a chat line for the given number of columns. // Appends the formatted lines to the destination array and // returns the number of formatted lines. u32 formatChatLine(const ChatLine& line, u32 cols, std::vector& destination) const; void resize(u32 scrollback); protected: s32 getTopScrollPos() const; s32 getBottomScrollPos() const; private: // Scrollback size u32 m_scrollback; // Array of unformatted chat lines std::vector m_unformatted; // Number of character columns in console u32 m_cols = 0; // Number of character rows in console u32 m_rows = 0; // Scroll position (console's top line index into m_formatted) s32 m_scroll = 0; // Array of formatted lines std::vector m_formatted; // Empty formatted line, for error returns ChatFormattedLine m_empty_formatted_line; }; class ChatPrompt { public: ChatPrompt(const std::wstring &prompt, u32 history_limit); ~ChatPrompt() = default; // Input character or string void input(wchar_t ch); void input(const std::wstring &str); // Add a string to the history void addToHistory(const std::wstring &line); // Get current line std::wstring getLine() const { return m_line; } // Get section of line that is currently selected std::wstring getSelection() const { return m_line.substr(m_cursor, m_cursor_len); } // Clear the current line void clear(); // Replace the current line with the given text std::wstring replace(const std::wstring &line); // Select previous command from history void historyPrev(); // Select next command from history void historyNext(); // Nick completion void nickCompletion(const std::list& names, bool backwards); // Update console size and reformat the visible portion of the prompt void reformat(u32 cols); // Get visible portion of the prompt. std::wstring getVisiblePortion() const; // Get cursor position (relative to visible portion). -1 if invalid s32 getVisibleCursorPosition() const; // Get length of cursor selection s32 getCursorLength() const { return m_cursor_len; } // Cursor operations enum CursorOp { CURSOROP_MOVE, CURSOROP_SELECT, CURSOROP_DELETE }; // Cursor operati#!/bin/sh # Update/create minetest po files # an auxiliary function to abort processing with an optional error # message abort() { test -n "$1" && echo >&2 "$1" exit 1 } # The po/ directory is assumed to be parallel to the directory where # this script is. Relative paths are fine for us so we can just # use the following trick (works both for manual invocations and for # script found from PATH) scriptisin="$(dirname "$(which "$0")")" # The script is executed from the parent of po/, which is also the # parent of the script directory and of the src/ directory. # We go through $scriptisin so that it can be executed from whatever # directory and still work correctly cd "$scriptisin/.." test -e po || abort "po/ directory not found" test -d po || abort "po/ is not a directory!" # Get a list of the languages we have to update/create cd po || abort "couldn't change directory to po!" # This assumes that we won't have dirnames with space, which is # the case for language codes, which are the only subdirs we expect to # find in po/ anyway. If you put anything else there, you need to suffer # the consequences of your actions,