Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**
Expand All @@ -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)**
Expand Down
66 changes: 14 additions & 52 deletions main/data/manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
}
}
Expand Down
72 changes: 37 additions & 35 deletions main/data/settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down