Console.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. #pragma once
  2. #include "Array.h"
  3. #include "Critical.h"
  4. #include "ReferenceCounter.h"
  5. #include "Text.h"
  6. #include "Thread.h"
  7. namespace Framework
  8. {
  9. class ConsoleHandler;
  10. enum class Color
  11. {
  12. BLACK,
  13. RED,
  14. GREEN,
  15. YELLOW,
  16. BLUE,
  17. MAGENTA,
  18. CYAN,
  19. WHITE,
  20. LIGHT_BLACK,
  21. LIGHT_RED,
  22. LIGHT_GREEN,
  23. LIGHT_YELLOW,
  24. LIGHT_BLUE,
  25. LIGHT_MAGENTA,
  26. LIGHT_CYAN,
  27. LIGHT_WHITE,
  28. };
  29. /**
  30. * simple console command interface used for autocompletion and execution of
  31. * commands
  32. */
  33. class ConsoleCommand : public ReferenceCounter
  34. {
  35. private:
  36. Text name;
  37. public:
  38. /**
  39. * creates a new command
  40. *
  41. * \param name the name of the command. if the user types this name into
  42. * the console at the beginning, the command will be executed
  43. */
  44. DLLEXPORT ConsoleCommand(Text name);
  45. DLLEXPORT virtual ~ConsoleCommand();
  46. /**
  47. * the name of the command
  48. *
  49. * \return the name
  50. */
  51. DLLEXPORT const Text& getName() const;
  52. /**
  53. * calculates autocomplete posibilities when the user presses the tab
  54. * key and wants to use this command
  55. *
  56. * \param args the current arguments that would be passed to the command
  57. * if it was executed
  58. * \param appendToLast true if the last argument is not finished
  59. * \param possibilities the array to which the
  60. * possibilities should be added
  61. */
  62. virtual void addAutocompletePossibilities(const RCArray<Text>& args,
  63. bool appendToLast,
  64. RCArray<Text>& possibilities) const = 0;
  65. /**
  66. * executes the command
  67. *
  68. * \param args the arguments that the user has passed to the command
  69. * \return true if the command was executed successfully
  70. */
  71. virtual bool execute(RCArray<Text>& args) const = 0;
  72. };
  73. /**
  74. * repesents console content that is sticky, meaning it stays in the console
  75. * even if other messages are printed or commands are executed
  76. */
  77. class StickyConsoleContent : public virtual ReferenceCounter
  78. {
  79. private:
  80. int length;
  81. char* content;
  82. Color* color;
  83. Color* backgroundColor;
  84. ConsoleHandler* zConsoleHandler;
  85. public:
  86. DLLEXPORT StickyConsoleContent();
  87. DLLEXPORT ~StickyConsoleContent();
  88. /**
  89. * the current length of the command.
  90. *
  91. * \return the length in characters including possible newlines
  92. */
  93. DLLEXPORT int getLength() const;
  94. /**
  95. * sets the current content of the command. all previous colors will be
  96. * removed. does not free any memory of the given arguments.
  97. *
  98. * \param length the new length in characters
  99. * \param content the new content
  100. */
  101. DLLEXPORT void setContent(int length, const char* content);
  102. /**
  103. * sets the current content of the command. all previous colors will be
  104. * removed. does not free any memory of the given arguments.
  105. *
  106. * \param length the new length in characters
  107. * \param content the new content
  108. * \param color the font color of the content
  109. */
  110. DLLEXPORT void setContent(int length, const char* content, Color color);
  111. /**
  112. * sets the current content of the command. all previous colors will be
  113. * removed. does not free any memory of the given arguments.
  114. *
  115. * \param length the new length in characters
  116. * \param content the new content
  117. * \param color the font color of the content
  118. * \param backgroundColor the background color of the content
  119. */
  120. DLLEXPORT void setContent(int length,
  121. const char* content,
  122. Color color,
  123. Color backgroundColor);
  124. /**
  125. * sets the current content of the command. all previous colors will be
  126. * removed. does not free any memory of the given arguments.
  127. *
  128. * \param length the new length in characters
  129. * \param content the new content
  130. * \param color array of font colors for each character
  131. */
  132. DLLEXPORT void setContent(
  133. int length, const char* content, Color* color);
  134. /**
  135. * sets the current content of the command. all previous colors will be
  136. * removed. does not free any memory of the given arguments.
  137. *
  138. * \param length the new length in characters
  139. * \param content the new content
  140. * \param color array of font colors for each character
  141. * \param backgroundColor array of background colors for each character
  142. */
  143. DLLEXPORT void setContent(int length,
  144. const char* content,
  145. Color* color,
  146. Color* backgroundColor);
  147. /**
  148. * replaces a part of the current content. the colors of the current
  149. * start position will be used for the new content. does not free any
  150. * memory of the given arguments.
  151. *
  152. * \param start the start position of the replacement
  153. * \param length the length of the content that should be replaced
  154. * \param newLength the length of the new content that should be
  155. * inserted instead of the old content
  156. * \param newContent the new content
  157. */
  158. DLLEXPORT void repaceContent(
  159. int start, int length, int newLength, const char* newContent);
  160. /**
  161. * replaces a part of the current content. the backgound color of the
  162. * current start position will be used for the new content. does not
  163. * free any memory of the given arguments.
  164. *
  165. * \param start the start position of the replacement
  166. * \param length the length of the content that should be replaced
  167. * \param newLength the length of the new content that should be
  168. * inserted instead of the old content
  169. * \param newContent the new content
  170. * \param color the font color of the new content
  171. */
  172. DLLEXPORT void repaceContent(int start,
  173. int length,
  174. int newLength,
  175. const char* newContent,
  176. Color color);
  177. /**
  178. * replaces a part of the current content. does not
  179. * free any memory of the given arguments.
  180. *
  181. * \param start the start position of the replacement
  182. * \param length the length of the content that should be replaced
  183. * \param newLength the length of the new content that should be
  184. * inserted instead of the old content
  185. * \param newContent the new content
  186. * \param color the font color of the new content
  187. * \param backgroundColor the background color of the new content
  188. */
  189. DLLEXPORT void repaceContent(int start,
  190. int length,
  191. int newLength,
  192. const char* newContent,
  193. Color color,
  194. Color backgroundColor);
  195. /**
  196. * replaces a part of the current content. the backgound color of the
  197. * current start position will be used for the new content. does not
  198. * free any memory of the given arguments.
  199. *
  200. * \param start the start position of the replacement
  201. * \param length the length of the content that should be replaced
  202. * \param newLength the length of the new content that should be
  203. * inserted instead of the old content
  204. * \param newContent the new content
  205. * \param color array the font colorc of the new content for each
  206. * character
  207. */
  208. DLLEXPORT void repaceContent(int start,
  209. int length,
  210. int newLength,
  211. const char* newContent,
  212. Color* color);
  213. /**
  214. * replaces a part of the current content. does not
  215. * free any memory of the given arguments.
  216. *
  217. * \param start the start position of the replacement
  218. * \param length the length of the content that should be replaced
  219. * \param newLength the length of the new content that should be
  220. * inserted instead of the old content
  221. * \param newContent the new content
  222. * \param color array the font colorc of the new content for each
  223. * character
  224. * \param backgroundColor the background color of the new content for
  225. * each character
  226. */
  227. DLLEXPORT void repaceContent(int start,
  228. int length,
  229. int newLength,
  230. const char* newContent,
  231. Color* color,
  232. Color* backgroundColor);
  233. /**
  234. * triggers reprinting of all sticky console content.
  235. */
  236. DLLEXPORT void triggerUpdate();
  237. /**
  238. * true if the content is a input line where the user can type in
  239. *
  240. * \param true if the user can edit this content
  241. */
  242. DLLEXPORT virtual bool isInput();
  243. public:
  244. /**
  245. * prints the content to the console
  246. *
  247. * \return number of lines printed
  248. */
  249. DLLEXPORT virtual int print() const;
  250. /**
  251. * sets the console handler instance where this content will be printed
  252. * to. This will automatically be done if the content is added to a
  253. * consolehandler.
  254. *
  255. * \param zConsoleHandler the handler instance without increasing the
  256. * reference counter
  257. */
  258. DLLEXPORT void setConsoleHandlerZ(ConsoleHandler* zConsoleHandler);
  259. protected:
  260. /**
  261. * called before all sticky console content is reprinted when isInput
  262. * is true. restoreCursorPos() must be called after this
  263. */
  264. DLLEXPORT virtual void setCursorToBeginning();
  265. /**
  266. * reprints all input from the user so that the user can edit the
  267. * content again. can only be called after setCursorToBeginning was
  268. * called
  269. */
  270. DLLEXPORT virtual void restoreCursorPos();
  271. ConsoleHandler* zConsoleHandlerRef() const;
  272. public:
  273. friend ConsoleHandler;
  274. };
  275. /**
  276. * displays a progress bar in the console.
  277. */
  278. class ConsoleProgressBar : public StickyConsoleContent
  279. {
  280. private:
  281. int progress;
  282. int maxProgress;
  283. int maxWidth;
  284. public:
  285. DLLEXPORT ConsoleProgressBar();
  286. /**
  287. * sets the max used with of the progress bar in charachters including
  288. * the percentage number.
  289. *
  290. * \param maxWidth the width in characters
  291. */
  292. DLLEXPORT void setMaxWidth(int maxWidth);
  293. /**
  294. * sets the current progress.
  295. *
  296. * \param progress the progress
  297. */
  298. DLLEXPORT void setProgress(int progress);
  299. /**
  300. * sets the max progress steps needed to reach 100% progress.
  301. *
  302. * \param maxProgress max progress
  303. */
  304. DLLEXPORT void setMaxProgress(int maxProgress);
  305. /**
  306. * the current progress.
  307. *
  308. * \return the progress
  309. */
  310. DLLEXPORT int getProgress() const;
  311. protected:
  312. /**
  313. * prints the progress bar to the console.
  314. *
  315. * \return number of lines printed
  316. */
  317. DLLEXPORT virtual int print() const override;
  318. };
  319. class ConsoleListView;
  320. /**
  321. * a command input line where the user can type in commands. the user can
  322. * type the tab key for autocompletion.
  323. * ConsoleListView is used for displaying the autocompletion possibilities.
  324. */
  325. class InputLine : public StickyConsoleContent,
  326. private Thread
  327. {
  328. private:
  329. int cursorPos;
  330. RCArray<ConsoleCommand> commands;
  331. Critical cs;
  332. bool closed;
  333. protected:
  334. Framework::Text input;
  335. ConsoleListView* suggestions;
  336. public:
  337. DLLEXPORT InputLine();
  338. DLLEXPORT ~InputLine();
  339. /**
  340. * ads a command to the list of possible commands used for
  341. * autocompletion and execution.
  342. *
  343. * \param command the command to add
  344. */
  345. DLLEXPORT void addPossibleCommand(ConsoleCommand* command);
  346. /**
  347. * returns true because the user can edit the content of this line.
  348. *
  349. * \return true
  350. */
  351. DLLEXPORT virtual bool isInput() override;
  352. /**
  353. * stops the input line thread and prevents further user input
  354. * this will not abort the current read operation. The thread will only
  355. * exit correctly when called during command execution
  356. */
  357. DLLEXPORT void close();
  358. protected:
  359. /**
  360. * called before all sticky console content is reprinted when isInput
  361. * is true. restoreCursorPos() must be called after this
  362. */
  363. DLLEXPORT virtual void setCursorToBeginning();
  364. /**
  365. * prints the input line to the console. restoreCursorPos must be called
  366. * later
  367. *
  368. * \return number of lines printed
  369. */
  370. DLLEXPORT virtual int print() const override;
  371. /**
  372. * reprints all input from the user so that the user can edit the
  373. * content again. can only be called after setCursorToBeginning was
  374. * called
  375. */
  376. DLLEXPORT virtual void restoreCursorPos() override;
  377. /**
  378. * writes the next autocomplete step to input or displays a list of
  379. * possibilities in suggestions.
  380. *
  381. */
  382. DLLEXPORT void applyAutocompletion();
  383. /**
  384. * executes a given command.
  385. *
  386. * \param command the command
  387. * \return true if the command was executed successfully
  388. */
  389. DLLEXPORT bool executeCommand(Text command);
  390. /**
  391. * splits a given command into its name and arguments.
  392. *
  393. * \param command the command to split
  394. * \param split the array with the name and arguments
  395. * \param lastFinished true if the last argument is finished (folowed by
  396. * a witespace or ending character)
  397. * \return true if the command was split successfully
  398. */
  399. DLLEXPORT bool parseCommand(
  400. Text command, RCArray<Text>& split, bool& lastFinished);
  401. private:
  402. DLLEXPORT void thread() override;
  403. friend ConsoleHandler;
  404. };
  405. /**
  406. * prints a list of words to the console. the list will be printed ordered
  407. * by ascii value. it can be organized in multiple columns.
  408. */
  409. class ConsoleListView : public StickyConsoleContent
  410. {
  411. private:
  412. int maxColumns;
  413. RCArray<Text> items;
  414. int maxVisibleLines;
  415. int lineOffset;
  416. public:
  417. DLLEXPORT ConsoleListView();
  418. /**
  419. * the number of columns used to display the complete list of words.
  420. *
  421. * \return the number of columns
  422. */
  423. DLLEXPORT int getUsedColumns() const;
  424. /**
  425. * the number of lines needed to display the complete list of words.
  426. *
  427. * \return the number of lines
  428. */
  429. DLLEXPORT int getNeededLines() const;
  430. /**
  431. * specifies the maximum amount of lines visible.
  432. *
  433. * \param maxVisibleLines the amount of lines
  434. */
  435. DLLEXPORT void setMaxVisibleLines(int maxVisibleLines);
  436. /**
  437. * specifies the offset of the first line that should be printed.
  438. *
  439. * \param lineOffset the index of the first line that is printed
  440. */
  441. DLLEXPORT void setLineOffset(int lineOffset);
  442. /**
  443. * specifies the maximum amount of columns used to display the list of
  444. * words.
  445. *
  446. * \param maxColumns the amount of columns
  447. */
  448. DLLEXPORT void setMaxColumns(int maxColumns);
  449. /**
  450. * adds a word to the list of words.
  451. *
  452. * \param item the word to add
  453. */
  454. DLLEXPORT void addItem(Text item);
  455. /**
  456. * removes all words from the list.
  457. */
  458. DLLEXPORT void clear();
  459. /**
  460. * the items in the list view.
  461. *
  462. * \return items
  463. */
  464. DLLEXPORT const RCArray<Text>& getItems() const;
  465. protected:
  466. /**
  467. * prints the list of words to the console.
  468. *
  469. * \return number of lines printed
  470. */
  471. DLLEXPORT virtual int print() const override;
  472. };
  473. enum class ConsoleContentPosition
  474. {
  475. /**
  476. * before all other sticky console content.
  477. */
  478. Top,
  479. /**
  480. * after all pther sticky console content.
  481. */
  482. Bottom,
  483. };
  484. class ConsoleHandler : public ReferenceCounter
  485. {
  486. private:
  487. StickyConsoleContent** lines;
  488. int* lineCounts;
  489. int contentCount;
  490. Critical cs;
  491. #ifdef WIN32
  492. HANDLE hConsole;
  493. #endif
  494. public:
  495. DLLEXPORT ConsoleHandler();
  496. DLLEXPORT ~ConsoleHandler();
  497. /**
  498. * adds a sticky console content to the console at a specified position.
  499. *
  500. * \param content the new content
  501. * \param pos the position of the new content
  502. */
  503. DLLEXPORT void addContent(
  504. StickyConsoleContent* content, ConsoleContentPosition pos);
  505. /**
  506. * removes a sticky console content from the list of displayed sticky
  507. * console content.
  508. *
  509. * \param zContent the content to remove without increasing the
  510. * reference counter
  511. */
  512. DLLEXPORT void removeContent(StickyConsoleContent* zContent);
  513. /**
  514. * the current with of the console window in characters.
  515. *
  516. * \return the with in characters
  517. */
  518. DLLEXPORT int getWidth() const;
  519. /**
  520. * the current height of the console window in characters.
  521. *
  522. * \return the height in characters
  523. */
  524. DLLEXPORT int getHeight() const;
  525. /**
  526. * removes all sticky console content from the list of displayed sticky
  527. * console content.
  528. */
  529. DLLEXPORT void clear();
  530. /**
  531. * reprints all sticky console content that is currently displayed.
  532. */
  533. DLLEXPORT void print();
  534. /**
  535. * prints something to the console at the position of the first sticky
  536. * console content and reprints all sticky console content below the
  537. * newly printed content.
  538. *
  539. * \param str the string to print
  540. */
  541. DLLEXPORT void print(Text str);
  542. public:
  543. friend InputLine;
  544. };
  545. } // namespace Framework