// 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 ( "strings" ) type rawReadingSettings struct { EnablePauseBreaks *bool `toml:"enablePauseBreaks"` SpeakNumbersAsDigits *bool `toml:"speakNumbersAsDigits"` SpeakMultiCaseStringsAsWords *bool `toml:"speakMultiCaseStringsAsWords"` EnableIndentation *bool `toml:"enableIndentation"` OnlySpeakDisplayedText *bool `toml:"onlySpeakDisplayedText"` SpeakBlankLines *bool `toml:"speakBlankLines"` EnableMnemonicSpeaking *bool `toml:"enableMnemonicSpeaking"` EnablePositionSpeaking *bool `toml:"enablePositionSpeaking"` EnableTutorialMessages *bool `toml:"enableTutorialMessages"` MessagesAreDetailed *bool `toml:"messagesAreDetailed"` UseColorNames *bool `toml:"useColorNames"` PresentTooltips *bool `toml:"presentToolTips"` EnableMouseReview *bool `toml:"enableMouseReview"` SpeakMisspelledIndicator *bool `toml:"speakMisspelledIndicator"` SpeakContextBlockquote *bool `toml:"speakContextBlockquote"` SpeakContextList *bool `toml:"speakContextList"` SpeakContextTable *bool `toml:"speakContextTable"` SpeakContextPanel *bool `toml:"speakContextPanel"` SpeakContextLandmark *bool `toml:"speakContextLandmark"` SpeakContextNonLandmarkForm *bool `toml:"speakContextNonLandmarkForm"` SayAllContextBlockquote *bool `toml:"sayAllContextBlockquote"` SayAllContextList *bool `toml:"sayAllContextList"` SayAllContextTable *bool `toml:"sayAllContextTable"` SayAllContextPanel *bool `toml:"sayAllContextPanel"` SayAllContextLandmark *bool `toml:"sayAllContextLandmark"` SayAllContextNonLandmarkForm *bool `toml:"sayAllContextNonLandmarkForm"` ReadFullRowInGUITable *bool `toml:"readFullRowInGUITable"` ReadFullRowInDocumentTable *bool `toml:"readFullRowInDocumentTable"` ReadFullRowInSpreadSheet *bool `toml:"readFullRowInSpreadSheet"` } type rawSettings struct { TimeFormat *string `toml:"time-format"` DateFormat *string `toml:"date-format"` UseCustomEchoVoice *bool `toml:"useCustomEchoVoice"` UseCustomEchoSpeechServer *bool `toml:"useCustomEchoSpeechServer"` UseCustomEchoForKey *bool `toml:"useCustomEchoForKey"` UseCustomEchoForCharacter *bool `toml:"useCustomEchoForCharacter"` UseCustomEchoForWord *bool `toml:"useCustomEchoForWord"` UseCustomEchoForSentence *bool `toml:"useCustomEchoForSentence"` EchoVoice *Voice `toml:"echoVoice"` EchoSpeechServerInfo []string `toml:"echoSpeechServerInfo"` EnableSound *bool `toml:"enableSound"` SoundVolume *float64 `toml:"soundVolume"` SoundSink *string `toml:"soundSink"` SoundTheme *string `toml:"soundTheme"` PlaySoundForRole *bool `toml:"playSoundForRole"` PlaySoundForState *bool `toml:"playSoundForState"` PlaySoundForPositionInSet *bool `toml:"playSoundForPositionInSet"` PlaySoundForValue *bool `toml:"playSoundForValue"` SpatializeObjectSounds *bool `toml:"spatializeObjectSounds"` BeepProgressBarUpdates *bool `toml:"beepProgressBarUpdates"` ProgressBarBeepInterval *int `toml:"progressBarBeepInterval"` RoleSoundPresentation *string `toml:"roleSoundPresentation"` StartingProfile []string `toml:"startingProfile"` ActiveProfile []string `toml:"activeProfile"` EnableSpeech *bool `toml:"enableSpeech"` EnableBraille *bool `toml:"enableBraille"` EnableContractedBraille *bool `toml:"enableContractedBraille"` BrailleContractionTable *string `toml:"brailleContractionTable"` BrailleRolenameStyle *int `toml:"brailleRolenameStyle"` BrailleDisableEOL *bool `toml:"disableBrailleEOL"` BrailleWordWrap *bool `toml:"enableBrailleWordWrap"` BrailleVerbosity *int `toml:"brailleVerbosityLevel"` BrailleSelectionIndicator *int `toml:"brailleSelectorIndicator"` BrailleLinkIndicator *int `toml:"brailleLinkIndicator"` BrailleFlashMessages *bool `toml:"enableFlashMessages"` BrailleFlashTime *int `toml:"brailleFlashTime"` BrailleFlashPersistent *bool `toml:"flashIsPersistent"` BrailleFlashDetailed *bool `toml:"flashIsDetailed"` SpeechServerInfo []string `toml:"speechServerInfo"` HardwareSpeechDevice *string `toml:"hardwareSpeechDevice"` HardwareSpeechBaudRate *int `toml:"hardwareSpeechBaudRate"` SpeechServerFactory *string `toml:"speechServerFactory"` SpeakDescription *bool `toml:"speakDescription"` SpeechVerbosityLevel *int `toml:"speechVerbosityLevel"` SayAllStyle *int `toml:"sayAllStyle"` Reading rawReadingSettings `toml:"reading"` VerbalizePunctuationStyle *int `toml:"verbalizePunctuationStyle"` CapitalizationStyle *string `toml:"capitalizationStyle"` KeyboardLayout *int `toml:"keyboardLayout"` CthulhuModifierKeys *[]string `toml:"cthulhuModifierKeys"` EnableKeyEcho *bool `toml:"enableKeyEcho"` EnableEchoByCharacter *bool `toml:"enableEchoByCharacter"` EnableEchoByWord *bool `toml:"enableEchoByWord"` EnableEchoBySentence *bool `toml:"enableEchoBySentence"` EnableAlphabeticKeys *bool `toml:"enableAlphabeticKeys"` EnableNumericKeys *bool `toml:"enableNumericKeys"` EnablePunctuationKeys *bool `toml:"enablePunctuationKeys"` EnableSpace *bool `toml:"enableSpace"` EnableModifierKeys *bool `toml:"enableModifierKeys"` EnableFunctionKeys *bool `toml:"enableFunctionKeys"` EnableActionKeys *bool `toml:"enableActionKeys"` EnableNavigationKeys *bool `toml:"enableNavigationKeys"` EnableDiacriticalKeys *bool `toml:"enableDiacriticalKeys"` Voices map[string]Voice `toml:"voices"` } type document struct { General rawSettings `toml:"general"` Profiles map[string]rawSettings `toml:"profiles"` } func selectedProfile(general rawSettings, profiles map[string]rawSettings) string { for _, profile := range [][]string{general.StartingProfile, general.ActiveProfile} { if len(profile) >= 2 && strings.TrimSpace(profile[1]) != "" { return profile[1] } } if _, exists := profiles["default"]; exists { return "default" } return "" }