Merge topic 'ccmake_incremental_log_display' into release-3.17

60bfaa8fe6 ccmake: Use incremental rendering for the logs
e9b36731e9 cmCursesLongMessageForm: Factor out helper to draw message to form

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard <robert.maynard@kitware.com>
Merge-request: !4573
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx
index 806e663..afd2b6b 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.cxx
+++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx
@@ -35,6 +35,22 @@
   }
 }
 
+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.append("\n" + output);
+    form_driver(this->Form, REQ_NEW_LINE);
+    this->DrawMessage(output.c_str());
+  }
+
+  this->UpdateStatusBar();
+  touchwin(stdscr);
+  refresh();
+}
+
 void cmCursesLongMessageForm::UpdateStatusBar()
 {
   int x;
@@ -109,8 +125,6 @@
     this->Form = nullptr;
   }
 
-  const char* msg = this->Messages.c_str();
-
   if (this->Fields[0]) {
     free_field(this->Fields[0]);
     this->Fields[0] = nullptr;
@@ -123,9 +137,18 @@
   this->Form = new_form(this->Fields);
   post_form(this->Form);
 
-  int i = 0;
   form_driver(this->Form, REQ_BEG_FIELD);
-  while (msg[i] != '\0' && i < 60000) {
+  this->DrawMessage(this->Messages.c_str());
+
+  this->UpdateStatusBar();
+  touchwin(stdscr);
+  refresh();
+}
+
+void cmCursesLongMessageForm::DrawMessage(const char* 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_NEW_LINE);
     } else {
@@ -138,10 +161,6 @@
   } else {
     form_driver(this->Form, REQ_BEG_FIELD);
   }
-
-  this->UpdateStatusBar();
-  touchwin(stdscr);
-  refresh();
 }
 
 void cmCursesLongMessageForm::HandleInput()
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.h b/Source/CursesDialog/cmCursesLongMessageForm.h
index 88efe62..da9fea2 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.h
+++ b/Source/CursesDialog/cmCursesLongMessageForm.h
@@ -27,6 +27,8 @@
   cmCursesLongMessageForm(cmCursesLongMessageForm const&) = delete;
   cmCursesLongMessageForm& operator=(cmCursesLongMessageForm const&) = delete;
 
+  void UpdateContent(std::string const& output, std::string const& title);
+
   // Description:
   // Handle user input.
   void HandleInput() override;
@@ -47,6 +49,10 @@
   void UpdateStatusBar() override;
 
 protected:
+  static constexpr int MAX_CONTENT_SIZE = 60000;
+
+  void DrawMessage(const char* msg) const;
+
   std::string Messages;
   std::string Title;
   ScrollBehavior Scrolling;
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 2c92835..65376d1 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -453,11 +453,11 @@
     this->LastProgress.append(progressBarCompleted, '#');
     this->LastProgress.append(progressBarWidth - progressBarCompleted, ' ');
     this->LastProgress += "] " + msg + "...";
+    this->DisplayOutputs(std::string());
   } else {
     this->Outputs.emplace_back(msg);
+    this->DisplayOutputs(msg);
   }
-
-  this->DisplayOutputs();
 }
 
 int cmCursesMainForm::Configure(int noconfigure)
@@ -589,7 +589,7 @@
 {
   this->Outputs.emplace_back(message);
   this->HasNonStatusOutputs = true;
-  this->DisplayOutputs();
+  this->DisplayOutputs(message);
 }
 
 void cmCursesMainForm::RemoveEntry(const char* value)
@@ -995,18 +995,22 @@
   this->LastProgress.clear();
 }
 
-void cmCursesMainForm::DisplayOutputs()
+void cmCursesMainForm::DisplayOutputs(std::string const& newOutput)
 {
   int xi;
   int yi;
   getmaxyx(stdscr, yi, xi);
 
-  auto newLogForm = new cmCursesLongMessageForm(
-    this->Outputs, this->LastProgress.c_str(),
-    cmCursesLongMessageForm::ScrollBehavior::ScrollDown);
-  CurrentForm = newLogForm;
-  this->LogForm.reset(newLogForm);
-  this->LogForm->Render(1, 1, xi, yi);
+  if (CurrentForm != this->LogForm.get()) {
+    auto newLogForm = new cmCursesLongMessageForm(
+      this->Outputs, this->LastProgress.c_str(),
+      cmCursesLongMessageForm::ScrollBehavior::ScrollDown);
+    CurrentForm = newLogForm;
+    this->LogForm.reset(newLogForm);
+    this->LogForm->Render(1, 1, xi, yi);
+  } else {
+    this->LogForm->UpdateContent(newOutput, this->LastProgress);
+  }
 }
 
 const char* cmCursesMainForm::s_ConstHelpMessage =
diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h
index b7c204d..2e06b90 100644
--- a/Source/CursesDialog/cmCursesMainForm.h
+++ b/Source/CursesDialog/cmCursesMainForm.h
@@ -129,7 +129,7 @@
   void ResetOutputs();
 
   // Display the current progress and output
-  void DisplayOutputs();
+  void DisplayOutputs(std::string const& newOutput);
 
   // Copies of cache entries stored in the user interface
   std::vector<cmCursesCacheEntryComposite> Entries;