// Cthulhu screen reader. // Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation, either version 3 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU General Public License along with // this program. If not, see . package config import ( "git.stormux.org/storm/cthulhu/internal/datetime" ) func apply(settings *Settings, values rawSettings) { // Keep the established patch order; absent fields leave prior values intact. apply_legacy_sound(settings, values) apply_legacy_output(settings, values) apply_legacy_speech_service(settings, values) apply_legacy_reading(settings, values) apply_legacy_speech_formats(settings, values) apply_legacy_keyboard(settings, values) apply_legacy_echo(settings, values) apply_legacy_default_voice(settings, values) } func apply_legacy_sound(settings *Settings, values rawSettings) { if values.EnableSound != nil { settings.EnableSound = *values.EnableSound } if values.SoundVolume != nil { settings.SoundVolume = *values.SoundVolume } if values.SoundSink != nil { settings.SoundSink = *values.SoundSink } if values.SoundTheme != nil { settings.SoundTheme = *values.SoundTheme } if values.PlaySoundForRole != nil { settings.PlaySoundForRole = *values.PlaySoundForRole } if values.PlaySoundForState != nil { settings.PlaySoundForState = *values.PlaySoundForState } if values.PlaySoundForPositionInSet != nil { settings.PlaySoundForPositionInSet = *values.PlaySoundForPositionInSet } if values.SpatializeObjectSounds != nil { settings.SpatializeObjectSounds = *values.SpatializeObjectSounds } if values.RoleSoundPresentation != nil { settings.RoleSoundPresentation = *values.RoleSoundPresentation } } func apply_legacy_output(settings *Settings, values rawSettings) { if values.EnableSpeech != nil { settings.EnableSpeech = *values.EnableSpeech } if values.EnableBraille != nil { settings.EnableBraille = *values.EnableBraille } if values.EnableContractedBraille != nil { settings.EnableContractedBraille = *values.EnableContractedBraille } if values.BrailleContractionTable != nil { settings.BrailleContractionTable = *values.BrailleContractionTable } if values.BrailleRolenameStyle != nil { settings.Braille.AbbreviateRoles = *values.BrailleRolenameStyle == 0 } if values.BrailleDisableEOL != nil { settings.Braille.DisableEOL = *values.BrailleDisableEOL } if values.BrailleWordWrap != nil { settings.Braille.WordWrap = *values.BrailleWordWrap } if values.BrailleVerbosity != nil { settings.Braille.Verbosity = *values.BrailleVerbosity } if values.BrailleSelectionIndicator != nil { settings.Braille.SelectionIndicator = *values.BrailleSelectionIndicator } if values.BrailleLinkIndicator != nil { settings.Braille.LinkIndicator = *values.BrailleLinkIndicator } if values.BrailleFlashMessages != nil { settings.Braille.FlashMessages = *values.BrailleFlashMessages } if values.BrailleFlashTime != nil { settings.Braille.FlashTime = *values.BrailleFlashTime } if values.BrailleFlashPersistent != nil { settings.Braille.FlashPersistent = *values.BrailleFlashPersistent } if values.BrailleFlashDetailed != nil { settings.Braille.FlashDetailed = *values.BrailleFlashDetailed } } func apply_legacy_speech_service(settings *Settings, values rawSettings) { if values.HardwareSpeechDevice != nil { settings.HardwareSpeechDevice = *values.HardwareSpeechDevice } if values.HardwareSpeechBaudRate != nil { settings.HardwareSpeechBaudRate = *values.HardwareSpeechBaudRate } if values.SpeechServerFactory != nil { settings.SpeechServerFactory = *values.SpeechServerFactory } if settings.SpeechServerFactory == "hardwarefactory" && len(values.SpeechServerInfo) > 1 { settings.SpeechOutputModule = values.SpeechServerInfo[1] } if values.SpeakDescription != nil { settings.SpeakDescription = *values.SpeakDescription } if values.SpeechVerbosityLevel != nil { settings.SpeechVerbosityLevel = *values.SpeechVerbosityLevel } if values.SayAllStyle != nil { settings.SayAllStyle = map[int]string{0: "line", 1: "sentence"}[*values.SayAllStyle] } } func apply_legacy_reading(settings *Settings, values rawSettings) { if values.Reading.OnlySpeakDisplayedText != nil { settings.Reading.OnlySpeakDisplayedText = *values.Reading.OnlySpeakDisplayedText } if values.Reading.SpeakBlankLines != nil { settings.Reading.SpeakBlankLines = *values.Reading.SpeakBlankLines } if values.Reading.EnableMnemonicSpeaking != nil { settings.Reading.EnableMnemonicSpeaking = *values.Reading.EnableMnemonicSpeaking } if values.Reading.EnablePositionSpeaking != nil { settings.Reading.EnablePositionSpeaking = *values.Reading.EnablePositionSpeaking } if values.Reading.EnableTutorialMessages != nil { settings.Reading.EnableTutorialMessages = *values.Reading.EnableTutorialMessages } if values.Reading.MessagesAreDetailed != nil { settings.Reading.MessagesAreDetailed = *values.Reading.MessagesAreDetailed } if values.Reading.UseColorNames != nil { settings.Reading.UseColorNames = *values.Reading.UseColorNames } if values.Reading.PresentTooltips != nil { settings.Reading.PresentTooltips = *values.Reading.PresentTooltips } if values.Reading.EnableMouseReview != nil { settings.Reading.EnableMouseReview = *values.Reading.EnableMouseReview } if values.Reading.SpeakMisspelledIndicator != nil { settings.Reading.SpeakMisspelledIndicator = *values.Reading.SpeakMisspelledIndicator } if values.Reading.EnablePauseBreaks != nil { settings.Reading.EnablePauseBreaks = *values.Reading.EnablePauseBreaks } if values.Reading.SpeakNumbersAsDigits != nil { settings.Reading.SpeakNumbersAsDigits = *values.Reading.SpeakNumbersAsDigits } if values.Reading.SpeakMultiCaseStringsAsWords != nil { settings.Reading.SpeakMultiCaseStringsAsWords = *values.Reading.SpeakMultiCaseStringsAsWords } if values.Reading.EnableIndentation != nil { settings.Reading.EnableIndentation = *values.Reading.EnableIndentation } if values.Reading.SpeakContextBlockquote != nil { settings.Reading.SpeakContextBlockquote = *values.Reading.SpeakContextBlockquote } if values.Reading.SpeakContextList != nil { settings.Reading.SpeakContextList = *values.Reading.SpeakContextList } if values.Reading.SpeakContextTable != nil { settings.Reading.SpeakContextTable = *values.Reading.SpeakContextTable } if values.Reading.SpeakContextPanel != nil { settings.Reading.SpeakContextPanel = *values.Reading.SpeakContextPanel } if values.Reading.SpeakContextLandmark != nil { settings.Reading.SpeakContextLandmark = *values.Reading.SpeakContextLandmark } if values.Reading.SpeakContextNonLandmarkForm != nil { settings.Reading.SpeakContextNonLandmarkForm = *values.Reading.SpeakContextNonLandmarkForm } if values.Reading.SayAllContextBlockquote != nil { settings.Reading.SayAllContextBlockquote = *values.Reading.SayAllContextBlockquote } if values.Reading.SayAllContextList != nil { settings.Reading.SayAllContextList = *values.Reading.SayAllContextList } if values.Reading.SayAllContextTable != nil { settings.Reading.SayAllContextTable = *values.Reading.SayAllContextTable } if values.Reading.SayAllContextPanel != nil { settings.Reading.SayAllContextPanel = *values.Reading.SayAllContextPanel } if values.Reading.SayAllContextLandmark != nil { settings.Reading.SayAllContextLandmark = *values.Reading.SayAllContextLandmark } if values.Reading.SayAllContextNonLandmarkForm != nil { settings.Reading.SayAllContextNonLandmarkForm = *values.Reading.SayAllContextNonLandmarkForm } if values.Reading.ReadFullRowInGUITable != nil { settings.Reading.ReadFullRowInGUITable = *values.Reading.ReadFullRowInGUITable } if values.Reading.ReadFullRowInDocumentTable != nil { settings.Reading.ReadFullRowInDocumentTable = *values.Reading.ReadFullRowInDocumentTable } if values.Reading.ReadFullRowInSpreadSheet != nil { settings.Reading.ReadFullRowInSpreadSheet = *values.Reading.ReadFullRowInSpreadSheet } } func apply_legacy_speech_formats(settings *Settings, values rawSettings) { if values.VerbalizePunctuationStyle != nil { settings.VerbalizePunctuationStyle = *values.VerbalizePunctuationStyle } if values.CapitalizationStyle != nil { settings.SetCapitalizationStyle(*values.CapitalizationStyle) } if values.TimeFormat != nil { settings.TimeFormat = *values.TimeFormat } if values.DateFormat != nil { settings.DateFormat = datetime.NormalizeDate(*values.DateFormat) } } func apply_legacy_keyboard(settings *Settings, values rawSettings) { if values.KeyboardLayout != nil { settings.KeyboardLayout = *values.KeyboardLayout } if values.CthulhuModifierKeys != nil { settings.CthulhuModifierKeys = append([]string(nil), (*values.CthulhuModifierKeys)...) } } func apply_legacy_echo(settings *Settings, values rawSettings) { if values.UseCustomEchoVoice != nil { settings.UseCustomEchoVoice = *values.UseCustomEchoVoice } if values.UseCustomEchoSpeechServer != nil { settings.UseCustomEchoSpeechServer = *values.UseCustomEchoSpeechServer } if values.UseCustomEchoForKey != nil { settings.UseCustomEchoForKey = *values.UseCustomEchoForKey } if values.UseCustomEchoForCharacter != nil { settings.UseCustomEchoForCharacter = *values.UseCustomEchoForCharacter } if values.UseCustomEchoForWord != nil { settings.UseCustomEchoForWord = *values.UseCustomEchoForWord } if values.UseCustomEchoForSentence != nil { settings.UseCustomEchoForSentence = *values.UseCustomEchoForSentence } if values.EchoVoice != nil { mergeVoice(&settings.EchoVoice, *values.EchoVoice) } if len(values.EchoSpeechServerInfo) > 1 { settings.EchoSpeechServer = values.EchoSpeechServerInfo[1] } if values.EnableKeyEcho != nil { settings.EnableKeyEcho = *values.EnableKeyEcho } if values.EnableEchoByCharacter != nil { settings.EnableEchoByCharacter = *values.EnableEchoByCharacter } if values.EnableEchoByWord != nil { settings.EnableEchoByWord = *values.EnableEchoByWord } if values.EnableEchoBySentence != nil { settings.EnableEchoBySentence = *values.EnableEchoBySentence } if values.EnableAlphabeticKeys != nil { settings.EnableAlphabeticKeys = *values.EnableAlphabeticKeys } if values.EnableNumericKeys != nil { settings.EnableNumericKeys = *values.EnableNumericKeys } if values.EnablePunctuationKeys != nil { settings.EnablePunctuationKeys = *values.EnablePunctuationKeys } if values.EnableSpace != nil { settings.EnableSpace = *values.EnableSpace } if values.EnableModifierKeys != nil { settings.EnableModifierKeys = *values.EnableModifierKeys } if values.EnableFunctionKeys != nil { settings.EnableFunctionKeys = *values.EnableFunctionKeys } if values.EnableActionKeys != nil { settings.EnableActionKeys = *values.EnableActionKeys } if values.EnableNavigationKeys != nil { settings.EnableNavigationKeys = *values.EnableNavigationKeys } if values.EnableDiacriticalKeys != nil { settings.EnableDiacriticalKeys = *values.EnableDiacriticalKeys } } func apply_legacy_default_voice(settings *Settings, values rawSettings) { if voice, exists := values.Voices["default"]; exists { mergeVoice(&settings.DefaultVoice, voice) } } func mergeVoice(target *Voice, source Voice) { if source.Rate != nil { target.Rate = source.Rate } if source.AveragePitch != nil { target.AveragePitch = source.AveragePitch } if source.Gain != nil { target.Gain = source.Gain } if source.Family != nil { family := *source.Family target.Family = &family } }