diff --git a/README.md b/README.md index 80c3430..2d137c8 100644 --- a/README.md +++ b/README.md @@ -91,8 +91,20 @@ mode stay where they were last typed. ### CW **Config → Keyer and messages** picks `cwdaemon` (a UDP port, usually 6789) or a -WinKeyer (a serial port), sets the speed, and edits the twelve function key -messages for CW and for phone. Escape stops sending. +WinKeyer (a serial port) and sets the speed. Escape stops sending. + +The messages are edited as their file, in a plain text editor: right-click any +of the function key buttons under the entry window, or use the two buttons in +Config → Keyer and messages. One line per key — the button label, a comma, then +the message — and a line starting with `#` is a comment. Which key a line +belongs to is decided by where it is in the file: the first twelve lines are F1 +to F12 while running, and twelve more give the same keys while searching, with +the ones left out keeping their running message. The buttons say what the file +says, and they change as you move between running and searching. + +This is N1MM's `.mc` format. **Import…** reads a file somebody published for +N1MM, **Export…** writes one out, and **Back to the defaults** puts the built-in +messages back. The macros are N1MM's, spelled the way N1MM's function-key documentation spells them, so a `.mc` file written for either program says the same thing. The text diff --git a/src/Nonemm.App/AppSession.cs b/src/Nonemm.App/AppSession.cs index 8191331..b5035ef 100644 --- a/src/Nonemm.App/AppSession.cs +++ b/src/Nonemm.App/AppSession.cs @@ -361,10 +361,10 @@ public sealed class AppSession : IDisposable { throw new InvalidOperationException("there is no keyer"); } - string template = Messages.For( - position.Mode.Category, - Settings.CwMessages, - Settings.PhoneMessages)[0]; + string template = Messages + .For(position.Mode.Category, Settings.CwMessageFile, Settings.PhoneMessageFile) + .Keys(position.IsRunning)[Esm.CallCq] + .Message; if (template.Length == 0) { throw new InvalidOperationException("F1 has no message — Config ▸ Keyer and messages"); diff --git a/src/Nonemm.App/Configuration/Settings.cs b/src/Nonemm.App/Configuration/Settings.cs index 429212d..5274deb 100644 --- a/src/Nonemm.App/Configuration/Settings.cs +++ b/src/Nonemm.App/Configuration/Settings.cs @@ -140,7 +140,15 @@ public sealed record Settings /// in `BandPlan.Default`; an entry replaces one band's boundaries. public IReadOnlyList SubBands { get; init; } = []; - /// The twelve function key messages, keyed F1 to F12. + /// The function key messages as the text of an N1MM `.mc` file, which is + /// what the editor edits and what import and export read and write. Empty + /// means the built-in messages. + public string CwMessageFile { get; init; } = ""; + + public string PhoneMessageFile { get; init; } = ""; + + /// Written by versions that kept twelve messages and no labels. Read once, + /// to fill the file text in, and never written again. public IReadOnlyList CwMessages { get; init; } = []; public IReadOnlyList PhoneMessages { get; init; } = []; @@ -232,11 +240,31 @@ public sealed record Settings } } - /// Carries the single radio an older settings file holds into the list. - private static Settings Migrated(Settings settings) => - settings.Radios.Count > 0 || settings.RigctldHost.Length == 0 - ? settings - : settings with + /// The twelve messages an older settings file holds, written out as the + /// text of a function key file with the labels this program used then. + private static string FileFrom(IReadOnlyList messages) + { + IReadOnlyList<(string Key, string Label)> keys = + [ + ("F1", "CQ"), ("F2", "Exch"), ("F3", "TU"), ("F4", "MyCall"), + ("F5", "HisCall"), ("F6", "QSO B4"), ("F7", "?"), ("F8", "Agn"), + ("F9", "Nr?"), ("F10", "Call?"), ("F11", "Spot"), ("F12", "Wipe"), + ]; + return string.Join( + '\n', + messages.Select((message, at) => at < keys.Count + ? $"{keys[at].Key} {keys[at].Label},{message}" + : $",{message}")); + } + + /// Carries what older settings files hold into the shape this one uses: the + /// single radio into the list of radios, and the twelve messages into the + /// text of a function key file. + private static Settings Migrated(Settings settings) + { + if (settings.RigctldHost.Length > 0 && settings.Radios.Count == 0) + { + settings = settings with { Radios = [new StoredRadio { @@ -248,6 +276,21 @@ public sealed record Settings RigctldPort = 0, RadioEnabled = false, }; + } + if (settings.CwMessages.Count > 0 && settings.CwMessageFile.Length == 0) + { + settings = settings with { CwMessageFile = FileFrom(settings.CwMessages), CwMessages = [] }; + } + if (settings.PhoneMessages.Count > 0 && settings.PhoneMessageFile.Length == 0) + { + settings = settings with + { + PhoneMessageFile = FileFrom(settings.PhoneMessages), + PhoneMessages = [], + }; + } + return settings; + } } /// One band's sub-band boundaries as they are stored. Kilohertz, because that diff --git a/src/Nonemm.App/Dialogs/KeyerDialog.axaml b/src/Nonemm.App/Dialogs/KeyerDialog.axaml index 8c882cc..834debb 100644 --- a/src/Nonemm.App/Dialogs/KeyerDialog.axaml +++ b/src/Nonemm.App/Dialogs/KeyerDialog.axaml @@ -1,7 +1,7 @@ @@ -23,9 +23,11 @@ Text="Ctrl+B starts calling CQ on one radio and then the other. Needs two radios." /> - - - + + +