chat.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #pragma once
  17. #include <string>
  18. #include <vector>
  19. #include <list>
  20. #include "irrlichttypes.h"
  21. #include "util/enriched_string.h"
  22. #include "settings.h"
  23. // Chat console related classes
  24. struct ChatLine
  25. {
  26. // age in seconds
  27. f32 age = 0.0f;
  28. // name of sending player, or empty if sent by server
  29. EnrichedString name;
  30. // message text
  31. EnrichedString text;
  32. ChatLine(const std::wstring &a_name, const std::wstring &a_text):
  33. name(a_name),
  34. text(a_text)
  35. {
  36. }
  37. ChatLine(const EnrichedString &a_name, const EnrichedString &a_text):
  38. name(a_name),
  39. text(a_text)
  40. {
  41. }
  42. };
  43. struct ChatFormattedFragment
  44. {
  45. // text string
  46. EnrichedString text;
  47. // starting column
  48. u32 column;
  49. // web link is empty for most frags
  50. std::string weblink;
  51. // formatting
  52. //u8 bold:1;
  53. };
  54. struct ChatFormattedLine
  55. {
  56. // Array of text fragments
  57. std::vector<ChatFormattedFragment> fragments;
  58. // true if first line of one formatted ChatLine
  59. bool first;
  60. };
  61. class ChatBuffer
  62. {
  63. public:
  64. ChatBuffer(u32 scrollback);
  65. ~ChatBuffer() = default;
  66. // Append chat line
  67. // Removes oldest chat line if scrollback size is reached
  68. void addLine(const std::wstring &name, const std::wstring &text);
  69. // Remove all chat lines
  70. void clear();
  71. // Get number of lines currently in buffer.
  72. u32 getLineCount() const;
  73. // Get reference to i-th chat line.
  74. const ChatLine& getLine(u32 index) const;
  75. // Increase each chat line's age by dtime.
  76. void step(f32 dtime);
  77. // Delete oldest N chat lines.
  78. void deleteOldest(u32 count);
  79. // Delete lines older than maxAge.
  80. void deleteByAge(f32 maxAge);
  81. // Get number of rows, 0 if reformat has not been called yet.
  82. u32 getRows() const;
  83. // Update console size and reformat all formatted lines.
  84. void reformat(u32 cols, u32 rows);
  85. // Get formatted line for a given row (0 is top of screen).
  86. // Only valid after reformat has been called at least once
  87. const ChatFormattedLine& getFormattedLine(u32 row) const;
  88. // Scrolling in formatted buffer (relative)
  89. // positive rows == scroll up, negative rows == scroll down
  90. void scroll(s32 rows);
  91. // Scrolling in formatted buffer (absolute)
  92. void scrollAbsolute(s32 scroll);
  93. // Scroll to bottom of buffer (newest)
  94. void scrollBottom();
  95. // Scroll to top of buffer (oldest)
  96. void scrollTop();
  97. // Format a chat line for the given number of columns.
  98. // Appends the formatted lines to the destination array and
  99. // returns the number of formatted lines.
  100. u32 formatChatLine(const ChatLine& line, u32 cols,
  101. std::vector<ChatFormattedLine>& destination) const;
  102. void resize(u32 scrollback);
  103. protected:
  104. s32 getTopScrollPos() const;
  105. s32 getBottomScrollPos() const;
  106. private:
  107. // Scrollback size
  108. u32 m_scrollback;
  109. // Array of unformatted chat lines
  110. std::vector<ChatLine> m_unformatted;
  111. // Number of character columns in console
  112. u32 m_cols = 0;
  113. // Number of character rows in console
  114. u32 m_rows = 0;
  115. // Scroll position (console's top line index into m_formatted)
  116. s32 m_scroll = 0;
  117. // Array of formatted lines
  118. std::vector<ChatFormattedLine> m_formatted;
  119. // Empty formatted line, for error returns
  120. ChatFormattedLine m_empty_formatted_line;
  121. // Enable clickable chat weblinks
  122. bool m_cache_clickable_chat_weblinks;
  123. // Color of clickable chat weblinks
  124. irr::video::SColor m_cache_chat_weblink_color;
  125. };
  126. class ChatPrompt
  127. {
  128. public:
  129. ChatPrompt(const std::wstring &prompt, u32 history_limit);
  130. ~ChatPrompt() = default;
  131. // Input character or string
  132. void input(wchar_t ch);
  133. void input(const std::wstring &str);
  134. // Add a string to the history
  135. void addToHistory(const std::wstring &line);
  136. // Get current line
  137. std::wstring getLine() const { return m_line; }
  138. // Get section of line that is currently selected
  139. std::wstring getSelection() const { return m_line.substr(m_cursor, m_cursor_len); }
  140. // Clear the current line
  141. void clear();
  142. // Replace the current line with the given text
  143. std::wstring replace(const std::wstring &line);
  144. // Select previous command from history
  145. void historyPrev();
  146. // Select next command from history
  147. void historyNext();
  148. // Nick completion
  149. void nickCompletion(const std::list<std::string>& names, bool backwards);
  150. // Update console size and reformat the visible portion of the prompt
  151. void reformat(u32 cols);
  152. // Get visible portion of the prompt.
  153. std::wstring getVisiblePortion() const;
  154. // Get cursor position (relative to visible portion). -1 if invalid
  155. s32 getVisibleCursorPosition() const;
  156. // Get length of cursor selection
  157. s32 getCursorLength() const { return m_cursor_len; }
  158. // Cursor operations
  159. enum CursorOp {
  160. CURSOROP_MOVE,
  161. CURSOROP_SELECT,
  162. CURSOROP_DELETE
  163. };
  164. // Cursor operation direction
  165. enum CursorOpDir {
  166. CURSOROP_DIR_LEFT,
  167. CURSOROP_DIR_RIGHT
  168. };
  169. // Cursor operation scope
  170. enum CursorOpScope {
  171. CURSOROP_SCOPE_CHARACTER,
  172. CURSOROP_SCOPE_WORD,
  173. CURSOROP_SCOPE_LINE,
  174. CURSOROP_SCOPE_SELECTION
  175. };
  176. // Cursor operation
  177. // op specifies whether it's a move or delete operation
  178. // dir specifies whether the operation goes left or right
  179. // scope specifies how far the operation will reach (char/word/line)
  180. // Examples:
  181. // cursorOperation(CURSOROP_MOVE, CURSOROP_DIR_RIGHT, CURSOROP_SCOPE_LINE)
  182. // moves the cursor to the end of the line.
  183. // cursorOperation(CURSOROP_DELETE, CURSOROP_DIR_LEFT, CURSOROP_SCOPE_WORD)
  184. // deletes the word to the left of the cursor.
  185. void cursorOperation(CursorOp op, CursorOpDir dir, CursorOpScope scope);
  186. protected:
  187. // set m_view to ensure that 0 <= m_view <= m_cursor < m_view + m_cols
  188. // if line can be fully shown, set m_view to zero
  189. // else, also ensure m_view <= m_line.size() + 1 - m_cols
  190. void clampView();
  191. private:
  192. // Prompt prefix
  193. std::wstring m_prompt = L"";
  194. // Currently edited line
  195. std::wstring m_line = L"";
  196. // History buffer
  197. std::vector<std::wstring> m_history;
  198. // History index (0 <= m_history_index <= m_history.size())
  199. u32 m_history_index = 0;
  200. // Maximum number of history entries
  201. u32 m_history_limit;
  202. // Number of columns excluding columns reserved for the prompt
  203. s32 m_cols = 0;
  204. // Start of visible portion (index into m_line)
  205. s32 m_view = 0;
  206. // Cursor (index into m_line)
  207. s32 m_cursor = 0;
  208. // Cursor length (length of selected portion of line)
  209. s32 m_cursor_len = 0;
  210. // Last nick completion start (index into m_line)
  211. s32 m_nick_completion_start = 0;
  212. // Last nick completion start (index into m_line)
  213. s32 m_nick_completion_end = 0;
  214. };
  215. class ChatBackend
  216. {
  217. public:
  218. ChatBackend();
  219. ~ChatBackend() = default;
  220. // Add chat message
  221. void addMessage(const std::wstring &name, std::wstring text);
  222. // Parse and add unparsed chat message
  223. void addUnparsedMessage(std::wstring line);
  224. // Get the console buffer
  225. ChatBuffer& getConsoleBuffer();
  226. // Get the recent messages buffer
  227. ChatBuffer& getRecentBuffer();
  228. // Concatenate all recent messages
  229. EnrichedString getRecentChat() const;
  230. // Get the console prompt
  231. ChatPrompt& getPrompt();
  232. // Reformat all buffers
  233. void reformat(u32 cols, u32 rows);
  234. // Clear all recent messages
  235. void clearRecentChat();
  236. // Age recent messages
  237. void step(float dtime);
  238. // Scrolling
  239. void scroll(s32 rows);
  240. void scrollPageDown();
  241. void scrollPageUp();
  242. // Resize recent buffer based on settings
  243. void applySettings();
  244. private:
  245. ChatBuffer m_console_buffer;
  246. ChatBuffer m_recent_buffer;
  247. ChatPrompt m_prompt;
  248. };