blob: 1526ea01803fb887aa34c4e0364287be7a8e036b [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 <ctype.h>
#include "program.h"
#include "cmdline.h"
#include "log.h"
#include "parse.h"
#include "scr.h"
static char *opt_boxLeft;
static char *opt_boxWidth;
static char *opt_boxTop;
static char *opt_boxHeight;
static char *opt_screenDriver;
static char *opt_driversDirectory;
BEGIN_OPTION_TABLE(programOptions)
{ .word = "screen-driver",
.letter = 'x',
.argument = "driver",
.setting.string = &opt_screenDriver,
.internal.setting = DEFAULT_SCREEN_DRIVER,
.description = "Screen driver: one of {" SCREEN_DRIVER_CODES "}"
},
{ .word = "left",
.letter = 'l',
.argument = "column",
.setting.string = &opt_boxLeft,
.description = "Left edge of region (from 0)."
},
{ .word = "columns",
.letter = 'c',
.argument = "count",
.setting.string = &opt_boxWidth,
.description = "Width of region."
},
{ .word = "top",
.letter = 't',
.argument = "row",
.setting.string = &opt_boxTop,
.description = "Top edge of region (from 0)."
},
{ .word = "rows",
.letter = 'r',
.argument = "count",
.setting.string = &opt_boxHeight,
.description = "Height of region."
},
{ .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."
},
END_OPTION_TABLE(programOptions)
static int
setRegion (
int *offsetValue, const char *offsetOption, const char *offsetName,
int *sizeValue, const char *sizeOption, int sizeLimit, const char *sizeName
) {
if (*offsetOption) {
{
const int minimum = 0;
const int maximum = sizeLimit - 1;
if (!validateInteger(offsetValue, offsetOption, &minimum, &maximum)) {
logMessage(LOG_ERR, "invalid %s: %s", offsetName, offsetOption);
return 0;
}
}
if (*sizeOption) {
const int minimum = 1;
const int maximum = sizeLimit - *offsetValue;
if (!validateInteger(sizeValue, sizeOption, &minimum, &maximum)) {
logMessage(LOG_ERR, "invalid %s: %s", sizeName, sizeOption);
return 0;
}
return 1;
}
} else if (*sizeOption) {
const int minimum = 1;
const int maximum = sizeLimit;
if (!validateInteger(sizeValue, sizeOption, &minimum, &maximum)) {
logMessage(LOG_ERR, "invalid %s: %s", sizeName, sizeOption);
return 0;
}
*offsetValue = (sizeLimit - *sizeValue) / 2;
return 1;
} else {
*offsetValue = sizeLimit / 4;
}
if ((*sizeValue = sizeLimit - (*offsetValue * 2)) < 1) *sizeValue = 1;
return 1;
}
int
main (int argc, char *argv[]) {
ProgramExitStatus exitStatus;
void *driverObject;
{
const CommandLineDescriptor descriptor = {
.options = &programOptions,
.applicationName = "scrtest",
.usage = {
.purpose = strtext("Test a screen driver."),
.parameters = "[parameter=value ...]",
}
};
PROCESS_OPTIONS(descriptor, argc, argv);
}
if ((screen = loadScreenDriver(opt_screenDriver, &driverObject, opt_driversDirectory))) {
const char *const *parameterNames = getScreenParameters(screen);
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;
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 screen parameter value: %s", assignment);
} else if (delimiter == assignment) {
logMessage(LOG_ERR, "missing screen 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;
}
if (!ok) logMessage(LOG_ERR, "invalid screen parameter: %s", assignment);
}
if (!ok) return PROG_EXIT_SYNTAX;
--argc;
}
if (constructScreenDriver(parameterSettings)) {
ScreenDescription description;
int left, top, width, height;
describeScreen(&description);
printf("Screen: %dx%d\n", description.cols, description.rows);
printf("Cursor: [%d,%d]\n", description.posx, description.posy);
if (setRegion(&left, opt_boxLeft, "starting column",
&width, opt_boxWidth, description.cols, "region width")) {
if (setRegion(&top, opt_boxTop, "starting row",
&height, opt_boxHeight, description.rows, "region height")) {
printf("Region: %dx%d@[%d,%d]\n", width, height, left, top);
{
ScreenCharacter buffer[width * height];
if (readScreen(left, top, width, height, buffer)) {
int line;
for (line=0; line<height; line++) {
int column;
for (column=0; column<width; column++) {
wchar_t character = buffer[line * width + column].text;
if (!iswLatin1(character)) {
putchar('?');
} else if (!isprint(character)) {
putchar('*');
} else {
putchar(character);
}
}
putchar('\n');
}
exitStatus = PROG_EXIT_SUCCESS;
} else {
logMessage(LOG_ERR, "Can't read screen.");
exitStatus = PROG_EXIT_FATAL;
}
}
} else {
exitStatus = PROG_EXIT_SYNTAX;
}
} else {
exitStatus = PROG_EXIT_SYNTAX;
}
} else {
logMessage(LOG_ERR, "can't open screen.");
exitStatus = PROG_EXIT_FATAL;
}
destructScreenDriver();
} else {
logMessage(LOG_ERR, "can't load screen driver.");
exitStatus = PROG_EXIT_FATAL;
}
return exitStatus;
}
#include "update.h"
void
scheduleUpdateIn (const char *reason, int delay) {
}