commit 0a32fd63af683abef99249c44ab474ffe1810817
Author: david.sorber <david.sorber@jacobs.com>
Date:   Fri Mar 1 06:48:34 2024 -0500

    Improved filtering and added parsing input from a plaintext file.

diff --git a/src/Catalog.cc b/src/Catalog.cc
index d162341..03f311c 100644
--- a/src/Catalog.cc
+++ b/src/Catalog.cc
@@ -1,20 +1,70 @@
 #include <algorithm>
+#include <fstream>
+#include <iostream>
 
 #include "Catalog.h"
 
 Catalog::Catalog()
 {
     // Temporarily fill the catalog with some test data
-    /*
-        {"Target", "baranovich@gmail.com\nF-B-3-7"},
-        {"United", "david.sorber@gmail.com\nF-B-3-7"},
-        {"Pepco", "david.sorber@gmail.com\nNZ-98-O"},
-        {"Washington Gas", "baranovich@gmail.com\nS-N-718"}
-     */
+#if 0
     m_catalog.push_back({"Target", "baranovich@gmail.com\nF-B-3-7"});
     m_catalog.push_back({"United", "david.sorber@gmail.com\nF-B-3-7"});
     m_catalog.push_back({"Pepco", "david.sorber@gmail.com\nNZ-98-O"});
     m_catalog.push_back({"Washington Gas", "baranovich@gmail.com\nS-N-718"});
+#else
+    const std::string pwFile("/home/dsorber/Documents/chicken_soup/chicken_soup.txt");
+
+    std::ifstream infile(pwFile);
+    if (! infile)
+    {
+        return;
+    }
+
+    // Iterate over the PW file and parse it (key is first line of each stanza
+    // and the value are the remaining lines)
+    std::string line;
+    std::string key;
+    std::string value;
+    bool firstLine = true;
+    while (std::getline(infile, line))
+    {
+        if (line.size() == 0)
+        {
+            // Debuggery
+//            std::cout << "KEY: " << key << std::endl;
+//            std::cout << "VAL: " << value << "\n" << std::endl;
+
+            m_catalog.push_back({key, value});
+            firstLine = true;
+        }
+        else
+        {
+            if (firstLine)
+            {
+                key.clear();
+                value.clear();
+
+                key.swap(line);
+                firstLine = false;
+            }
+            else
+            {
+                value += line + "\n";
+            }
+        }
+    }
+
+    // Debuggery
+//    std::cout << "KEY: " << key << std::endl;
+//    std::cout << "VAL: " << value << "\n" << std::endl;
+    m_catalog.push_back({key, value});
+
+    // Close the input file
+    infile.close();
+
+
+#endif
 
     // Sort the catalog (A -> Z) for display purposes
     std::sort(
diff --git a/src/CatalogItem.cc b/src/CatalogItem.cc
index c5a6dc6..2dd13c0 100644
--- a/src/CatalogItem.cc
+++ b/src/CatalogItem.cc
@@ -1,3 +1,5 @@
+#include <cstring>
+
 #include "CatalogItem.h"
 
 CatalogItem::CatalogItem(const std::string& key, const std::string& value)
@@ -14,6 +16,10 @@ CatalogItem::CatalogItem(const std::string& key, const std::string& value)
             m_keyLower.at(idx) = (m_keyLower.at(idx) | 32);
         }
     }
+
+    // Zero out value buffer and then copy the value into the buffer
+    std::memset(m_valueBuffer, 0, VALUE_BUFFER_SIZE);
+    std::memcpy(m_valueBuffer, m_value.data(), m_value.size());
 }
 
 CatalogItem::~CatalogItem()
diff --git a/src/CatalogItem.h b/src/CatalogItem.h
index 74d9eeb..cc818b9 100644
--- a/src/CatalogItem.h
+++ b/src/CatalogItem.h
@@ -9,6 +9,8 @@ class CatalogItem
 {
 public:
 
+    static inline const uint32_t VALUE_BUFFER_SIZE{1024};
+
     CatalogItem(const std::string& key, const std::string& value);
 
     ~CatalogItem();
@@ -28,6 +30,16 @@ public:
         return m_value;
     }
 
+    inline char* getValueBuffer()
+    {
+        return m_valueBuffer;
+    }
+
+    inline uint32_t getValueBufferSize() const
+    {
+        return VALUE_BUFFER_SIZE;
+    }
+
     /**
      * Should this CatalogItem be visible
      * @return
@@ -61,8 +73,12 @@ private:
     std::string m_keyLower;
     std::string m_value;
 
+    char m_valueBuffer[VALUE_BUFFER_SIZE];
+
     bool m_visible;
 
+
+
 };
 
 
diff --git a/src/main.cpp b/src/main.cpp
index 6e0a2ca..48516b0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,13 +1,9 @@
+// pwmgr main
 // Dear ImGui: standalone example application for SDL2 + SDL_Renderer
 // (SDL is a cross-platform general purpose library for handling windows, inputs,
 // OpenGL/Vulkan/Metal graphics context creation, etc.)
-
-// Learn about Dear ImGui:
-// - FAQ                  https://dearimgui.com/faq
-// - Getting Started      https://dearimgui.com/getting-started
-// - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
-// - Introduction, links and more at the top of imgui.cpp
-
+//
+// TODO: consider switching to the below
 // Important to understand: SDL_Renderer is an _optional_ component of SDL2.
 // For a multi-platform app consider using e.g. SDL+DirectX on Windows and
 // SDL+OpenGL on Linux/OSX.
@@ -15,7 +11,6 @@
 #include <cstdio>
 #include <cstdint>
 #include <iostream>
-//#include <ostream>
 #include <map>
 #include <string>
 #include <vector>
@@ -34,7 +29,6 @@
 #endif
 
 const std::string APP_NAME("pwmgr");
-
 const std::string VERSION("v0.0.1");
 
 const std::string BOLD{"\033[1m"};
@@ -48,16 +42,30 @@ const std::string UP_ONE = "\033[1A";
 
 #define ERROR_MSG       BOLD << RED << "ERROR: " << ENDC
 
+
 Catalog catalog;
 
 
-static ImGuiInputTextFlags MULTILINE_TEXT_FLAGS = ImGuiInputTextFlags_AllowTabInput;
+static ImGuiInputTextFlags MULTILINE_TEXT_FLAGS =
+        ImGuiInputTextFlags_AllowTabInput | ImGuiInputTextFlags_ReadOnly;
 
 int catalogFilterCallback(ImGuiInputTextCallbackData* data)
 {
     if (data->BufTextLen > 0)
     {
-        std::cout << "BUFFER: " << data->Buf << std::endl;
+        // Lowercase the buffer  in place
+        for (uint32_t idx = 0; idx < data->BufTextLen; ++idx)
+        {
+            if ((data->Buf[idx] >= 'A') && (data->Buf[idx] <= 'Z'))
+            {
+                data->Buf[idx] |= 32;
+            }
+        }
+
+        // Debuggery
+//        std::cout << "BUFFER: " << data->Buf << std::endl;
+
+        // Now filter the catalog
         catalog.filter(data->Buf);
     }
     else
@@ -152,10 +160,7 @@ int main(int argc, char** argv)
     //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
     //IM_ASSERT(font != nullptr);
 
-    // Our state
-    bool show_demo_window = false;
-    bool show_another_window = false;
-    ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+    // GUI state
 
     // Main loop
     bool done = false;
@@ -204,7 +209,7 @@ int main(int argc, char** argv)
         ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize);
 #endif
         ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
-        ImGui::Begin("inner window", nullptr,
+        ImGui::Begin("inner_window", nullptr,
                      ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_MenuBar);
 
 
@@ -233,15 +238,16 @@ int main(int argc, char** argv)
 
                 for (auto& iter : catalog)
                 {
+                    // ImGuiInputTextFlags_ReadOnly
                     if (iter.visible() &&
                         ImGui::CollapsingHeader(iter.getKey().c_str()))
                     {
 //                        ImGui::Text("%s", iter.second.c_str());
                         ImGui::InputTextMultiline(
                             iter.getLcKey().c_str(),
-                            const_cast<char*>(iter.getValue().c_str()),
-                             iter.getValue().size(),
-                             ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 4),
+                            iter.getValueBuffer(),
+                         iter.getValueBufferSize(),
+                            ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 4),
                             MULTILINE_TEXT_FLAGS);
                     }
                 }
@@ -256,18 +262,16 @@ int main(int argc, char** argv)
                 ImGui::BeginChild("item view",
                                   ImVec2(0, -ImGui::GetFrameHeightWithSpacing()));
 
-
-//                ImGui::Text("MyObject: %d", selected);
-                char str0[128]{};
-                ImGui::InputText("Filter", str0,
-                                 IM_ARRAYSIZE(str0),
+                char filterBuffer[128]{};
+                ImGui::InputText("Filter", filterBuffer,
+                                 IM_ARRAYSIZE(filterBuffer),
                                  ImGuiInputTextFlags_CallbackEdit,
                                  catalogFilterCallback);
 
                 ImGui::Separator();
                 if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
                 {
-                    if (ImGui::BeginTabItem("Description"))
+                    if (ImGui::BeginTabItem("Options"))
                     {
                         ImGui::TextWrapped(
                         "Lorem ipsum dolor sit amet, consectetur adipiscing "
@@ -276,9 +280,12 @@ int main(int argc, char** argv)
                         ImGui::EndTabItem();
                     }
 
-                    if (ImGui::BeginTabItem("Details"))
+                    if (ImGui::BeginTabItem("About"))
                     {
-                        ImGui::Text("ID: 0123456789");
+                        ImGui::Text("%s version: %s", APP_NAME.c_str(),
+                                                          VERSION.c_str());
+                        ImGui::Text("Compiled on: %s ", __TIMESTAMP__);
+                        ImGui::Text("Created by: dsorber");
                         ImGui::EndTabItem();
                     }
                     ImGui::EndTabBar();
