577 lines
24 KiB
Go
577 lines
24 KiB
Go
// 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 <https://www.gnu.org/licenses/gpl-3.0.html>.
|
|
|
|
package config
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"git.stormux.org/storm/cthulhu/internal/datetime"
|
|
"git.stormux.org/storm/cthulhu/internal/input"
|
|
)
|
|
|
|
// Application profiles store only values that differ from the global profile.
|
|
// The writable schema is made of nested value structs and pointer fields, so
|
|
// clearing equal leaves preserves its existing patch semantics.
|
|
func applicationProfileDifference(global, application Settings) writableProfile {
|
|
base := profileFromSettings(global)
|
|
result := profileFromSettings(application)
|
|
clearEqualProfileFields(reflect.ValueOf(&result).Elem(), reflect.ValueOf(base))
|
|
return result
|
|
}
|
|
|
|
func clearEqualProfileFields(result, base reflect.Value) {
|
|
for index := 0; index < result.NumField(); index++ {
|
|
field, baseline := result.Field(index), base.Field(index)
|
|
if field.Kind() == reflect.Struct {
|
|
clearEqualProfileFields(field, baseline)
|
|
} else if reflect.DeepEqual(field.Interface(), baseline.Interface()) {
|
|
field.SetZero()
|
|
}
|
|
}
|
|
}
|
|
|
|
// RebaseApplicationSettings keeps session-only application choices when the
|
|
// global profile changes, while newly inherited values follow the new global.
|
|
func RebaseApplicationSettings(oldGlobal, newGlobal, application Settings) Settings {
|
|
patch := applicationProfileDifference(oldGlobal, application)
|
|
rebased := newGlobal
|
|
applyProfile(&rebased, patch)
|
|
rebased.ActiveProfile = application.ActiveProfile
|
|
return rebased
|
|
}
|
|
|
|
func profileFromSettings(settings Settings) writableProfile {
|
|
return writableProfile{
|
|
OCR: writableOCR{Language: stringPointer(settings.OCR.Language), Layout: intPointer(settings.OCR.Layout), Scale: intPointer(settings.OCR.Scale), Grayscale: boolPointer(settings.OCR.Grayscale), Invert: boolPointer(settings.OCR.Invert), BlackWhite: boolPointer(settings.OCR.BlackWhite), Threshold: intPointer(settings.OCR.Threshold), AutoRefresh: boolPointer(settings.OCR.AutoRefresh), RefreshInterval: intPointer(settings.OCR.RefreshInterval), ConfirmClick: boolPointer(settings.OCR.ConfirmClick), CopyFirstResult: boolPointer(settings.OCR.CopyFirstResult), AutoReadAll: boolPointer(settings.OCR.AutoReadAll)},
|
|
ProgressBar: writableProgressBar{
|
|
OutputMode: stringPointer(settings.ProgressBar.OutputMode),
|
|
ReportBackground: boolPointer(settings.ProgressBar.ReportBackground),
|
|
BeepPercentageInterval: intPointer(settings.ProgressBar.BeepPercentageInterval),
|
|
SpeechPercentageInterval: intPointer(settings.ProgressBar.SpeechPercentageInterval),
|
|
},
|
|
Presentation: writablePresentation{
|
|
Pronunciations: pronunciationSlicePointer(settings.Pronunciations),
|
|
TextAttributes: writableTextAttributes{Choices: textAttributeSlicePointer(settings.TextAttributes.Choices), Indicator: intPointer(settings.TextAttributes.Indicator)},
|
|
TimeFormat: stringPointer(settings.TimeFormat), DateFormat: stringPointer(settings.DateFormat),
|
|
SpeakDescription: boolPointer(settings.SpeakDescription),
|
|
SpeechVerbosityLevel: intPointer(settings.SpeechVerbosityLevel),
|
|
SayAllStyle: stringPointer(settings.SayAllStyle),
|
|
Reading: writableReading{
|
|
AutomaticallyReadClipboardChanges: boolPointer(settings.Reading.AutomaticallyReadClipboardChanges),
|
|
AutomaticallyReadTitleChanges: boolPointer(settings.Reading.AutomaticallyReadTitleChanges),
|
|
EnablePauseBreaks: boolPointer(settings.Reading.EnablePauseBreaks),
|
|
SpeakNumbersAsDigits: boolPointer(settings.Reading.SpeakNumbersAsDigits),
|
|
SpeakMultiCaseStringsAsWords: boolPointer(settings.Reading.SpeakMultiCaseStringsAsWords),
|
|
EnableIndentation: boolPointer(settings.Reading.EnableIndentation),
|
|
IndentationPresentationMode: stringPointer(settings.Reading.IndentationPresentationMode),
|
|
OnlySpeakDisplayedText: boolPointer(settings.Reading.OnlySpeakDisplayedText),
|
|
SpeakBlankLines: boolPointer(settings.Reading.SpeakBlankLines),
|
|
EnableMnemonicSpeaking: boolPointer(settings.Reading.EnableMnemonicSpeaking),
|
|
EnablePositionSpeaking: boolPointer(settings.Reading.EnablePositionSpeaking),
|
|
EnableTutorialMessages: boolPointer(settings.Reading.EnableTutorialMessages),
|
|
MessagesAreDetailed: boolPointer(settings.Reading.MessagesAreDetailed),
|
|
UseColorNames: boolPointer(settings.Reading.UseColorNames),
|
|
PresentTooltips: boolPointer(settings.Reading.PresentTooltips),
|
|
EnableMouseReview: boolPointer(settings.Reading.EnableMouseReview),
|
|
SpeakMisspelledIndicator: boolPointer(settings.Reading.SpeakMisspelledIndicator),
|
|
SpeakContextBlockquote: boolPointer(settings.Reading.SpeakContextBlockquote),
|
|
SpeakContextList: boolPointer(settings.Reading.SpeakContextList),
|
|
SpeakContextTable: boolPointer(settings.Reading.SpeakContextTable),
|
|
SpeakContextPanel: boolPointer(settings.Reading.SpeakContextPanel),
|
|
SpeakContextLandmark: boolPointer(settings.Reading.SpeakContextLandmark),
|
|
SpeakContextNonLandmarkForm: boolPointer(settings.Reading.SpeakContextNonLandmarkForm),
|
|
SayAllContextBlockquote: boolPointer(settings.Reading.SayAllContextBlockquote),
|
|
SayAllContextList: boolPointer(settings.Reading.SayAllContextList),
|
|
SayAllContextTable: boolPointer(settings.Reading.SayAllContextTable),
|
|
SayAllContextPanel: boolPointer(settings.Reading.SayAllContextPanel),
|
|
SayAllContextLandmark: boolPointer(settings.Reading.SayAllContextLandmark),
|
|
SayAllContextNonLandmarkForm: boolPointer(settings.Reading.SayAllContextNonLandmarkForm),
|
|
ReadFullRowInGUITable: boolPointer(settings.Reading.ReadFullRowInGUITable),
|
|
ReadFullRowInDocumentTable: boolPointer(settings.Reading.ReadFullRowInDocumentTable),
|
|
ReadFullRowInSpreadSheet: boolPointer(settings.Reading.ReadFullRowInSpreadSheet),
|
|
},
|
|
},
|
|
Speech: writableSpeech{
|
|
HardwareDevice: stringPointer(settings.HardwareSpeechDevice),
|
|
HardwareBaudRate: intPointer(settings.HardwareSpeechBaudRate),
|
|
Enabled: boolPointer(settings.EnableSpeech), ServerFactory: stringPointer(settings.SpeechServerFactory),
|
|
HistoryLimit: intPointer(settings.SpeechHistoryLimit),
|
|
Punctuation: intPointer(settings.VerbalizePunctuationStyle), Capitalization: stringPointer(settings.CapitalizationStyle),
|
|
DefaultVoice: voicePointer(settings.DefaultVoice),
|
|
UppercaseVoice: voicePointer(settings.UppercaseVoice),
|
|
HyperlinkVoice: voicePointer(settings.HyperlinkVoice),
|
|
SystemVoice: voicePointer(settings.SystemVoice),
|
|
OutputModule: stringPointer(settings.SpeechOutputModule),
|
|
},
|
|
Braille: writableBraille{Enabled: boolPointer(settings.EnableBraille),
|
|
Contracted: boolPointer(settings.EnableContractedBraille),
|
|
ContractionTable: stringPointer(settings.BrailleContractionTable),
|
|
AbbreviateRoles: boolPointer(settings.Braille.AbbreviateRoles),
|
|
DisableEOL: boolPointer(settings.Braille.DisableEOL), WordWrap: boolPointer(settings.Braille.WordWrap),
|
|
Verbosity: intPointer(settings.Braille.Verbosity), SelectionIndicator: intPointer(settings.Braille.SelectionIndicator),
|
|
LinkIndicator: intPointer(settings.Braille.LinkIndicator), FlashMessages: boolPointer(settings.Braille.FlashMessages),
|
|
FlashTime: intPointer(settings.Braille.FlashTime), FlashPersistent: boolPointer(settings.Braille.FlashPersistent),
|
|
FlashDetailed: boolPointer(settings.Braille.FlashDetailed)},
|
|
Sound: writableSound{
|
|
Enabled: boolPointer(settings.EnableSound), Volume: floatPointer(settings.SoundVolume),
|
|
Sink: stringPointer(settings.SoundSink), Theme: stringPointer(settings.SoundTheme),
|
|
PlayForRole: boolPointer(settings.PlaySoundForRole), PlayForState: boolPointer(settings.PlaySoundForState),
|
|
PlayForPosition: boolPointer(settings.PlaySoundForPositionInSet),
|
|
Spatialize: boolPointer(settings.SpatializeObjectSounds),
|
|
RolePresentationStrategy: stringPointer(settings.RoleSoundPresentation),
|
|
},
|
|
Keyboard: writableKeyboard{
|
|
Bindings: bindingSlicePointer(settings.KeyBindings),
|
|
Layout: intPointer(settings.KeyboardLayout),
|
|
ScreenReaderKeys: stringSlicePointer(settings.CthulhuModifierKeys),
|
|
},
|
|
KeyEcho: writableKeyEcho{
|
|
UseCustomEchoVoice: boolPointer(settings.UseCustomEchoVoice),
|
|
UseCustomEchoSpeechServer: boolPointer(settings.UseCustomEchoSpeechServer),
|
|
UseCustomEchoForKey: boolPointer(settings.UseCustomEchoForKey),
|
|
UseCustomEchoForCharacter: boolPointer(settings.UseCustomEchoForCharacter),
|
|
UseCustomEchoForWord: boolPointer(settings.UseCustomEchoForWord),
|
|
UseCustomEchoForSentence: boolPointer(settings.UseCustomEchoForSentence),
|
|
EchoVoice: voicePointer(settings.EchoVoice), EchoSpeechServer: stringPointer(settings.EchoSpeechServer),
|
|
|
|
Enabled: boolPointer(settings.EnableKeyEcho), ByCharacter: boolPointer(settings.EnableEchoByCharacter),
|
|
ByWord: boolPointer(settings.EnableEchoByWord), BySentence: boolPointer(settings.EnableEchoBySentence),
|
|
Alphabetic: boolPointer(settings.EnableAlphabeticKeys), Numeric: boolPointer(settings.EnableNumericKeys),
|
|
Punctuation: boolPointer(settings.EnablePunctuationKeys), Space: boolPointer(settings.EnableSpace),
|
|
Modifiers: boolPointer(settings.EnableModifierKeys), FunctionKeys: boolPointer(settings.EnableFunctionKeys),
|
|
ActionKeys: boolPointer(settings.EnableActionKeys), NavigationKeys: boolPointer(settings.EnableNavigationKeys),
|
|
Diacritical: boolPointer(settings.EnableDiacriticalKeys),
|
|
},
|
|
}
|
|
}
|
|
|
|
func applyProfile(settings *Settings, profile writableProfile) {
|
|
apply_profile_ocr(&settings.OCR, profile.OCR)
|
|
// Keep the established patch order; absent fields leave prior values intact.
|
|
apply_profile_formats(settings, profile)
|
|
apply_profile_echo_voice(settings, profile)
|
|
apply_profile_reading(settings, profile)
|
|
apply_profile_output(settings, profile)
|
|
apply_profile_speech(settings, profile)
|
|
apply_profile_sound(settings, profile)
|
|
if value := profile.ProgressBar.OutputMode; value != nil {
|
|
settings.ProgressBar.OutputMode = *value
|
|
}
|
|
if value := profile.ProgressBar.ReportBackground; value != nil {
|
|
settings.ProgressBar.ReportBackground = *value
|
|
}
|
|
if value := profile.ProgressBar.BeepPercentageInterval; value != nil {
|
|
settings.ProgressBar.BeepPercentageInterval = *value
|
|
}
|
|
if value := profile.ProgressBar.SpeechPercentageInterval; value != nil {
|
|
settings.ProgressBar.SpeechPercentageInterval = *value
|
|
}
|
|
apply_profile_keyboard(settings, profile)
|
|
apply_profile_echo_keys(settings, profile)
|
|
}
|
|
|
|
func apply_profile_ocr(settings *OCRSettings, patch writableOCR) {
|
|
if patch.Language != nil {
|
|
settings.Language = *patch.Language
|
|
}
|
|
if patch.Layout != nil {
|
|
settings.Layout = *patch.Layout
|
|
}
|
|
if patch.Scale != nil {
|
|
settings.Scale = *patch.Scale
|
|
}
|
|
if patch.Grayscale != nil {
|
|
settings.Grayscale = *patch.Grayscale
|
|
}
|
|
if patch.Invert != nil {
|
|
settings.Invert = *patch.Invert
|
|
}
|
|
if patch.BlackWhite != nil {
|
|
settings.BlackWhite = *patch.BlackWhite
|
|
}
|
|
if patch.Threshold != nil {
|
|
settings.Threshold = *patch.Threshold
|
|
}
|
|
if patch.AutoRefresh != nil {
|
|
settings.AutoRefresh = *patch.AutoRefresh
|
|
}
|
|
if patch.RefreshInterval != nil {
|
|
settings.RefreshInterval = *patch.RefreshInterval
|
|
}
|
|
if patch.ConfirmClick != nil {
|
|
settings.ConfirmClick = *patch.ConfirmClick
|
|
}
|
|
if patch.CopyFirstResult != nil {
|
|
settings.CopyFirstResult = *patch.CopyFirstResult
|
|
}
|
|
if patch.AutoReadAll != nil {
|
|
settings.AutoReadAll = *patch.AutoReadAll
|
|
}
|
|
}
|
|
|
|
func apply_profile_formats(settings *Settings, profile writableProfile) {
|
|
if v := profile.Presentation.TimeFormat; v != nil {
|
|
settings.TimeFormat = *v
|
|
}
|
|
if v := profile.Presentation.DateFormat; v != nil {
|
|
settings.DateFormat = datetime.NormalizeDate(*v)
|
|
}
|
|
}
|
|
|
|
func apply_profile_echo_voice(settings *Settings, profile writableProfile) {
|
|
if v := profile.KeyEcho.UseCustomEchoVoice; v != nil {
|
|
settings.UseCustomEchoVoice = *v
|
|
}
|
|
if v := profile.KeyEcho.UseCustomEchoSpeechServer; v != nil {
|
|
settings.UseCustomEchoSpeechServer = *v
|
|
}
|
|
if v := profile.KeyEcho.UseCustomEchoForKey; v != nil {
|
|
settings.UseCustomEchoForKey = *v
|
|
}
|
|
if v := profile.KeyEcho.UseCustomEchoForCharacter; v != nil {
|
|
settings.UseCustomEchoForCharacter = *v
|
|
}
|
|
if v := profile.KeyEcho.UseCustomEchoForWord; v != nil {
|
|
settings.UseCustomEchoForWord = *v
|
|
}
|
|
if v := profile.KeyEcho.UseCustomEchoForSentence; v != nil {
|
|
settings.UseCustomEchoForSentence = *v
|
|
}
|
|
if v := profile.KeyEcho.EchoVoice; v != nil {
|
|
settings.EchoVoice = cloneVoice(*v)
|
|
}
|
|
if v := profile.KeyEcho.EchoSpeechServer; v != nil {
|
|
settings.EchoSpeechServer = *v
|
|
}
|
|
}
|
|
|
|
func apply_profile_reading(settings *Settings, profile writableProfile) {
|
|
if value := profile.Presentation.Pronunciations; value != nil {
|
|
settings.Pronunciations = append([]PronunciationEntry(nil), (*value)...)
|
|
}
|
|
if value := profile.Presentation.TextAttributes.Choices; value != nil {
|
|
settings.TextAttributes.Choices = append([]TextAttributeChoice(nil), (*value)...)
|
|
}
|
|
if value := profile.Presentation.TextAttributes.Indicator; value != nil {
|
|
settings.TextAttributes.Indicator = *value
|
|
}
|
|
if value := profile.Presentation.SpeakDescription; value != nil {
|
|
settings.SpeakDescription = *value
|
|
}
|
|
if value := profile.Presentation.SpeechVerbosityLevel; value != nil {
|
|
settings.SpeechVerbosityLevel = *value
|
|
}
|
|
if value := profile.Presentation.SayAllStyle; value != nil {
|
|
settings.SayAllStyle = *value
|
|
}
|
|
if value := profile.Presentation.Reading.AutomaticallyReadClipboardChanges; value != nil {
|
|
settings.Reading.AutomaticallyReadClipboardChanges = *value
|
|
}
|
|
if value := profile.Presentation.Reading.AutomaticallyReadTitleChanges; value != nil {
|
|
settings.Reading.AutomaticallyReadTitleChanges = *value
|
|
}
|
|
if value := profile.Presentation.Reading.OnlySpeakDisplayedText; value != nil {
|
|
settings.Reading.OnlySpeakDisplayedText = *value
|
|
}
|
|
if value := profile.Presentation.Reading.EnablePauseBreaks; value != nil {
|
|
settings.Reading.EnablePauseBreaks = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SpeakNumbersAsDigits; value != nil {
|
|
settings.Reading.SpeakNumbersAsDigits = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SpeakMultiCaseStringsAsWords; value != nil {
|
|
settings.Reading.SpeakMultiCaseStringsAsWords = *value
|
|
}
|
|
if value := profile.Presentation.Reading.EnableIndentation; value != nil {
|
|
settings.Reading.EnableIndentation = *value
|
|
}
|
|
if value := profile.Presentation.Reading.IndentationPresentationMode; value != nil {
|
|
settings.Reading.IndentationPresentationMode = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SpeakBlankLines; value != nil {
|
|
settings.Reading.SpeakBlankLines = *value
|
|
}
|
|
if value := profile.Presentation.Reading.EnableMnemonicSpeaking; value != nil {
|
|
settings.Reading.EnableMnemonicSpeaking = *value
|
|
}
|
|
if value := profile.Presentation.Reading.EnablePositionSpeaking; value != nil {
|
|
settings.Reading.EnablePositionSpeaking = *value
|
|
}
|
|
if value := profile.Presentation.Reading.EnableTutorialMessages; value != nil {
|
|
settings.Reading.EnableTutorialMessages = *value
|
|
}
|
|
if value := profile.Presentation.Reading.MessagesAreDetailed; value != nil {
|
|
settings.Reading.MessagesAreDetailed = *value
|
|
}
|
|
if value := profile.Presentation.Reading.UseColorNames; value != nil {
|
|
settings.Reading.UseColorNames = *value
|
|
}
|
|
if value := profile.Presentation.Reading.PresentTooltips; value != nil {
|
|
settings.Reading.PresentTooltips = *value
|
|
}
|
|
if value := profile.Presentation.Reading.EnableMouseReview; value != nil {
|
|
settings.Reading.EnableMouseReview = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SpeakMisspelledIndicator; value != nil {
|
|
settings.Reading.SpeakMisspelledIndicator = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SpeakContextBlockquote; value != nil {
|
|
settings.Reading.SpeakContextBlockquote = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SpeakContextList; value != nil {
|
|
settings.Reading.SpeakContextList = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SpeakContextTable; value != nil {
|
|
settings.Reading.SpeakContextTable = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SpeakContextPanel; value != nil {
|
|
settings.Reading.SpeakContextPanel = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SpeakContextLandmark; value != nil {
|
|
settings.Reading.SpeakContextLandmark = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SpeakContextNonLandmarkForm; value != nil {
|
|
settings.Reading.SpeakContextNonLandmarkForm = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SayAllContextBlockquote; value != nil {
|
|
settings.Reading.SayAllContextBlockquote = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SayAllContextList; value != nil {
|
|
settings.Reading.SayAllContextList = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SayAllContextTable; value != nil {
|
|
settings.Reading.SayAllContextTable = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SayAllContextPanel; value != nil {
|
|
settings.Reading.SayAllContextPanel = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SayAllContextLandmark; value != nil {
|
|
settings.Reading.SayAllContextLandmark = *value
|
|
}
|
|
if value := profile.Presentation.Reading.SayAllContextNonLandmarkForm; value != nil {
|
|
settings.Reading.SayAllContextNonLandmarkForm = *value
|
|
}
|
|
if value := profile.Presentation.Reading.ReadFullRowInGUITable; value != nil {
|
|
settings.Reading.ReadFullRowInGUITable = *value
|
|
}
|
|
if value := profile.Presentation.Reading.ReadFullRowInDocumentTable; value != nil {
|
|
settings.Reading.ReadFullRowInDocumentTable = *value
|
|
}
|
|
if value := profile.Presentation.Reading.ReadFullRowInSpreadSheet; value != nil {
|
|
settings.Reading.ReadFullRowInSpreadSheet = *value
|
|
}
|
|
}
|
|
|
|
func apply_profile_output(settings *Settings, profile writableProfile) {
|
|
if value := profile.Speech.Enabled; value != nil {
|
|
settings.EnableSpeech = *value
|
|
}
|
|
if value := profile.Speech.HistoryLimit; value != nil {
|
|
settings.SpeechHistoryLimit = *value
|
|
}
|
|
if value := profile.Braille.Enabled; value != nil {
|
|
settings.EnableBraille = *value
|
|
}
|
|
if value := profile.Braille.Contracted; value != nil {
|
|
settings.EnableContractedBraille = *value
|
|
}
|
|
if value := profile.Braille.ContractionTable; value != nil {
|
|
settings.BrailleContractionTable = *value
|
|
}
|
|
if value := profile.Braille.AbbreviateRoles; value != nil {
|
|
settings.Braille.AbbreviateRoles = *value
|
|
}
|
|
if value := profile.Braille.DisableEOL; value != nil {
|
|
settings.Braille.DisableEOL = *value
|
|
}
|
|
if value := profile.Braille.WordWrap; value != nil {
|
|
settings.Braille.WordWrap = *value
|
|
}
|
|
if value := profile.Braille.Verbosity; value != nil {
|
|
settings.Braille.Verbosity = *value
|
|
}
|
|
if value := profile.Braille.SelectionIndicator; value != nil {
|
|
settings.Braille.SelectionIndicator = *value
|
|
}
|
|
if value := profile.Braille.LinkIndicator; value != nil {
|
|
settings.Braille.LinkIndicator = *value
|
|
}
|
|
if value := profile.Braille.FlashMessages; value != nil {
|
|
settings.Braille.FlashMessages = *value
|
|
}
|
|
if value := profile.Braille.FlashTime; value != nil {
|
|
settings.Braille.FlashTime = *value
|
|
}
|
|
if value := profile.Braille.FlashPersistent; value != nil {
|
|
settings.Braille.FlashPersistent = *value
|
|
}
|
|
if value := profile.Braille.FlashDetailed; value != nil {
|
|
settings.Braille.FlashDetailed = *value
|
|
}
|
|
}
|
|
|
|
func apply_profile_speech(settings *Settings, profile writableProfile) {
|
|
if value := profile.Speech.HardwareDevice; value != nil {
|
|
settings.HardwareSpeechDevice = *value
|
|
}
|
|
if value := profile.Speech.HardwareBaudRate; value != nil {
|
|
settings.HardwareSpeechBaudRate = *value
|
|
}
|
|
if value := profile.Speech.ServerFactory; value != nil {
|
|
settings.SpeechServerFactory = *value
|
|
}
|
|
if value := profile.Speech.Punctuation; value != nil {
|
|
settings.VerbalizePunctuationStyle = *value
|
|
}
|
|
if value := profile.Speech.Capitalization; value != nil {
|
|
settings.CapitalizationStyle = *value
|
|
}
|
|
if value := profile.Speech.OutputModule; value != nil {
|
|
settings.SpeechOutputModule = *value
|
|
}
|
|
if value := profile.Speech.DefaultVoice; value != nil {
|
|
settings.DefaultVoice = cloneVoice(*value)
|
|
}
|
|
if value := profile.Speech.UppercaseVoice; value != nil {
|
|
settings.UppercaseVoice = cloneVoice(*value)
|
|
}
|
|
if value := profile.Speech.HyperlinkVoice; value != nil {
|
|
settings.HyperlinkVoice = cloneVoice(*value)
|
|
}
|
|
if value := profile.Speech.SystemVoice; value != nil {
|
|
settings.SystemVoice = cloneVoice(*value)
|
|
}
|
|
}
|
|
|
|
func apply_profile_sound(settings *Settings, profile writableProfile) {
|
|
if value := profile.Sound.Enabled; value != nil {
|
|
settings.EnableSound = *value
|
|
}
|
|
if value := profile.Sound.Volume; value != nil {
|
|
settings.SoundVolume = *value
|
|
}
|
|
if value := profile.Sound.Sink; value != nil {
|
|
settings.SoundSink = *value
|
|
}
|
|
if value := profile.Sound.Theme; value != nil {
|
|
settings.SoundTheme = *value
|
|
}
|
|
if value := profile.Sound.PlayForRole; value != nil {
|
|
settings.PlaySoundForRole = *value
|
|
}
|
|
if value := profile.Sound.PlayForState; value != nil {
|
|
settings.PlaySoundForState = *value
|
|
}
|
|
if value := profile.Sound.PlayForPosition; value != nil {
|
|
settings.PlaySoundForPositionInSet = *value
|
|
}
|
|
if value := profile.Sound.Spatialize; value != nil {
|
|
settings.SpatializeObjectSounds = *value
|
|
}
|
|
if value := profile.Sound.RolePresentationStrategy; value != nil {
|
|
settings.RoleSoundPresentation = *value
|
|
}
|
|
}
|
|
|
|
func apply_profile_keyboard(settings *Settings, profile writableProfile) {
|
|
if value := profile.Keyboard.Bindings; value != nil {
|
|
settings.KeyBindings = input.CloneBindingOverrides(*value)
|
|
}
|
|
if value := profile.Keyboard.Layout; value != nil {
|
|
settings.KeyboardLayout = *value
|
|
}
|
|
if value := profile.Keyboard.ScreenReaderKeys; value != nil {
|
|
settings.CthulhuModifierKeys = append([]string(nil), (*value)...)
|
|
}
|
|
}
|
|
|
|
func apply_profile_echo_keys(settings *Settings, profile writableProfile) {
|
|
if value := profile.KeyEcho.Enabled; value != nil {
|
|
settings.EnableKeyEcho = *value
|
|
}
|
|
if value := profile.KeyEcho.ByCharacter; value != nil {
|
|
settings.EnableEchoByCharacter = *value
|
|
}
|
|
if value := profile.KeyEcho.ByWord; value != nil {
|
|
settings.EnableEchoByWord = *value
|
|
}
|
|
if value := profile.KeyEcho.BySentence; value != nil {
|
|
settings.EnableEchoBySentence = *value
|
|
}
|
|
if value := profile.KeyEcho.Alphabetic; value != nil {
|
|
settings.EnableAlphabeticKeys = *value
|
|
}
|
|
if value := profile.KeyEcho.Numeric; value != nil {
|
|
settings.EnableNumericKeys = *value
|
|
}
|
|
if value := profile.KeyEcho.Punctuation; value != nil {
|
|
settings.EnablePunctuationKeys = *value
|
|
}
|
|
if value := profile.KeyEcho.Space; value != nil {
|
|
settings.EnableSpace = *value
|
|
}
|
|
if value := profile.KeyEcho.Modifiers; value != nil {
|
|
settings.EnableModifierKeys = *value
|
|
}
|
|
if value := profile.KeyEcho.FunctionKeys; value != nil {
|
|
settings.EnableFunctionKeys = *value
|
|
}
|
|
if value := profile.KeyEcho.ActionKeys; value != nil {
|
|
settings.EnableActionKeys = *value
|
|
}
|
|
if value := profile.KeyEcho.NavigationKeys; value != nil {
|
|
settings.EnableNavigationKeys = *value
|
|
}
|
|
if value := profile.KeyEcho.Diacritical; value != nil {
|
|
settings.EnableDiacriticalKeys = *value
|
|
}
|
|
}
|
|
|
|
func boolPointer(value bool) *bool { return &value }
|
|
|
|
func intPointer(value int) *int { return &value }
|
|
|
|
func floatPointer(value float64) *float64 { return &value }
|
|
|
|
func stringPointer(value string) *string { return &value }
|
|
|
|
func stringSlicePointer(value []string) *[]string {
|
|
copy := append([]string(nil), value...)
|
|
return ©
|
|
}
|
|
|
|
func pronunciationSlicePointer(value []PronunciationEntry) *[]PronunciationEntry {
|
|
copy := append([]PronunciationEntry{}, value...)
|
|
return ©
|
|
}
|
|
|
|
func textAttributeSlicePointer(value []TextAttributeChoice) *[]TextAttributeChoice {
|
|
copy := append([]TextAttributeChoice{}, value...)
|
|
return ©
|
|
}
|
|
|
|
func voicePointer(value Voice) *Voice { copy := cloneVoice(value); return © }
|
|
|
|
func bindingSlicePointer(value []input.BindingOverride) *[]input.BindingOverride {
|
|
copy := input.CloneBindingOverrides(value)
|
|
if copy == nil {
|
|
copy = []input.BindingOverride{}
|
|
}
|
|
return ©
|
|
}
|