blob: ca0f202a5982032079bc3bdab32075d1a5feef15 [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 <stdio.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include "program.h"
#include "cmdline.h"
#include "parameters.h"
#include "log.h"
#include "parse.h"
#include "file.h"
#include "cmd_queue.h"
#include "brl.h"
#include "brl_input.h"
#include "brl_utils.h"
#include "ttb.h"
#include "ktb.h"
#include "message.h"
#include "utf8.h"
#include "async_wait.h"
#include "learn.h"
BrailleDisplay brl;
static char *opt_brailleDevice;
char *opt_driversDirectory;
static char *opt_tablesDirectory;
static char *opt_writableDirectory;
BEGIN_OPTION_TABLE(programOptions)
{ .word = "device",
.letter = 'd',
.argument = "device",
.setting.string = &opt_brailleDevice,
.internal.setting = BRAILLE_DEVICE,
.description = "Path to device for accessing braille display."
},
{ .word = "tables-directory",
.letter = 'T',
.argument = strtext("directory"),
.setting.string = &opt_tablesDirectory,
.internal.setting = TABLES_DIRECTORY,
.internal.adjust = fixInstallPath,
.description = strtext("Path to directory containing tables.")
},
{ .word = "drivers-directory",
.letter = 'D',
.argument = "directory",
.setting.string = &opt_driversDirectory,
.internal.setting = DRIVERS_DIRECTORY,
.internal.adjust = fixInstallPath,
.description = "Path to directory for loading drivers."
},
{ .word = "writable-directory",
.letter = 'W',
.argument = strtext("directory"),
.setting.string = &opt_writableDirectory,
.internal.setting = WRITABLE_DIRECTORY,
.internal.adjust = fixInstallPath,
.description = strtext("Path to directory which can be written to.")
},
END_OPTION_TABLE(programOptions)
int
main (int argc, char *argv[]) {
ProgramExitStatus exitStatus;
const char *driver = NULL;
void *object;
{
const CommandLineDescriptor descriptor = {
.options = &programOptions,
.applicationName = "brltest",
.usage = {
.purpose = strtext("Test a braille driver."),
.parameters = "[driver [parameter=value ...]]",
}
};
PROCESS_OPTIONS(descriptor, argc, argv);
}
setWritableDirectory(opt_writableDirectory);
if (argc) {
driver = *argv++, --argc;
}
if (!*opt_brailleDevice) {
changeStringSetting(&opt_brailleDevice, BRAILLE_DEVICE);
}
if ((braille = loadBrailleDriver(driver, &object, opt_driversDirectory))) {
const char *const *parameterNames = braille->parameters;
char **parameterSettings;
if (!parameterNames) {
static const char *const noNames[] = {NULL};
parameterNames = noNames;
}
{
const char *const *name = parameterNames;
unsigned int count;
char **setting;
while (*name) name += 1;
count = name - parameterNames;
if (!(parameterSettings = malloc((count + 1) * sizeof(*parameterSettings)))) {
logMallocError();
return PROG_EXIT_FATAL;
}
setting = parameterSettings;
while (count--) *setting++ = "";
*setting = NULL;
}
while (argc) {
char *assignment = *argv++;
int ok = 0;
char *delimiter = strchr(assignment, '=');
if (!delimiter) {
logMessage(LOG_ERR, "missing braille driver parameter value: %s", assignment);
} else if (delimiter == assignment) {
logMessage(LOG_ERR, "missing braille driver parameter name: %s", assignment);
} else {
size_t nameLength = delimiter - assignment;
const char *const *name = parameterNames;
while (*name) {
if (strncasecmp(assignment, *name, nameLength) == 0) {
parameterSettings[name - parameterNames] = delimiter + 1;
ok = 1;
break;
}
name += 1;
}
if (!ok) logMessage(LOG_ERR, "invalid braille driver parameter: %s", assignment);
}
if (!ok) return PROG_EXIT_SYNTAX;
argc -= 1;
}
constructBrailleDisplay(&brl);
identifyBrailleDriver(braille, 0); /* start-up messages */
if (braille->construct(&brl, parameterSettings, opt_brailleDevice)) {
if (ensureBrailleBuffer(&brl, LOG_INFO)) {
if (brl.keyNames) {
char *path = makeInputTablePath(opt_tablesDirectory, braille->definition.code, brl.keyBindings);
if (path) {
brl.keyTable = compileKeyTable(path, brl.keyNames);
free(path);
}
}
beginCommandQueue();
startBrailleInput();
learnMode(10000);
stopBrailleInput();
if (brl.keyTable) {
KeyTable *table = brl.keyTable;
brl.keyTable = NULL;
destroyKeyTable(table);
}
braille->destruct(&brl); /* finish with the display */
exitStatus = PROG_EXIT_SUCCESS;
} else {
logMessage(LOG_ERR, "can't allocate braille buffer");
exitStatus = PROG_EXIT_FATAL;
}
} else {
logMessage(LOG_ERR, "can't initialize braille driver");
exitStatus = PROG_EXIT_FATAL;
}
} else {
logMessage(LOG_ERR, "can't load braille driver");
exitStatus = PROG_EXIT_FATAL;
}
return exitStatus;
}
typedef struct {
unsigned endWait:1;
} MessageData;
static int
handleMessageCommands (int command, void *data) {
MessageData *mgd = data;
mgd->endWait = 1;
return 1;
}
ASYNC_CONDITION_TESTER(testEndMessageWait) {
const MessageData *mgd = data;
return mgd->endWait;
}
int
message (const char *mode, const char *text, MessageOptions options) {
MessageData mgd;
size_t size = brl.textColumns * brl.textRows;
wchar_t buffer[size];
size_t length = countUtf8Characters(text);
wchar_t characters[length + 1];
const wchar_t *character = characters;
clearStatusCells(&brl);
makeWcharsFromUtf8(text, characters, ARRAY_COUNT(characters));
pushCommandEnvironment("message", NULL, NULL);
pushCommandHandler("message", KTB_CTX_WAITING,
handleMessageCommands, NULL, &mgd);
while (length) {
size_t count = (length <= size)? length: (size - 1);
wmemcpy(buffer, character, count);
character += count;
length -= count;
if (length) {
buffer[(count = size) - 1] = WC_C('-');
}
wmemset(&buffer[count], WC_C(' '), (size - count));
{
unsigned int i;
for (i=0; i<size; i+=1) {
brl.buffer[i] = convertCharacterToDots(textTable, buffer[i]);
}
}
if (!braille->writeWindow(&brl, buffer)) return 0;
if (length) {
int delay = MESSAGE_HOLD_TIMEOUT - brl.writeDelay;
mgd.endWait = 0;
drainBrailleOutput(&brl, 0);
asyncAwaitCondition(delay, testEndMessageWait, &mgd);
}
}
popCommandEnvironment();
return 1;
}
#include "scr.h"
KeyTableCommandContext
getScreenCommandContext (void) {
return KTB_CTX_DEFAULT;
}
#include "alert.h"
void
alert (AlertIdentifier identifier) {
}
void
speakAlertText (const wchar_t *text) {
}
#include "api_control.h"
const ApiMethods api;