| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst or https://cmake.org/licensing for details. */ | |
| #include "cmCursesLongMessageForm.h" | |
| #include <cstdio> | |
| #include <cstring> | |
| #include "cmCursesForm.h" | |
| #include "cmCursesMainForm.h" | |
| #include "cmCursesStandardIncludes.h" | |
| #include "cmStringAlgorithms.h" | |
| #include "cmVersion.h" | |
| inline int ctrl(int z) | |
| { | |
| return (z & 037); | |
| } | |
| cmCursesLongMessageForm::cmCursesLongMessageForm( | |
| std::vector<std::string> const& messages, char const* title, | |
| ScrollBehavior scrollBehavior) | |
| : Scrolling(scrollBehavior) | |
| { | |
| // Append all messages into on big string | |
| this->Messages = cmJoin(messages, "\n"); | |
| this->Title = title; | |
| this->Fields[0] = nullptr; | |
| this->Fields[1] = nullptr; | |
| } | |
| cmCursesLongMessageForm::~cmCursesLongMessageForm() | |
| { | |
| if (this->Fields[0]) { | |
| free_field(this->Fields[0]); | |
| } | |
| } | |
| void cmCursesLongMessageForm::UpdateContent(std::string const& output, | |
| std::string const& title) | |
| { | |
| this->Title = title; | |
| if (!output.empty() && this->Messages.size() < MAX_CONTENT_SIZE) { | |
| this->Messages.push_back('\n'); | |
| this->Messages.append(output); | |
| form_driver(this->Form, REQ_NEXT_LINE); | |
| form_driver(this->Form, REQ_BEG_LINE); | |
| this->DrawMessage(output.c_str()); | |
| } | |
| this->UpdateStatusBar(); | |
| touchwin(stdscr); | |
| refresh(); | |
| } | |
| void cmCursesLongMessageForm::UpdateStatusBar() | |
| { | |
| int x; | |
| int y; | |
| getmaxyx(stdscr, y, x); | |
| char bar[cmCursesMainForm::MAX_WIDTH]; | |
| size_t size = this->Title.size(); | |
| if (size >= cmCursesMainForm::MAX_WIDTH) { | |
| size = cmCursesMainForm::MAX_WIDTH - 1; | |
| } | |
| strncpy(bar, this->Title.c_str(), size); | |
| for (size_t i = size; i < cmCursesMainForm::MAX_WIDTH; i++) { | |
| bar[i] = ' '; | |
| } | |
| int width; | |
| if (x >= 0 && x < cmCursesMainForm::MAX_WIDTH) { | |
| width = x; | |
| } else { | |
| width = cmCursesMainForm::MAX_WIDTH - 1; | |
| } | |
| bar[width] = '\0'; | |
| char version[cmCursesMainForm::MAX_WIDTH]; | |
| char vertmp[128]; | |
| snprintf(vertmp, sizeof(vertmp), "CMake Version %s", | |
| cmVersion::GetCMakeVersion()); | |
| size_t sideSpace = (width - strlen(vertmp)); | |
| for (size_t i = 0; i < sideSpace; i++) { | |
| version[i] = ' '; | |
| } | |
| snprintf(version + sideSpace, sizeof(version) - sideSpace, "%s", vertmp); | |
| version[width] = '\0'; | |
| char fmt_s[] = "%s"; | |
| move(y - 4, 0); | |
| attron(A_STANDOUT); | |
| printw(fmt_s, bar); | |
| attroff(A_STANDOUT); | |
| move(y - 3, 0); | |
| printw(fmt_s, version); | |
| pos_form_cursor(this->Form); | |
| } | |
| void cmCursesLongMessageForm::PrintKeys() | |
| { | |
| int x; | |
| int y; | |
| getmaxyx(stdscr, y, x); | |
| if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) { | |
| return; | |
| } | |
| char firstLine[512]; | |
| snprintf(firstLine, sizeof(firstLine), "Press [e] to exit screen"); | |
| char fmt_s[] = "%s"; | |
| move(y - 2, 0); | |
| printw(fmt_s, firstLine); | |
| pos_form_cursor(this->Form); | |
| } | |
| void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/, | |
| int /*height*/) | |
| { | |
| int x; | |
| int y; | |
| getmaxyx(stdscr, y, x); | |
| if (this->Form) { | |
| unpost_form(this->Form); | |
| free_form(this->Form); | |
| this->Form = nullptr; | |
| } | |
| if (this->Fields[0]) { | |
| free_field(this->Fields[0]); | |
| this->Fields[0] = nullptr; | |
| } | |
| this->Fields[0] = new_field(y - 6, x - 2, 1, 1, 0, 0); | |
| field_opts_off(this->Fields[0], O_STATIC); | |
| this->Form = new_form(this->Fields); | |
| post_form(this->Form); | |
| form_driver(this->Form, REQ_BEG_FIELD); | |
| this->DrawMessage(this->Messages.c_str()); | |
| this->UpdateStatusBar(); | |
| touchwin(stdscr); | |
| refresh(); | |
| } | |
| void cmCursesLongMessageForm::DrawMessage(char const* msg) const | |
| { | |
| int i = 0; | |
| while (msg[i] != '\0' && i < MAX_CONTENT_SIZE) { | |
| if (msg[i] == '\n' && msg[i + 1] != '\0') { | |
| form_driver(this->Form, REQ_NEXT_LINE); | |
| form_driver(this->Form, REQ_BEG_LINE); | |
| } else { | |
| form_driver(this->Form, msg[i]); | |
| } | |
| i++; | |
| } | |
| if (this->Scrolling == ScrollBehavior::ScrollDown) { | |
| form_driver(this->Form, REQ_END_FIELD); | |
| } else { | |
| form_driver(this->Form, REQ_BEG_FIELD); | |
| } | |
| } | |
| void cmCursesLongMessageForm::HandleInput() | |
| { | |
| if (!this->Form) { | |
| return; | |
| } | |
| char debugMessage[128]; | |
| for (;;) { | |
| this->PrintKeys(); | |
| int key = getch(); | |
| #ifdef _WIN32 | |
| if (key == KEY_RESIZE) { | |
| HandleResize(); | |
| } | |
| #endif // _WIN32 | |
| snprintf(debugMessage, sizeof(debugMessage), | |
| "Message widget handling input, key: %d", key); | |
| cmCursesForm::LogMessage(debugMessage); | |
| // quit | |
| if (key == 'o' || key == 'e') { | |
| break; | |
| } | |
| if (key == KEY_DOWN || key == ctrl('n') || key == 'j') { | |
| form_driver(this->Form, REQ_SCR_FLINE); | |
| } else if (key == KEY_UP || key == ctrl('p') || key == 'k') { | |
| form_driver(this->Form, REQ_SCR_BLINE); | |
| } else if (key == KEY_NPAGE || key == ctrl('d')) { | |
| form_driver(this->Form, REQ_SCR_FPAGE); | |
| } else if (key == KEY_PPAGE || key == ctrl('u')) { | |
| form_driver(this->Form, REQ_SCR_BPAGE); | |
| } | |
| this->UpdateStatusBar(); | |
| touchwin(stdscr); | |
| wrefresh(stdscr); | |
| } | |
| } |