cmCursesLongMessageForm.cxx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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 <cstdio>
  5. #include <cstring>
  6. #include "cmCursesForm.h"
  7. #include "cmCursesMainForm.h"
  8. #include "cmCursesStandardIncludes.h"
  9. #include "cmStringAlgorithms.h"
  10. #include "cmVersion.h"
  11. inline int ctrl(int z)
  12. {
  13. return (z & 037);
  14. }
  15. cmCursesLongMessageForm::cmCursesLongMessageForm(
  16. std::vector<std::string> const& messages, const char* title,
  17. ScrollBehavior scrollBehavior)
  18. : Scrolling(scrollBehavior)
  19. {
  20. // Append all messages into on big string
  21. this->Messages = cmJoin(messages, "\n");
  22. this->Title = title;
  23. this->Fields[0] = nullptr;
  24. this->Fields[1] = nullptr;
  25. }
  26. cmCursesLongMessageForm::~cmCursesLongMessageForm()
  27. {
  28. if (this->Fields[0]) {
  29. free_field(this->Fields[0]);
  30. }
  31. }
  32. void cmCursesLongMessageForm::UpdateStatusBar()
  33. {
  34. int x;
  35. int 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; 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;
  74. int y;
  75. getmaxyx(stdscr, y, x);
  76. if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
  77. return;
  78. }
  79. char firstLine[512];
  80. sprintf(firstLine, "Press [e] to exit screen");
  81. char fmt_s[] = "%s";
  82. curses_move(y - 2, 0);
  83. printw(fmt_s, firstLine);
  84. pos_form_cursor(this->Form);
  85. }
  86. void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/,
  87. int /*height*/)
  88. {
  89. int x;
  90. int y;
  91. getmaxyx(stdscr, y, x);
  92. if (this->Form) {
  93. unpost_form(this->Form);
  94. free_form(this->Form);
  95. this->Form = nullptr;
  96. }
  97. const char* msg = this->Messages.c_str();
  98. if (this->Fields[0]) {
  99. free_field(this->Fields[0]);
  100. this->Fields[0] = nullptr;
  101. }
  102. this->Fields[0] = new_field(y - 6, x - 2, 1, 1, 0, 0);
  103. field_opts_off(this->Fields[0], O_STATIC);
  104. this->Form = new_form(this->Fields);
  105. post_form(this->Form);
  106. int i = 0;
  107. form_driver(this->Form, REQ_BEG_FIELD);
  108. while (msg[i] != '\0' && i < 60000) {
  109. if (msg[i] == '\n' && msg[i + 1] != '\0') {
  110. form_driver(this->Form, REQ_NEW_LINE);
  111. } else {
  112. form_driver(this->Form, msg[i]);
  113. }
  114. i++;
  115. }
  116. if (this->Scrolling == ScrollBehavior::ScrollDown) {
  117. form_driver(this->Form, REQ_END_FIELD);
  118. } else {
  119. form_driver(this->Form, REQ_BEG_FIELD);
  120. }
  121. this->UpdateStatusBar();
  122. touchwin(stdscr);
  123. refresh();
  124. }
  125. void cmCursesLongMessageForm::HandleInput()
  126. {
  127. if (!this->Form) {
  128. return;
  129. }
  130. char debugMessage[128];
  131. for (;;) {
  132. this->PrintKeys();
  133. int key = getch();
  134. sprintf(debugMessage, "Message widget handling input, key: %d", key);
  135. cmCursesForm::LogMessage(debugMessage);
  136. // quit
  137. if (key == 'o' || key == 'e') {
  138. break;
  139. }
  140. if (key == KEY_DOWN || key == ctrl('n')) {
  141. form_driver(this->Form, REQ_SCR_FLINE);
  142. } else if (key == KEY_UP || key == ctrl('p')) {
  143. form_driver(this->Form, REQ_SCR_BLINE);
  144. } else if (key == KEY_NPAGE || key == ctrl('d')) {
  145. form_driver(this->Form, REQ_SCR_FPAGE);
  146. } else if (key == KEY_PPAGE || key == ctrl('u')) {
  147. form_driver(this->Form, REQ_SCR_BPAGE);
  148. }
  149. this->UpdateStatusBar();
  150. touchwin(stdscr);
  151. wrefresh(stdscr);
  152. }
  153. }