806e663e9e4a809164c852b3b717a31a604ce5df
[platform/upstream/cmake.git] / Source / CursesDialog / cmCursesLongMessageForm.cxx
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
5 #include <cstdio>
6 #include <cstring>
7
8 #include "cmCursesForm.h"
9 #include "cmCursesMainForm.h"
10 #include "cmCursesStandardIncludes.h"
11 #include "cmStringAlgorithms.h"
12 #include "cmVersion.h"
13
14 inline int ctrl(int z)
15 {
16   return (z & 037);
17 }
18
19 cmCursesLongMessageForm::cmCursesLongMessageForm(
20   std::vector<std::string> const& messages, const char* title,
21   ScrollBehavior scrollBehavior)
22   : Scrolling(scrollBehavior)
23 {
24   // Append all messages into on big string
25   this->Messages = cmJoin(messages, "\n");
26   this->Title = title;
27   this->Fields[0] = nullptr;
28   this->Fields[1] = nullptr;
29 }
30
31 cmCursesLongMessageForm::~cmCursesLongMessageForm()
32 {
33   if (this->Fields[0]) {
34     free_field(this->Fields[0]);
35   }
36 }
37
38 void cmCursesLongMessageForm::UpdateStatusBar()
39 {
40   int x;
41   int y;
42   getmaxyx(stdscr, y, x);
43
44   char bar[cmCursesMainForm::MAX_WIDTH];
45   size_t size = this->Title.size();
46   if (size >= cmCursesMainForm::MAX_WIDTH) {
47     size = cmCursesMainForm::MAX_WIDTH - 1;
48   }
49   strncpy(bar, this->Title.c_str(), size);
50   for (size_t i = size; i < cmCursesMainForm::MAX_WIDTH; i++) {
51     bar[i] = ' ';
52   }
53   int width;
54   if (x < cmCursesMainForm::MAX_WIDTH) {
55     width = x;
56   } else {
57     width = cmCursesMainForm::MAX_WIDTH - 1;
58   }
59
60   bar[width] = '\0';
61
62   char version[cmCursesMainForm::MAX_WIDTH];
63   char vertmp[128];
64   sprintf(vertmp, "CMake Version %s", cmVersion::GetCMakeVersion());
65   size_t sideSpace = (width - strlen(vertmp));
66   for (size_t i = 0; i < sideSpace; i++) {
67     version[i] = ' ';
68   }
69   sprintf(version + sideSpace, "%s", vertmp);
70   version[width] = '\0';
71
72   char fmt_s[] = "%s";
73   curses_move(y - 4, 0);
74   attron(A_STANDOUT);
75   printw(fmt_s, bar);
76   attroff(A_STANDOUT);
77   curses_move(y - 3, 0);
78   printw(fmt_s, version);
79   pos_form_cursor(this->Form);
80 }
81
82 void cmCursesLongMessageForm::PrintKeys()
83 {
84   int x;
85   int y;
86   getmaxyx(stdscr, y, x);
87   if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
88     return;
89   }
90   char firstLine[512];
91   sprintf(firstLine, "Press [e] to exit screen");
92
93   char fmt_s[] = "%s";
94   curses_move(y - 2, 0);
95   printw(fmt_s, firstLine);
96   pos_form_cursor(this->Form);
97 }
98
99 void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/,
100                                      int /*height*/)
101 {
102   int x;
103   int y;
104   getmaxyx(stdscr, y, x);
105
106   if (this->Form) {
107     unpost_form(this->Form);
108     free_form(this->Form);
109     this->Form = nullptr;
110   }
111
112   const char* msg = this->Messages.c_str();
113
114   if (this->Fields[0]) {
115     free_field(this->Fields[0]);
116     this->Fields[0] = nullptr;
117   }
118
119   this->Fields[0] = new_field(y - 6, x - 2, 1, 1, 0, 0);
120
121   field_opts_off(this->Fields[0], O_STATIC);
122
123   this->Form = new_form(this->Fields);
124   post_form(this->Form);
125
126   int i = 0;
127   form_driver(this->Form, REQ_BEG_FIELD);
128   while (msg[i] != '\0' && i < 60000) {
129     if (msg[i] == '\n' && msg[i + 1] != '\0') {
130       form_driver(this->Form, REQ_NEW_LINE);
131     } else {
132       form_driver(this->Form, msg[i]);
133     }
134     i++;
135   }
136   if (this->Scrolling == ScrollBehavior::ScrollDown) {
137     form_driver(this->Form, REQ_END_FIELD);
138   } else {
139     form_driver(this->Form, REQ_BEG_FIELD);
140   }
141
142   this->UpdateStatusBar();
143   touchwin(stdscr);
144   refresh();
145 }
146
147 void cmCursesLongMessageForm::HandleInput()
148 {
149   if (!this->Form) {
150     return;
151   }
152
153   char debugMessage[128];
154
155   for (;;) {
156     this->PrintKeys();
157     int key = getch();
158
159     sprintf(debugMessage, "Message widget handling input, key: %d", key);
160     cmCursesForm::LogMessage(debugMessage);
161
162     // quit
163     if (key == 'o' || key == 'e') {
164       break;
165     }
166     if (key == KEY_DOWN || key == ctrl('n')) {
167       form_driver(this->Form, REQ_SCR_FLINE);
168     } else if (key == KEY_UP || key == ctrl('p')) {
169       form_driver(this->Form, REQ_SCR_BLINE);
170     } else if (key == KEY_NPAGE || key == ctrl('d')) {
171       form_driver(this->Form, REQ_SCR_FPAGE);
172     } else if (key == KEY_PPAGE || key == ctrl('u')) {
173       form_driver(this->Form, REQ_SCR_BPAGE);
174     }
175
176     this->UpdateStatusBar();
177     touchwin(stdscr);
178     wrefresh(stdscr);
179   }
180 }