From 587bdee678ec0756025c009bbd9c729e7883d1c4 Mon Sep 17 00:00:00 2001
From: Thomas Jentzsch <tjentzsch@yahoo.de>
Date: Mon, 10 May 2021 16:06:43 +0200
Subject: [PATCH] refactored history buffer and increased max size from 20 to
 1000

---
 src/debugger/gui/PromptWidget.cxx | 112 +++++++++++++++---------------
 src/debugger/gui/PromptWidget.hxx |  12 ++--
 2 files changed, 64 insertions(+), 60 deletions(-)

diff --git a/src/debugger/gui/PromptWidget.cxx b/src/debugger/gui/PromptWidget.cxx
index f8ef7aa24..01686f5fe 100644
--- a/src/debugger/gui/PromptWidget.cxx
+++ b/src/debugger/gui/PromptWidget.cxx
@@ -542,19 +542,41 @@ void PromptWidget::textPaste()
 #endif
 }
 
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+int PromptWidget::historyDir(int& index, int direction, bool promptSpace)
+{
+  int historySize = int(_history.size()) + (promptSpace ? 1 : 0);
+
+  index += direction;
+  if(index < 0)
+    index += historySize;
+  else
+    index %= historySize;
+
+  return index;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PromptWidget::historyAdd(const string& entry)
+{
+  if(_historyIndex >= _history.size())
+    _history.push_back(entry);
+  else
+    _history[_historyIndex] = entry;
+}
+
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void PromptWidget::addToHistory(const char* str)
 {
   // Do not add duplicates, remove old duplicate
-  if(_historySize)
+  if(_history.size())
   {
     int i = _historyIndex;
-    int historyEnd = _historyIndex % _historySize;
+    int historyEnd = _historyIndex % _history.size();
 
     do
     {
-      if(--i < 0)
-        i =_historySize - 1;
+      historyDir(i, -1);
 
       if(!BSPF::compareIgnoreCase(_history[i], str))
       {
@@ -563,76 +585,55 @@ void PromptWidget::addToHistory(const char* str)
         do
         {
           prevJ = j;
-          j = (j + 1) % (_historySize);
+          historyDir(j, +1);
+          _history[prevJ] = _history[j];
+        }
+        while(j != historyEnd);
 
-        #if defined(BSPF_WINDOWS)
-          strncpy_s(_history[prevJ], kLineBufferSize, _history[j], kLineBufferSize - 1);
-        #else
-          strncpy(_history[prevJ], _history[j], kLineBufferSize - 1);
-        #endif
-        } while(j != historyEnd);
-
-        if(--_historyIndex < 0)
-          _historyIndex = _historySize - 1;
-        _historySize--;
+        historyDir(_historyIndex, -1);
         break;
       }
-    } while(i != historyEnd);
+    }
+    while(i != historyEnd);
   }
-
-#if defined(BSPF_WINDOWS)
-  strncpy_s(_history[_historyIndex], kLineBufferSize, str, kLineBufferSize - 1);
-#else
-  strncpy(_history[_historyIndex], str, kLineBufferSize - 1);
-#endif
-  _historyIndex = (_historyIndex + 1) % kHistorySize;
+  historyAdd(str);
   _historyLine = 0; // reset history scroll
-
-  if (_historySize < kHistorySize)
-    _historySize++;
+  _historyIndex = (_historyIndex + 1) % kHistorySize;
 }
 
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 bool PromptWidget::historyScroll(int direction)
 {
-  if(_historySize == 0)
+  if(_history.size() == 0)
     return false;
 
   if(_historyLine == 0)
   {
-    int i;
+    string input;
 
-    for(i = 0; i < _promptEndPos - _promptStartPos; i++)
-      _history[_historyIndex][i] = buffer(_promptStartPos + i); //FIXME: int to char??
+    for(int i = _promptStartPos; i < _promptEndPos; i++)
+      input += buffer(i) & 0x7f;
 
-    _history[_historyIndex][i] = '\0';
+    historyAdd(input);
   }
 
-  // Advance to the next line in the history
-  int histSize = _historySize + (_historySize < kHistorySize ? 1 : 0);
-  int line = _historyLine + direction;
+  // Advance to the next/prev line in the history
+  historyDir(_historyLine, direction, _history.size() < kHistorySize);
 
-  if(line < 0)
-    line += histSize;
-  line %= histSize;
+  // Search the history using the original input
+  do
+  {
+    int idx = _historyLine
+      ? (_historyIndex - _historyLine + _history.size()) % int(_history.size())
+      : _historyIndex;
 
-  // If anything in the buffer, search the history.
-  if(_currentPos > _promptStartPos) {
-    do
-    {
-      int idx = line ? (_historyIndex - line + _historySize) % _historySize
-                     : _historyIndex;
+    if(BSPF::startsWithIgnoreCase(_history[idx], _history[_historyIndex]))
+      break;
 
-      if(BSPF::startsWithIgnoreCase(_history[idx], _history[_historyIndex]))
-        break;
-
-      line += direction;
-      if(line < 0)
-        line += histSize;
-      line %= histSize;
-    } while(line); // if line == 0, nothing was found
+    // Advance to the next/prev line in the history
+    historyDir(_historyLine, direction, _history.size() < kHistorySize);
   }
-  _historyLine = line;
+  while(_historyLine); // If _historyLine == 0, nothing was found
 
   // Remove the current user text
   _currentPos = _promptStartPos;
@@ -642,8 +643,9 @@ bool PromptWidget::historyScroll(int direction)
   scrollToCurrent();
 
   // Print the text from the history
-  int idx = _historyLine ? (_historyIndex - _historyLine + _historySize) % _historySize
-                         : _historyIndex;
+  int idx = _historyLine
+    ? (_historyIndex - _historyLine + _history.size()) % int(_history.size())
+    : _historyIndex;
 
   for(int i = 0; i < kLineBufferSize && _history[idx][i] != '\0'; i++)
     putcharIntern(_history[idx][i]);
@@ -652,7 +654,7 @@ bool PromptWidget::historyScroll(int direction)
   // Ensure once more the caret is visible (in case of very long history entries)
   scrollToCurrent();
 
-  return line;
+  return true;
 }
 
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/debugger/gui/PromptWidget.hxx b/src/debugger/gui/PromptWidget.hxx
index a7eb16bee..b3f30b03a 100644
--- a/src/debugger/gui/PromptWidget.hxx
+++ b/src/debugger/gui/PromptWidget.hxx
@@ -42,8 +42,6 @@ class PromptWidget : public Widget, public CommandSender
     ~PromptWidget() override = default;
 
   public:
-    ATTRIBUTE_FMT_PRINTF int printf(const char* format, ...);
-    ATTRIBUTE_FMT_PRINTF int vprintf(const char* format, va_list argptr);
     void print(const string& str);
     void printPrompt();
     string saveBuffer(const FilesystemNode& file);
@@ -54,6 +52,8 @@ class PromptWidget : public Widget, public CommandSender
     void addToHistory(const char *str);
 
   protected:
+    ATTRIBUTE_FMT_PRINTF int printf(const char* format, ...);
+    ATTRIBUTE_FMT_PRINTF int vprintf(const char* format, va_list argptr);
     int& buffer(int idx) { return _buffer[idx % kBufferSize]; }
 
     void drawWidget(bool hilite) override;
@@ -99,7 +99,7 @@ class PromptWidget : public Widget, public CommandSender
     enum {
       kBufferSize = 32768,
       kLineBufferSize = 256,
-      kHistorySize = 50
+      kHistorySize = 1000
     };
 
     int  _buffer[kBufferSize];  // NOLINT  (will be rewritten soon)
@@ -117,8 +117,7 @@ class PromptWidget : public Widget, public CommandSender
 
     ScrollBarWidget* _scrollBar;
 
-    char _history[kHistorySize][kLineBufferSize];  // NOLINT  (will be rewritten soon)
-    int _historySize{0};
+    std::vector<string> _history;
     int _historyIndex{0};
     int _historyLine{0};
     int _tabCount{-1};
@@ -130,6 +129,9 @@ class PromptWidget : public Widget, public CommandSender
     bool _firstTime{true};
     bool _exitedEarly{false};
 
+    int historyDir(int& index, int direction, bool promptSpace = false);
+    void historyAdd(const string& entry);
+
   private:
     // Following constructors and assignment operators not supported
     PromptWidget() = delete;