Check the entry boxes by the rules the log window uses

The entry window took any text and only the log window checked it, so the
same value was accepted in one place and refused in the other. The rules
now live in one file, ExchangeCheck, which both windows call.

OperatingPosition.EntryProblem names the first box that cannot be logged
and why. LogContact and SaveQuickEdit throw on one, so a caller that has
not checked cannot write nonsense to the log. The entry window checks
before it logs, puts the reason in the status line and the cursor in the
box to fix, which covers Enter, the Log It button, ESM and {LOG}.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015NZkFxHde1iifAQemFTHxf
This commit is contained in:
2026-09-10 11:13:38 +00:00
co-authored by Claude Opus 5
parent 95e1405be1
commit ab9730b26d
6 changed files with 175 additions and 33 deletions
+18 -2
View File
@@ -490,7 +490,7 @@ public sealed partial class EntryWindow : Window
/// both do.
private void SaveQuickEdit()
{
if (Logging?.SaveQuickEdit() is not { } saved)
if (!IsEntryUsable() || Logging?.SaveQuickEdit() is not { } saved)
{
return;
}
@@ -502,7 +502,7 @@ public sealed partial class EntryWindow : Window
private void LogContact()
{
if (Logging is null)
if (Logging is null || !IsEntryUsable())
{
return;
}
@@ -521,6 +521,22 @@ public sealed partial class EntryWindow : Window
boxes[0].Focus();
}
/// True when everything typed can go in the log. A value the contest will
/// not take puts the reason in the status line and the cursor in its box,
/// which is where the operator has to fix it.
private bool IsEntryUsable()
{
if (Logging?.EntryProblem() is not { } problem)
{
return true;
}
Status(problem.Message);
Logging.Entry.FocusOn(problem.Field);
boxes[problem.Field].Focus();
boxes[problem.Field].SelectAll();
return false;
}
/// What space does: the callsign box and the exchange boxes, stepping over
/// the reports and over a box this station is not asked for, and round to
/// the callsign again. This is N1MM's NextTab.