From 1086299804ddfa27c339c2224819b89a56fb4f63 Mon Sep 17 00:00:00 2001 From: No0ne558 Date: Thu, 5 Feb 2026 11:26:46 -0800 Subject: [PATCH] Fix Hardware button type: duplicate Server displays and startup bugs - Simplified server display logic: first terminal is ALWAYS the server - FindServer() now auto-cleans duplicate 'Server' terminals from previous buggy runs - Fixed printer deletion on every startup (only migrate if server has no printer) - Fixed terminal iterator reset after cleanup loop - Fixed multiple terminals being marked as server - Removed complex multi-pass server detection logic Files modified: manager.cc, settings.cc, changelog.md --- docs/changelog.md | 15 ++++++++- main/data/manager.cc | 66 +++++++++------------------------------ main/data/settings.cc | 72 ++++++++++++++++++++++--------------------- 3 files changed, 65 insertions(+), 88 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 0308873a..70dae3e0 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -7,6 +7,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## [Unreleased] ### Fixed +- **Hardware Button Type: Simplified Server Display Logic (2026-02-05)** + - Completely simplified the server display and terminal initialization logic + - **New Approach**: The FIRST terminal in the list is ALWAYS the server display + - **Changes Made**: + - Rewrote `FindServer()` to simply return the first terminal and ensure it's marked as server + - Simplified remote terminal initialization to skip the first terminal (server) and process others + - Removed complex multi-pass server detection and matching logic + - Removed `have_server` counting and display_host matching complexity + - Added automatic cleanup of duplicate "Server" terminals created by previous buggy code + - **Root Cause**: Previous complex logic with multiple passes, display_host matching, and server flag tracking was causing duplicate server displays to be created and persisted + - **Solution**: Simple rule - first terminal = server, all others = remote displays. FindServer() now removes any duplicate auto-created "Server" terminals found after the first terminal. + - **Impact**: No more duplicate server displays, existing duplicates are automatically cleaned up on startup + - **Files modified**: `main/data/manager.cc`, `main/data/settings.cc` + - **Hardware Button Type: Critical Startup Bugs (2026-02-04)** - Fixed multiple critical bugs in Hardware button type that caused issues after system reboot - **Bug 1: Printer Deletion on Every Startup** @@ -25,7 +39,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - **Root Cause**: `FindServer()` checked display_host match before IsServer flag, potentially returning wrong terminal - **Solution**: Changed to two-pass approach - first find explicit server, then check display_host match - **Impact**: Existing server terminal is always found first - - **⚠️ KNOWN ISSUE**: Duplicate "Server" displays may still appear in some configurations - investigation ongoing - **Files modified**: `main/data/manager.cc`, `main/data/settings.cc` - **Tender Settings Button Type: Null Pointer and Record Navigation Bugs (2026-02-04)** diff --git a/main/data/manager.cc b/main/data/manager.cc index db4245de..422679e1 100644 --- a/main/data/manager.cc +++ b/main/data/manager.cc @@ -1259,54 +1259,22 @@ int StartSystem(int my_use_net) // for the local terminal. int count = 0; int allowed = num_terms - 1; - int have_server = settings->HaveServerTerm(); + + // The first terminal is always the server - handled by FindServer() + // Process all other terminals as remote displays TermInfo *ti = settings->TermList(); - if (have_server > 1) - { - // Multiple terminals are marked as server - keep only the first one - int found = 0; - while (ti != nullptr) - { - if (ti->IsServer()) - { - if (found) - { - // Clear server flag on all but the first server found - ti->IsServer(0); - } - else - { - // First server found - update its display host and keep it - ti->display_host.Set(displaystr.data()); - found = 1; - } - } - ti = ti->next; - } - // Save settings after cleaning up duplicate servers - settings->Save(); - // Reset ti to the head of the list for the second loop - ti = settings->TermList(); - } + if (ti != nullptr) + ti = ti->next; // Skip the first terminal (server) + while (ti != nullptr) { - // this early, the TermInfo entry is the server entry if its - // isserver value is true or if display_host is equal to - // displaystr. So we only start up a remote terminal if - // IsServer() returns false and the two display strings do - // not match. Otherwise, we do a little background maintenance. - if (ti->display_host.empty() && have_server == 0) - { - ti->display_host.Set(displaystr.data()); - ti->IsServer(1); - have_server = 1; // Update count to prevent setting another terminal as server - } - else if (ti->IsServer()) - { - // make sure the server's display host value is current - ti->display_host.Set(displaystr.data()); - } - else if (strcmp(ti->display_host.Value(), displaystr.data()) != 0) + // Clear any stale server flags on non-first terminals + if (ti->IsServer()) + ti->IsServer(0); + + // Open remote terminals that have a different display host + if (!ti->display_host.empty() && + strcmp(ti->display_host.Value(), displaystr.data()) != 0) { if (count < allowed) { @@ -1316,19 +1284,13 @@ int StartSystem(int my_use_net) ti->OpenTerm(MasterControl); if (ti->next) sleep(OPENTERM_SLEEP); + count++; } else { printf("Not licensed to run terminal '%s'\n", ti->name.Value()); } } - else if (have_server == 0) - { - // this entry isn't explicitly set as server, but we got a match on - // the display string, so we'll set it now. - ti->IsServer(1); - have_server = 1; // Update count to prevent setting another terminal as server - } ti = ti->next; } } diff --git a/main/data/settings.cc b/main/data/settings.cc index 62000ccc..dcc50cdf 100644 --- a/main/data/settings.cc +++ b/main/data/settings.cc @@ -4470,50 +4470,52 @@ MealInfo *Settings::FindMealByID(int id) TermInfo *Settings::FindServer(const genericChar* displaystr) { FnTrace("Settings::FindServer()"); - TermInfo *retti = nullptr; TermInfo *ti = term_list.Head(); - // First pass: look for a terminal explicitly marked as server - while (ti != nullptr) + // The first terminal in the list is ALWAYS the server display + if (ti != nullptr) { - if (ti->IsServer()) + // Ensure the first terminal is marked as server + if (!ti->IsServer()) { - retti = ti; - break; + ti->IsServer(1); } - ti = ti->next; - } - - // Second pass: if no server found, look for matching display_host - if (retti == nullptr) - { - ti = term_list.Head(); - while (ti != nullptr) + + // Remove any other terminals that were previously marked as server + // and have the default "Server" name (auto-created duplicates) + TermInfo *other = ti->next; + while (other != nullptr) { - if (strcmp(displaystr, ti->display_host.Value()) == 0) + TermInfo *next_other = other->next; + if (other->IsServer()) { - retti = ti; - // Mark this terminal as the server since it matches our display - retti->IsServer(1); - break; + other->IsServer(0); } - ti = ti->next; + // Remove auto-created "Server" terminals that are duplicates + if (strcmp(other->name.Value(), "Server") == 0 && + (other->display_host.empty() || + strcmp(other->display_host.Value(), displaystr) == 0)) + { + Remove(other); + delete other; + } + other = next_other; } - } - - // If still no match, create a new server terminal - if (retti == nullptr) - { - retti = new TermInfo; - retti->name.Set("Server"); - retti->display_host.Clear(); - retti->type = TERMINAL_NORMAL; - retti->printer_model = 0; - retti->printer_port = 0; - retti->IsServer(1); - AddFront(retti); - } - return retti; + + return ti; + } + + // No terminals exist - create the server terminal + ti = new TermInfo; + ti->name.Set("Server"); + ti->display_host.Clear(); + ti->type = TERMINAL_NORMAL; + ti->printer_model = 0; + ti->printer_port = 0; + ti->IsServer(1); + AddFront(ti); + + return ti; } TermInfo *Settings::FindTerminal(const char* displaystr)