cmCursesLongMessageForm.cxx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmCursesLongMessageForm.h"
  4. #include "cmCursesForm.h"
  5. #include "cmCursesMainForm.h"
  6. #include "cmCursesStandardIncludes.h"
  7. #include "cmVersion.h"
  8. #include <stdio.h>
  9. #include <string.h>
  10. inline int ctrl(int z)
  11. {
  12. return (z & 037);
  13. }
  14. cmCursesLongMessageForm::cmCursesLongMessageForm(
  15. std::vector<std::string> const& messages, const char* title)
  16. {
  17. // Append all messages into on big string
  18. for (std::string const& message : messages) {
  19. this->Messages += message;
  20. // Add one blank line after each message
  21. this->Messages += "\n\n";
  22. }
  23. this->Title = title;
  24. this->Fields[0] = nullptr;
  25. this->Fields[1] = nullptr;
  26. }
  27. cmCursesLongMessageForm::~cmCursesLongMessageForm()
  28. {
  29. if (this->Fields[0]) {
  30. free_field(this->Fields[0]);
  31. }
  32. }
  33. void cmCursesLongMessageForm::UpdateStatusBar()
  34. {
  35. int x, y;
  36. getmaxyx(stdscr, y, x);
  37. char bar[cmCursesMainForm::MAX_WIDTH];
  38. size_t size = this->Title.size();
  39. if (size >= cmCursesMainForm::MAX_WIDTH) {
  40. size = cmCursesMainForm::MAX_WIDTH - 1;
  41. }
  42. strncpy(bar, this->Title.c_str(), size);
  43. for (size_t i = size - 1; i < cmCursesMainForm::MAX_WIDTH; i++) {
  44. bar[i] = ' ';
  45. }
  46. int width;
  47. if (x < cmCursesMainForm::MAX_WIDTH) {
  48. width = x;
  49. } else {
  50. width = cmCursesMainForm::MAX_WIDTH - 1;
  51. }
  52. bar[width] = '\0';
  53. char version[cmCursesMainForm::MAX_WIDTH];
  54. char vertmp[128];
  55. sprintf(vertmp, "CMake Version %s", cmVersion::GetCMakeVersion());
  56. size_t sideSpace = (width - strlen(vertmp));
  57. for (size_t i = 0; i < sideSpace; i++) {
  58. version[i] = ' ';
  59. }
  60. sprintf(version + sideSpace, "%s", vertmp);
  61. version[width] = '\0';
  62. char fmt_s[] = "%s";
  63. curses_move(y - 4, 0);
  64. attron(A_STANDOUT);
  65. printw(fmt_s, bar);
  66. attroff(A_STANDOUT);
  67. curses_move(y - 3, 0);
  68. printw(fmt_s, version);
  69. pos_form_cursor(this->Form);
  70. }
  71. void cmCursesLongMessageForm::PrintKeys()
  72. {
  73. int x, y;
  74. getmaxyx(stdscr, y, x);
  75. if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
  76. return;
  77. }
  78. char firstLine[512];
  79. sprintf(firstLine, "Press [e] to exit help");
  80. char fmt_s[] = "%s";
  81. curses_move(y - 2, 0);
  82. printw(fmt_s, firstLine);
  83. pos_form_cursor(this->Form);
  84. }
  85. void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/,
  86. int /*height*/)
  87. {
  88. int x, y;
  89. getmaxyx(stdscr, y, x);
  90. if (this->Form) {
  91. unpost_form(this->Form);
  92. free_form(this->Form);
  93. this->Form = nullptr;
  94. }
  95. const char* msg = this->Messages.c_str();
  96. curses_clear();
  97. if (this->Fields[0]) {
  98. free_field(this->Fields[0]);
  99. this->Fields[0] = nullptr;
  100. }
  101. this->Fields[0] = new_field(y - 6, x - 2, 1, 1, 0, 0);
  102. field_opts_off(this->Fields[0], O_STATIC);
  103. this->Form = new_form(this->Fields);
  104. post_form(this->Form);
  105. int i = 0;
  106. form_driver(this->Form, REQ_BEG_FIELD);
  107. while (msg[i] != '\0' && i < 60000) {
  108. if (msg[i] == '\n' && msg[i + 1] != '\0') {
  109. form_driver(this->Form, REQ_NEW_LINE);
  110. } else {
  111. form_driver(this->Form, msg[i]);
  112. }
  113. i++;
  114. }
  115. form_driver(this->Form, REQ_BEG_FIELD);
  116. this->UpdateStatusBar();
  117. this->PrintKeys();
  118. touchwin(stdscr);
  119. refresh();
  120. }
  121. void cmCursesLongMessageForm::HandleInput()
  122. {
  123. if (!this->Form) {
  124. return;
  125. }
  126. char debugMessage[128];
  127. for (;;) {
  128. int key = getch();
  129. sprintf(debugMessage, "Message widget handling input, key: %d", key);
  130. cmCursesForm::LogMessage(debugMessage);
  131. // quit
  132. if (key == 'o' || key == 'e') {
  133. break;
  134. }
  135. if (key == KEY_DOWN || key == ctrl('n')) {
  136. form_driver(this->Form, REQ_SCR_FLINE);
  137. } else if (key == KEY_UP || key == ctrl('p')) {
  138. form_driver(this->Form, REQ_SCR_BLINE);
  139. } else if (key == KEY_NPAGE || key == ctrl('d')) {
  140. form_driver(this->Form, REQ_SCR_FPAGE);
  141. } else if (key == KEY_PPAGE || key == ctrl('u')) {
  142. form_driver(this->Form, REQ_SCR_BPAGE);
  143. }
  144. this->UpdateStatusBar();
  145. this->PrintKeys();
  146. touchwin(stdscr);
  147. wrefresh(stdscr);
  148. }
  149. }