From 3cef885934901efe0de82a9041d956536f5ed7a7 Mon Sep 17 00:00:00 2001 From: rouggy Date: Mon, 20 Jul 2026 16:12:24 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20Flex=20CWX=20type-ahead=20backspace=20(?= =?UTF-8?q?cwx=20erase)=20=E2=80=94=20phase=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Completes the CWX type-ahead loop: with send-on-type the keyer-panel CW text already streams each typed char to the radio's CWX buffer (which keys in order, so you can keep typing while it sends); this adds the matching un-send. Route wkBackspace to FlexBackspaceCW -> cwx erase N, so backspacing a mistyped char in send-on-type removes it from the buffer before the radio keys it. --- app.go | 9 +++++++++ frontend/src/App.tsx | 7 +++++-- frontend/wailsjs/go/main/App.d.ts | 2 ++ frontend/wailsjs/go/main/App.js | 4 ++++ internal/cat/cat.go | 5 ++++- internal/cat/flex.go | 11 +++++++++++ 6 files changed, 35 insertions(+), 3 deletions(-) diff --git a/app.go b/app.go index 8f492a5..098d2c8 100644 --- a/app.go +++ b/app.go @@ -10389,6 +10389,15 @@ func (a *App) FlexSetKeySpeed(wpm int) error { return a.cat.FlexDo(func(fc cat.FlexController) error { return fc.SetCWSpeed(wpm) }) } +// FlexBackspaceCW removes the last n not-yet-keyed characters from the CWX buffer +// (type-ahead correction). n<1 deletes one. +func (a *App) FlexBackspaceCW(n int) error { + if a.cat == nil { + return fmt.Errorf("cat not initialized") + } + return a.cat.FlexDo(func(fc cat.FlexController) error { return fc.BackspaceCW(n) }) +} + // IcomStopCW aborts the CW message currently being sent. func (a *App) IcomStopCW() error { if a.cat == nil { diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 8bceaf1..8d5f0b4 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -36,7 +36,7 @@ import { GetWinkeyerSettings, SaveWinkeyerSettings, ListSerialPorts, GetWinkeyerStatus, WinkeyerConnect, WinkeyerDisconnect, WinkeyerSend, WinkeyerStop, WinkeyerSetSpeed, WinkeyerBackspace, IcomSendCW, IcomStopCW, IcomSetKeySpeed, IcomSetBreakIn, GetIcomState, - FlexSendCW, FlexStopCW, FlexSetKeySpeed, + FlexSendCW, FlexStopCW, FlexSetKeySpeed, FlexBackspaceCW, GetDVKMessages, GetDVKStatus, DVKPlay, DVKStop, StartCWDecoder, StopCWDecoder, SetCWDecoderPitch, ChatAvailable, GetChatHistory, SendChatMessage, GetOnlineOperators, @@ -2221,7 +2221,10 @@ export default function App() { if (cwSourceRef.current === 'flex') { FlexSendCW(chars).catch(() => {}); return; } WinkeyerSend(chars).catch(() => {}); } - function wkBackspace() { WinkeyerBackspace().catch(() => {}); } + function wkBackspace() { + if (cwSourceRef.current === 'flex') { FlexBackspaceCW(1).catch(() => {}); return; } + WinkeyerBackspace().catch(() => {}); + } function wkToggleSendOnType(on: boolean) { setWkSendOnType(on); saveWk({ send_on_type: on }); } // Resolve slot status for any spot we haven't seen yet — debounced so we diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index fb09e98..e1a5e96 100644 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -192,6 +192,8 @@ export function FlexAmpOperate(arg1:boolean):Promise; export function FlexApplyBandAntenna(arg1:string):Promise; +export function FlexBackspaceCW(arg1:number):Promise; + export function FlexMox(arg1:boolean):Promise; export function FlexSendCW(arg1:string):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index af784db..bbf7fab 100644 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -342,6 +342,10 @@ export function FlexApplyBandAntenna(arg1) { return window['go']['main']['App']['FlexApplyBandAntenna'](arg1); } +export function FlexBackspaceCW(arg1) { + return window['go']['main']['App']['FlexBackspaceCW'](arg1); +} + export function FlexMox(arg1) { return window['go']['main']['App']['FlexMox'](arg1); } diff --git a/internal/cat/cat.go b/internal/cat/cat.go index 65d8ae9..ad62c0f 100644 --- a/internal/cat/cat.go +++ b/internal/cat/cat.go @@ -396,9 +396,12 @@ type FlexController interface { SetCWBreakInDelay(int) error // CWX keyer — buffered CW keying via SmartSDR's CWX subsystem, so a Flex needs // no WinKeyer / SmartCAT. SendCW queues text (the radio buffers and keys it); - // StopCW clears the buffer, aborting the send. + // StopCW clears the buffer, aborting the send. BackspaceCW removes the last n + // not-yet-keyed characters from the buffer (un-send while sending — for + // type-ahead corrections). SendCW(string) error StopCW() error + BackspaceCW(int) error SetCWSidetone(bool) error SetSidetoneLevel(int) error SetCWFilter(int) error diff --git a/internal/cat/flex.go b/internal/cat/flex.go index cdadd44..3b57876 100644 --- a/internal/cat/flex.go +++ b/internal/cat/flex.go @@ -1601,6 +1601,17 @@ func (f *Flex) StopCW() error { return nil } +// BackspaceCW removes the last n not-yet-keyed characters from the CWX buffer — +// the "un-send while sending" a serial WinKeyer can't do. Used for type-ahead +// corrections (backspacing a mistyped call before the radio has keyed it). +func (f *Flex) BackspaceCW(n int) error { + if n < 1 { + n = 1 + } + f.send(fmt.Sprintf("cwx erase %d", n)) + return nil +} + func (f *Flex) SetCWSidetone(on bool) error { f.mu.Lock() f.tx.cwSidetone = on