blob: 58c51a89d1dfae0c8c3a8a362c50936367ebf287 [file] [log] [blame] [edit]
/*
* BRLTTY - A background process providing access to the console screen (when in
* text mode) for a blind person using a refreshable braille display.
*
* Copyright (C) 1995-2023 by The BRLTTY Developers.
*
* BRLTTY comes with ABSOLUTELY NO WARRANTY.
*
* This is free software, placed under the terms of the
* GNU Lesser General Public License, as published by the Free Software
* Foundation; either version 2.1 of the License, or (at your option) any
* later version. Please see the file LICENSE-LGPL for details.
*
* Web Page: http://brltty.app/
*
* This software is maintained by Dave Mielke <dave@mielke.cc>.
*/
#include "prologue.h"
#include "parameters.h"
#include "api_control.h"
#include "cmd_queue.h"
#include "cmd_toggle.h"
#include "brl_cmds.h"
#include "prefs.h"
#include "scr.h"
#include "scr_special.h"
#include "scr_menu.h"
#include "alert.h"
#include "tune.h"
#include "core.h"
typedef enum {
TOGGLE_ERROR,
TOGGLE_SAME,
TOGGLE_OFF,
TOGGLE_ON
} ToggleResult;
static ToggleResult
toggleBit (
int *bits, int bit, int command,
AlertIdentifier offAlert,
AlertIdentifier onAlert
) {
int oldBits = *bits;
switch (command & BRL_FLG_TOGGLE_MASK) {
case 0:
*bits ^= bit;
break;
case BRL_FLG_TOGGLE_ON:
*bits |= bit;
break;
case BRL_FLG_TOGGLE_OFF:
*bits &= ~bit;
break;
default:
alert(ALERT_COMMAND_REJECTED);
return TOGGLE_ERROR;
}
{
int isOn = (*bits & bit) != 0;
AlertIdentifier identifier = isOn? onAlert: offAlert;
alert(identifier);
if (*bits != oldBits) return isOn? TOGGLE_ON: TOGGLE_OFF;
tuneWait(TUNE_TOGGLE_REPEAT_DELAY);
alert(identifier);
return TOGGLE_SAME;
}
}
static ToggleResult
toggleSetting (
unsigned char *setting, int command,
AlertIdentifier offAlert,
AlertIdentifier onAlert
) {
const int bit = 1;
int bits = *setting? bit: 0;
ToggleResult result = toggleBit(&bits, bit, command, offAlert, onAlert);
*setting = (bits & bit)? bit: 0;
return result;
}
static ToggleResult
togglePreferenceSetting (unsigned char *setting, int command) {
ToggleResult result = toggleSetting(setting, command, ALERT_TOGGLE_OFF, ALERT_TOGGLE_ON);
if (result > TOGGLE_SAME) menuScreenUpdated();
return result;
}
static ToggleResult
toggleModeSetting (unsigned char *setting, int command) {
return toggleSetting(setting, command, ALERT_NONE, ALERT_NONE);
}
static ToggleResult
toggleFunctionalSetting (
int command,
int (*get) (void),
void (*set) (int value)
) {
const int bit = 1;
int bits = get()? bit: 0;
ToggleResult result = toggleBit(
&bits, bit, command,
ALERT_TOGGLE_OFF, ALERT_TOGGLE_ON
);
set(!!(bits & bit));
return result;
}
static int
handleToggleCommands (int command, void *data) {
switch (command & BRL_MSK_CMD) {
case BRL_CMD_SKPIDLNS:
togglePreferenceSetting(&prefs.skipIdenticalLines, command);
api.updateParameter(BRLAPI_PARAM_SKIP_IDENTICAL_LINES, 0);
break;
case BRL_CMD_SKPBLNKWINS:
togglePreferenceSetting(&prefs.skipBlankBrailleWindows, command);
break;
case BRL_CMD_SLIDEWIN:
togglePreferenceSetting(&prefs.slidingBrailleWindow, command);
break;
case BRL_CMD_SIXDOTS:
togglePreferenceSetting(&prefs.brailleVariant, command);
onBrailleVariantUpdated();
break;
case BRL_CMD_CONTRACTED:
toggleFunctionalSetting(command, isContractedBraille, setContractedBraille);
break;
case BRL_CMD_COMPBRL6:
toggleFunctionalSetting(command, isSixDotComputerBraille, setSixDotComputerBraille);
break;
case BRL_CMD_CSRTRK:
toggleSetting(&ses->trackScreenCursor, command, ALERT_CURSOR_UNLINKED, ALERT_CURSOR_LINKED);
if (ses->trackScreenCursor) {
#ifdef ENABLE_SPEECH_SUPPORT
if (spk.track.isActive && (scr.number == spk.track.screenNumber)) {
spk.track.speechLocation = SPK_LOC_NONE;
} else
#endif /* ENABLE_SPEECH_SUPPORT */
{
trackScreenCursor(1);
}
}
break;
case BRL_CMD_CSRSIZE:
togglePreferenceSetting(&prefs.screenCursorStyle, command);
break;
case BRL_CMD_CSRVIS:
togglePreferenceSetting(&prefs.showScreenCursor, command);
break;
case BRL_CMD_CSRHIDE:
toggleModeSetting(&ses->hideScreenCursor, command);
break;
case BRL_CMD_CSRBLINK:
togglePreferenceSetting(&prefs.blinkingScreenCursor, command);
break;
case BRL_CMD_ATTRVIS:
togglePreferenceSetting(&prefs.showAttributes, command);
break;
case BRL_CMD_ATTRBLINK:
togglePreferenceSetting(&prefs.blinkingAttributes, command);
break;
case BRL_CMD_CAPBLINK:
togglePreferenceSetting(&prefs.blinkingCapitals, command);
break;
case BRL_CMD_AUTOREPEAT:
togglePreferenceSetting(&prefs.autorepeatEnabled, command);
break;
case BRL_CMD_BRLKBD:
togglePreferenceSetting(&prefs.brailleKeyboardEnabled, command);
break;
case BRL_CMD_BRLUCDOTS:
togglePreferenceSetting(&prefs.brailleTypingMode, command);
break;
case BRL_CMD_TOUCH_NAV:
togglePreferenceSetting(&prefs.touchNavigation, command);
break;
case BRL_CMD_TUNES:
togglePreferenceSetting(&prefs.alertTunes, command); /* toggle sound on/off */
api.updateParameter(BRLAPI_PARAM_AUDIBLE_ALERTS, 0);
break;
case BRL_CMD_AUTOSPEAK:
togglePreferenceSetting(&prefs.autospeak, command);
break;
case BRL_CMD_ASPK_SEL_LINE:
togglePreferenceSetting(&prefs.autospeakSelectedLine, command);
break;
case BRL_CMD_ASPK_SEL_CHAR:
togglePreferenceSetting(&prefs.autospeakSelectedCharacter, command);
break;
case BRL_CMD_ASPK_INS_CHARS:
togglePreferenceSetting(&prefs.autospeakInsertedCharacters, command);
break;
case BRL_CMD_ASPK_DEL_CHARS:
togglePreferenceSetting(&prefs.autospeakDeletedCharacters, command);
break;
case BRL_CMD_ASPK_REP_CHARS:
togglePreferenceSetting(&prefs.autospeakReplacedCharacters, command);
break;
case BRL_CMD_ASPK_CMP_WORDS:
togglePreferenceSetting(&prefs.autospeakCompletedWords, command);
break;
case BRL_CMD_ASPK_INDENT:
togglePreferenceSetting(&prefs.autospeakLineIndent, command);
break;
case BRL_CMD_SHOW_CURR_LOCN:
togglePreferenceSetting(&prefs.showSpeechCursor, command);
break;
case BRL_CMD_INFO:
if (haveStatusCells() || !(textMaximized || statusCount)) {
toggleModeSetting(&infoMode, command);
} else {
ToggleResult result = toggleModeSetting(&textMaximized, command);
if (result > TOGGLE_SAME) reconfigureBrailleWindow();
}
break;
case BRL_CMD_DISPMD:
toggleModeSetting(&ses->displayMode, command);
break;
case BRL_CMD_FREEZE: {
unsigned char setting;
if (isMainScreen()) {
setting = 0;
} else if (isSpecialScreen(SCR_FROZEN)) {
setting = 1;
} else {
alert(ALERT_COMMAND_REJECTED);
break;
}
switch (toggleSetting(&setting, command, ALERT_SCREEN_UNFROZEN, ALERT_SCREEN_FROZEN)) {
case TOGGLE_OFF:
deactivateSpecialScreen(SCR_FROZEN);
break;
case TOGGLE_ON:
if (!activateSpecialScreen(SCR_FROZEN)) alert(ALERT_COMMAND_REJECTED);
break;
default:
break;
}
break;
}
default:
return 0;
}
return 1;
}
int
addToggleCommands (void) {
return pushCommandHandler("toggle", KTB_CTX_DEFAULT,
handleToggleCommands, NULL, NULL);
}