blob: 324a4b2635caf639ccc34ed80c1c44f969f23068 [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>.
*/
#define BRLAPI_NO_SINGLE_SESSION
#define BRLAPI_NO_DEPRECATED
#include <windows.h>
#include <stdbool.h>
#include <stdio.h>
#include "brlapi.h"
#include "webrloem.h"
#define C(cmd) (BRLAPI_KEY_CMD_##cmd & BRLAPI_KEY_CMD_ARG_MASK)
static const unsigned command_button[] = {
[ C(LNUP) ] = 1 /* go up one line */,
[ C(LNDN) ] = 2 /* go down one line */,
[ C(WINUP) ] = 3 /* go up several lines */,
[ C(WINDN) ] = 4 /* go down several lines */,
[ C(PRDIFLN) ] = 5 /* go up to nearest line with different content */,
[ C(NXDIFLN) ] = 6 /* go down to nearest line with different content */,
[ C(ATTRUP) ] = 7 /* go up to nearest line with different highlighting */,
[ C(ATTRDN) ] = 8 /* go down to nearest line with different highlighting */,
[ C(TOP) ] = 9 /* go to top line */,
[ C(BOT) ] = 10 /* go to bottom line */,
[ C(TOP_LEFT) ] = 11 /* go to beginning of top line */,
[ C(BOT_LEFT) ] = 12 /* go to beginning of bottom line */,
[ C(PRPGRPH) ] = 13 /* go up to last line of previous paragraph */,
[ C(NXPGRPH) ] = 14 /* go down to first line of next paragraph */,
[ C(PRPROMPT) ] = 15 /* go up to previous command prompt */,
[ C(NXPROMPT) ] = 16 /* go down to next command prompt */,
[ C(CHRLT) ] = 17 /* go left one character */,
[ C(CHRRT) ] = 18 /* go right one character */,
[ C(HWINLT) ] = 19 /* go left half a window */,
[ C(HWINRT) ] = 20 /* go right half a window */,
[ C(FWINLT) ] = 21 /* go left one window */,
[ C(FWINRT) ] = 22 /* go right one window */,
[ C(FWINLTSKIP) ] = 23 /* go left to nearest non-blank window */,
[ C(FWINRTSKIP) ] = 24 /* go right to nearest non-blank window */,
[ C(LNBEG) ] = 25 /* go to beginning of line */,
[ C(LNEND) ] = 26 /* go to end of line */,
[ C(HOME) ] = 27 /* go to cursor */,
[ C(BACK) ] = 28 /* go back (undo unexpected cursor tracking motion) */,
[ C(FREEZE) ] = 29 /* toggle screen mode frozen/live */,
[ C(DISPMD) ] = 30 /* toggle display mode attributes/text */,
[ C(SIXDOTS) ] = 31 /* toggle text style 6-dot/8-dot */,
[ C(SLIDEWIN) ] = 32 /* toggle sliding window on/off */,
[ C(SKPIDLNS) ] = 33 /* toggle skipping of lines with identical content on/off */,
[ C(SKPBLNKWINS) ] = 34 /* toggle skipping of blank windows on/off */,
[ C(CSRVIS) ] = 35 /* toggle cursor visibility on/off */,
[ C(CSRTRK) ] = 36 /* toggle cursor tracking on/off */,
[ C(CSRSIZE) ] = 37 /* toggle cursor style block/underline */,
[ C(CSRBLINK) ] = 38 /* toggle cursor blinking on/off */,
[ C(ATTRVIS) ] = 39 /* toggle attribute underlining on/off */,
[ C(ATTRBLINK) ] = 40 /* toggle attribute blinking on/off */,
[ C(CAPBLINK) ] = 41 /* toggle capital letter blinking on/off */,
[ C(TUNES) ] = 42 /* toggle alert tunes on/off */,
[ C(AUTOREPEAT) ] = 43 /* toggle autorepeat on/off */,
[ C(AUTOSPEAK) ] = 44 /* toggle autospeak on/off */,
[ C(HELP) ] = 45 /* enter/leave help display */,
[ C(INFO) ] = 46 /* enter/leave status display */,
[ C(LEARN) ] = 47 /* enter/leave command learn mode */,
[ C(PREFMENU) ] = 48 /* enter/leave preferences menu */,
[ C(PREFSAVE) ] = 49 /* save current preferences */,
[ C(PREFLOAD) ] = 50 /* restore saved preferences */,
[ C(MUTE) ] = 51 /* stop speaking immediately */,
[ C(SPKHOME) ] = 52 /* go to current (most recent) speech position */,
[ C(SAY_LINE) ] = 53 /* speak current line */,
[ C(SAY_ABOVE) ] = 54 /* speak from top of screen through current line */,
[ C(SAY_BELOW) ] = 55 /* speak from current line through bottom of screen */,
[ C(SAY_SLOWER) ] = 56 /* decrease speech rate */,
[ C(SAY_FASTER) ] = 57 /* increase speech rate */,
[ C(SAY_SOFTER) ] = 58 /* decrease speech volume */,
[ C(SAY_LOUDER) ] = 59 /* increase speech volume */,
[ C(SWITCHVT_PREV) ] = 60 /* switch to previous virtual terminal */,
[ C(SWITCHVT_NEXT) ] = 61 /* switch to next virtual terminal */,
[ C(CSRJMP_VERT) ] = 62 /* bring cursor to line (no horizontal motion) */,
[ C(RESTARTBRL) ] = 63 /* reinitialize braille driver */,
[ C(RESTARTSPEECH) ] = 64 /* reinitialize speech driver */,
};
int raw;
bool WEBrailleOpen(int portType, int portNumber, DWORD *handle)
{
brlapi_handle_t *brl_handle = malloc(brlapi_getHandleSize());
brlapi_range_t ranges[] = {
{
.first = BRLAPI_KEY_TYPE_CMD | BRLAPI_KEY_CMD_ROUTE,
.last = BRLAPI_KEY_TYPE_CMD | BRLAPI_KEY_CMD_ROUTE | BRLAPI_KEY_CMD_ARG_MASK,
}
};
int i,j;
brlapi_range_t *cmd_ranges;
if (brlapi__openConnection(brl_handle, NULL, NULL) == INVALID_HANDLE_VALUE)
goto error;
raw = portNumber == 2;
if (raw) {
char name[BRLAPI_MAXNAMELENGTH+1];
if (brlapi__getDriverName(brl_handle, name, sizeof(name)) == -1)
goto error;
if (brlapi__enterTtyModeWithPath(brl_handle, NULL, 0, name) == -1)
goto error;
} else {
if (brlapi__enterTtyModeWithPath(brl_handle, NULL, 0, NULL) == -1)
goto error;
}
if (brlapi__ignoreAllKeys(brl_handle) == -1)
goto error;
if (brlapi__acceptKeyRanges(brl_handle, ranges, sizeof(ranges)/sizeof(ranges[0])) == -1)
goto error;
cmd_ranges = malloc(64 * sizeof(cmd_ranges[0]));
for (i = 0, j = 0; i < sizeof(command_button)/sizeof(command_button[0]); i++) {
if (command_button[i]) {
cmd_ranges[j].first = cmd_ranges[j].last = BRLAPI_KEY_TYPE_CMD | (BRLAPI_KEY_CMD(0) + command_button[i]);
j++;
}
}
if (brlapi__acceptKeyRanges(brl_handle, cmd_ranges, j) == -1)
goto error;
free(cmd_ranges);
*handle = (DWORD) brl_handle;
return TRUE;
error:
free(brl_handle);
return FALSE;
}
bool WEBrailleClose(DWORD handle)
{
brlapi_handle_t *brl_handle = (void*) handle;
brlapi__closeConnection(brl_handle);
return TRUE;
}
bool WEGetBrailleDisplayInfo(DWORD handle, int *numberOfCells, int *numberOfStatusCells)
{
brlapi_handle_t *brl_handle = (void*) handle;
unsigned int x, y;
if (brlapi__getDisplaySize(brl_handle, &x, &y) == -1)
return FALSE;
*numberOfCells = x * y;
*numberOfStatusCells = 0;
return TRUE;
}
static bool keysent = FALSE;
bool WEGetBrailleKey(DWORD handle, DWORD *key1, DWORD *key2, int *routingKey, int *doubleRoutingKey, bool *routingOverStatusCell)
{
brlapi_handle_t *brl_handle = (void*) handle;
brlapi_keyCode_t code;
unsigned cmd;
*key1 = 0;
*key2 = 0;
*routingKey = 0;
*doubleRoutingKey = 0;
*routingOverStatusCell = FALSE;
if (keysent) {
keysent = FALSE;
return TRUE;
}
if (brlapi__readKey(brl_handle, 0, &code) != 1)
return FALSE;
if (raw) {
keysent = TRUE;
*key1 = code & 0xffffffffu;
*key2 = code >> 32;
return TRUE;
}
if ((code & BRLAPI_KEY_TYPE_MASK) != BRLAPI_KEY_TYPE_CMD)
return FALSE;
cmd = code & BRLAPI_KEY_CMD_BLK_MASK;
if (cmd == BRLAPI_KEY_CMD_ROUTE) {
*routingKey = (code & BRLAPI_KEY_CMD_ARG_MASK) + 1;
} else {
unsigned button;
unsigned arg = code & BRLAPI_KEY_CMD_ARG_MASK;
if (arg >= sizeof(command_button)/sizeof(command_button[0]))
return FALSE;
button = command_button[arg];
if ((button > 64) || (button == 0))
return FALSE;
if (button > 32)
*key2 = 1 << (button - 1 - 32);
else
*key1 = 1 << (button - 1);
}
keysent = TRUE;
return TRUE;
}
bool WEUpdateBrailleDisplay(DWORD handle, BYTE *pMainCells, int mainCellsCount, BYTE *pStatusCells, int statusCellsCount)
{
brlapi_handle_t *brl_handle = (void*) handle;
int numCells, numStatCells;
if (!WEGetBrailleDisplayInfo(handle, &numCells, &numStatCells))
return FALSE;
{
unsigned char dots[numCells];
memcpy(dots, pMainCells, mainCellsCount);
memset(dots + mainCellsCount, 0, numCells - mainCellsCount);
if (brlapi__writeDots(brl_handle, dots) == -1)
return FALSE;
}
return TRUE;
}