[BRLTTY] Working with braille characters in console mode?
Samuel Thibault
samuel.thibault at ens-lyon.org
Mon Jan 21 05:33:39 EST 2008
Samuel Thibault, le Mon 21 Jan 2008 00:20:47 +0000, a écrit :
> Samuel Thibault, le Sat 19 Jan 2008 23:23:22 +0000, a écrit :
> > Samuel Thibault, le Sat 19 Jan 2008 21:13:46 +0000, a écrit :
> > > > have brltty map them correctly to the associated dot combination?
> > >
> > > Unfortunately the screen driver model still does't take unicode into
> > > account and thus brltty will still show question marks for now.
> >
> > Maybe we could extend it temporarily without having to revamp everything
> > right now by just adding a SCR_DOTS request that returns dots, if any?
> > For 0x28uv, the screen driver would return ' ' for SCR_TEXT and 0xuv for
> > SCR_DOTS, which the main loop of brltty.c could mix just before the call
> > to writeWindow.
>
> Here is a patch, tested for the Linux and AtSpi screen drivers.
Here is a fixed patch (against svn revision 3469)
Samuel
-------------- next part --------------
Index: Programs/scr_help.c
===================================================================
--- Programs/scr_help.c (r?vision 3468)
+++ Programs/scr_help.c (copie de travail)
@@ -246,6 +246,8 @@
pages[pageNumber] + ((box.top + row) * getBigEndian(description->width)) + box.left,
box.width);
}
+ } else if (property == SCR_DOTS) {
+ memset(buffer, 0X00, box.width*box.height);
} else {
memset(buffer, 0X07, box.width*box.height);
}
Index: Programs/scr_base.c
--- Programs/scr_base.c (r?vision 3468)
+++ Programs/scr_base.c (copie de travail)
@@ -57,6 +57,8 @@
if (!validateScreenBox(&box, description.cols, description.rows)) return 0;
if (property == SCR_TEXT) {
memcpy(buffer, text_BaseScreen+box.left, box.width);
+ } else if (property == SCR_DOTS) {
+ memset(buffer, 0X00, box.width);
} else {
memset(buffer, 0X07, box.width);
}
Index: Programs/scr_frozen.c
--- Programs/scr_frozen.c (r?vision 3468)
+++ Programs/scr_frozen.c (copie de travail)
@@ -27,6 +27,7 @@
static ScreenDescription screenDescription;
static unsigned char *screenText;
static unsigned char *screenAttributes;
+static unsigned char *screenDots;
static int
construct_FrozenScreen (BaseScreen *source) {
@@ -35,7 +36,9 @@
if ((screenAttributes = calloc(screenDescription.rows*screenDescription.cols, sizeof(*screenAttributes)))) {
if (source->read((ScreenBox){0, 0, screenDescription.cols, screenDescription.rows}, screenText, SCR_TEXT)) {
if (source->read((ScreenBox){0, 0, screenDescription.cols, screenDescription.rows}, screenAttributes, SCR_ATTRIB)) {
- return 1;
+ if (source->read((ScreenBox){0, 0, screenDescription.cols, screenDescription.rows}, screenDots, SCR_DOTS)) {
+ return 1;
+ }
}
}
free(screenAttributes);
@@ -71,7 +74,7 @@
static int
read_FrozenScreen (ScreenBox box, unsigned char *buffer, ScreenCharacterProperty property) {
if (validateScreenBox(&box, screenDescription.cols, screenDescription.rows)) {
- unsigned char *screen = (property == SCR_TEXT)? screenText: screenAttributes;
+ unsigned char *screen = (property == SCR_TEXT)? screenText: (property == SCR_DOTS)? screenDots: screenAttributes;
int row;
for (row=0; row<box.height; row++)
memcpy(buffer + (row * box.width),
Index: Programs/brltty.c
--- Programs/brltty.c (r?vision 3468)
+++ Programs/brltty.c (copie de travail)
@@ -2488,6 +2488,21 @@
readScreen(p->winx, p->winy, winlen, brl.y, attrbuf, SCR_ATTRIB);
overlayAttributes(attrbuf, winlen, brl.y);
}
+
+ /* Mix raw U+28uv dots */
+ if (!p->showAttributes) {
+ unsigned char buf[brl.x*brl.y];
+ readScreen(p->winx, p->winy, winlen, brl.y, buf, SCR_DOTS);
+ int i;
+ if (winlen < brl.x) {
+ for (i=brl.y-1; i>0; i--)
+ memmove(buf+i*brl.x, buf+i*winlen, winlen);
+ for (i=0; i<brl.y; i++)
+ memset(buf+i*brl.x+winlen, 0, brl.x-winlen);
+ }
+ for (i=0; i<brl.x*brl.y; i++)
+ if (buf[i]) brl.buffer[i] = buf[i];
+ }
}
if (brl.cursor >= 0) {
Index: Programs/scr.c
--- Programs/scr.c (r?vision 3468)
+++ Programs/scr.c (copie de travail)
@@ -205,6 +205,8 @@
memset(buffer, ' ', count);
if (length) memcpy(buffer, message+box->left, length);
+ } else if (property == SCR_DOTS) {
+ memset(buffer, 0X00, count);
} else {
memset(buffer, 0X07, count);
}
Index: Programs/scr.h
--- Programs/scr.h (r?vision 3468)
+++ Programs/scr.h (copie de travail)
@@ -27,7 +27,8 @@
/* mode argument for readScreen() */
typedef enum {
SCR_TEXT, /* get screen text */
- SCR_ATTRIB /* get screen attributes */
+ SCR_ATTRIB, /* get screen attributes */
+ SCR_DOTS /* get dots, if any */
} ScreenCharacterProperty;
typedef struct {
Index: ScreenDrivers/Linux/screen.c
--- ScreenDrivers/Linux/screen.c (r?vision 3468)
+++ ScreenDrivers/Linux/screen.c (copie de travail)
@@ -451,7 +451,7 @@
static unsigned short shiftedAttributesMask;
static void
-setAttributesMasks (unsigned char bit) {
+setAttributesMasks (unsigned short bit) {
fontAttributesMask = bit;
unshiftedAttributesMask = (((bit & 0XF000) - 0X1000) & 0XF000) |
(((bit & 0X0F00) - 0X0100) & 0X0F00);
@@ -529,7 +529,7 @@
if (parameters[PARM_HFB] && *parameters[PARM_HFB]) {
int bit = 0;
static const int minimum = 0;
- static const int maximum = 7;
+ static const int maximum = 15;
static const char *choices[] = {"auto", "vga", "fb", NULL};
unsigned int choice;
if (validateInteger(&bit, parameters[PARM_HFB], &minimum, &maximum)) {
@@ -581,6 +581,37 @@
* the expected character set.
*/
static unsigned char translationTable[0X200];
+static unsigned char dotsTranslationTable[0X200];
+
+static int findPosition(unsigned short unicode) {
+ unsigned short directPosition = 0XFF;
+ int position = -1;
+
+ if (vgaLargeTable) directPosition |= 0X100;
+
+ if (!screenFontMapCount) {
+ if (unicode < 0X100) position = unicode;
+ } else if ((unicode & ~directPosition) == 0XF000) {
+ position = unicode & directPosition;
+ } else {
+ int first = 0;
+ int last = screenFontMapCount-1;
+ while (first <= last) {
+ int current = (first + last) / 2;
+ struct unipair *map = &screenFontMapTable[current];
+ if (map->unicode < unicode)
+ first = current + 1;
+ else if (map->unicode > unicode)
+ last = current - 1;
+ else {
+ if (map->fontpos < vgaCharacterCount) position = map->fontpos;
+ break;
+ }
+ }
+ }
+ return position;
+}
+
static int
setTranslationTable (int force) {
int acmChanged = setApplicationCharacterMap && setApplicationCharacterMap(force);
@@ -590,35 +621,13 @@
if (vccChanged || force) determineAttributesMasks();
if (acmChanged || sfmChanged || vccChanged) {
- unsigned short directPosition = 0XFF;
- if (vgaLargeTable) directPosition |= 0X100;
-
memset(translationTable, '?', sizeof(translationTable));
+ memset(dotsTranslationTable, 0, sizeof(dotsTranslationTable));
{
int character;
for (character=0XFF; character>=0; --character) {
unsigned short unicode = applicationCharacterMap[character];
- int position = -1;
- if (!screenFontMapCount) {
- if (unicode < 0X100) position = unicode;
- } else if ((unicode & ~directPosition) == 0XF000) {
- position = unicode & directPosition;
- } else {
- int first = 0;
- int last = screenFontMapCount-1;
- while (first <= last) {
- int current = (first + last) / 2;
- struct unipair *map = &screenFontMapTable[current];
- if (map->unicode < unicode)
- first = current + 1;
- else if (map->unicode > unicode)
- last = current - 1;
- else {
- if (map->fontpos < vgaCharacterCount) position = map->fontpos;
- break;
- }
- }
- }
+ int position = findPosition(unicode);
if (position < 0) {
if (debugCharacterTranslationTable) {
LogPrint(LOG_DEBUG, "no character mapping: char=%2.2X unum=%4.4X", character, unicode);
@@ -632,6 +641,24 @@
}
}
}
+ {
+ int dots;
+ for (dots=0XFF; dots>=0; --dots) {
+ unsigned short unicode = BRL_UC_ROW|dots;
+ int position = findPosition(unicode);
+ if (position < 0) {
+ if (debugCharacterTranslationTable) {
+ LogPrint(LOG_DEBUG, "no dots mapping: dots=%2.2X unum=%4.4X", dots, unicode);
+ }
+ } else {
+ dotsTranslationTable[position] = dots;
+ if (debugCharacterTranslationTable) {
+ LogPrint(LOG_DEBUG, "dots mapping: dots=%2.2X unum=%4.4X fpos=%2.2X",
+ dots, unicode, position);
+ }
+ }
+ }
+ }
if (debugCharacterTranslationTable) {
const unsigned int count = 0X10;
int position;
@@ -640,6 +667,11 @@
sprintf(description, "c2f[%02X]", position);
LogBytes(LOG_DEBUG, description, &translationTable[position], count);
}
+ for (position=0; position<vgaCharacterCount; position+=count) {
+ char description[0X20];
+ sprintf(description, "c2f[%02X]", position);
+ LogBytes(LOG_DEBUG, description, &dotsTranslationTable[position], count);
+ }
}
return 1;
}
@@ -907,8 +939,6 @@
ScreenDescription description;
describe_LinuxScreen(&description);
if (validateScreenBox(&box, description.cols, description.rows)) {
- int text = property == SCR_TEXT;
-
if (problemText) {
setScreenMessage(&box, buffer, property, problemText);
return 1;
@@ -945,7 +975,7 @@
}
source = line;
- if (text) {
+ if (property == SCR_TEXT) {
unsigned char src[box.width];
const unsigned char *trg = target;
int column;
@@ -964,6 +994,25 @@
memcpy(desc, "char", 4);
LogBytes(LOG_DEBUG, desc, trg, box.width);
}
+ } else if (property == SCR_DOTS) {
+ unsigned char src[box.width];
+ const unsigned char *trg = target;
+ int column;
+ for (column=0; column<box.width; ++column) {
+ const unsigned char byte = *source & 0XFF;
+ int position = byte;
+ if (*source & fontAttributesMask) position |= 0X100;
+ src[column] = byte;
+ *target++ = dotsTranslationTable[position];
+ source++;
+ }
+ if (debugScreenTextTranslation) {
+ char desc[0X20];
+ sprintf(desc, "fpos[%03d,%03d]", box.left, box.top+row);
+ LogBytes(LOG_DEBUG, desc, src, box.width);
+ memcpy(desc, "dots", 4);
+ LogBytes(LOG_DEBUG, desc, trg, box.width);
+ }
} else {
int column;
for (column=0; column<box.width; ++column) {
Index: ScreenDrivers/PcBios/screen.c
--- ScreenDrivers/PcBios/screen.c (r?vision 3468)
+++ ScreenDrivers/PcBios/screen.c (copie de travail)
@@ -59,6 +59,10 @@
unsigned offset = ScreenPrimary;
ScreenDescription description;
describe_PcBiosScreen(&description);
+ if (property == SCR_DOTS) {
+ memset(buffer, 0, box.width * box.height);
+ return 1;
+ }
if (validateScreenBox(&box, description.cols, description.rows)) {
int row, col;
_farsetsel(_go32_conventional_mem_selector());
Index: ScreenDrivers/Screen/screen.c
--- ScreenDrivers/Screen/screen.c (r?vision 3468)
+++ ScreenDrivers/Screen/screen.c (copie de travail)
@@ -176,6 +176,10 @@
read_ScreenScreen (ScreenBox box, unsigned char *buffer, ScreenCharacterProperty property) {
ScreenDescription description; /* screen statistics */
describe_ScreenScreen(&description);
+ if (property == SCR_DOTS) {
+ memset(buffer, 0, box.width * box.height);
+ return 1;
+ }
if (validateScreenBox(&box, description.cols, description.rows)) {
off_t start = 4 + (((property == SCR_TEXT)? 0: 1) * description.cols * description.rows) + (box.top * description.cols) + box.left;
int row;
Index: ScreenDrivers/AtSpi/screen.c
--- ScreenDrivers/AtSpi/screen.c (r?vision 3468)
+++ ScreenDrivers/AtSpi/screen.c (copie de travail)
@@ -608,7 +608,10 @@
memset(buffer,0x07,box.height*box.width);
return 1;
}
- memset(buffer,' ',box.height*box.width);
+ if (property == SCR_TEXT)
+ memset(buffer,' ',box.height*box.width);
+ else
+ memset(buffer,0,box.height*box.width);
pthread_mutex_lock(&updateMutex);
if (!curTerm) {
setScreenMessage(&box, buffer, property, nonatspi);
@@ -621,8 +624,15 @@
if (curRowLengths[box.top+y])
for (x=0; x<box.width; x++) {
if (box.left+x<curRowLengths[box.top+y] - (curRows[box.top+y][curRowLengths[box.top+y]-1]=='\n')) {
- if ((c = convertWcharToChar(curRows[box.top+y][box.left+x])) == EOF)
- c = '?';
+ if (property == SCR_TEXT) {
+ if ((c = convertWcharToChar(curRows[box.top+y][box.left+x])) == EOF)
+ c = '?';
+ } else {
+ if (((curRows[box.top+y][box.left+x]) & ~0xFF) == BRL_UC_ROW)
+ c = curRows[box.top+y][box.left+x] & 0xFF;
+ else
+ c = 0;
+ }
buffer[y*box.width+x] = c;
}
}
Index: ScreenDrivers/Hurd/screen.c
--- ScreenDrivers/Hurd/screen.c (r?vision 3468)
+++ ScreenDrivers/Hurd/screen.c (copie de travail)
@@ -214,13 +214,21 @@
}
if (validateScreenBox(&box, description.cols, description.rows)) {
uint32_t lines, start, row, col;
- const int which = property == SCR_TEXT ? offsetof(conchar_t,chr):offsetof(conchar_t,attr);
+ const int which = property != SCR_ATTRIB ? offsetof(conchar_t,chr):offsetof(conchar_t,attr);
lines = screenMap->screen.lines;
start = screenMap->screen.cur_line;
for (row=start+box.top; row<start+box.top+box.height; ++row)
for (col=box.left; col<box.left+box.width; ++col) {
- if ((c = convertWcharToChar(*(uint32_t *)(((unsigned char *) &screenDisplay[(row%lines)*description.cols+col])+which))) == EOF)
- c = '?';
+ if (property == SCR_DOTS) {
+ uint32_t wc = *(uint32_t *)(((unsigned char *) &screenDisplay[(row%lines)*description.cols+col])+which);
+ if ((wc & ~0xFF) == BRL_UC_ROW)
+ c = wc & 0xFF;
+ else
+ c = 0;
+ } else {
+ if ((c = convertWcharToChar(*(uint32_t *)(((unsigned char *) &screenDisplay[(row%lines)*description.cols+col])+which))) == EOF)
+ c = '?';
+ }
*buffer++ = c;
}
return 1;
Index: ScreenDrivers/Windows/screen.c
--- ScreenDrivers/Windows/screen.c (r?vision 3468)
+++ ScreenDrivers/Windows/screen.c (copie de travail)
@@ -193,7 +193,7 @@
static int
read_WindowsScreen (ScreenBox box, unsigned char *buffer, ScreenCharacterProperty property) {
/* TODO: GetConsoleCP */
- int text = property == SCR_TEXT;
+ int text = property != SCR_ATTRIB;
int x, y;
static int wide;
COORD coord;
@@ -269,7 +269,14 @@
if (wide > 0) {
for (x=0; x<box.width; x++) {
wchar_t c = ((wchar_t *)buf)[x];
- if (c >= 0X100) c = '?';
+ if (property == SCR_DOTS) {
+ if ((c & ~0xFF) == BRL_UC_ROW)
+ c &= 0xFF;
+ else
+ c = 0;
+ } else {
+ if (c >= 0X100) c = '?';
+ }
buffer[y*box.width+x] = c;
}
} else {
More information about the BRLTTY
mailing list