/* * 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-2019 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 . */ #include "prologue.h" #include #include "log.h" #include "report.h" #include "brl_utils.h" #include "brl_dots.h" #include "async_wait.h" #include "ktb.h" void drainBrailleOutput (BrailleDisplay *brl, int minimumDelay) { int duration = brl->writeDelay + 1; brl->writeDelay = 0; if (duration < minimumDelay) duration = minimumDelay; asyncWait(duration); } void setBrailleOffline (BrailleDisplay *brl) { if (!brl->isOffline) { brl->isOffline = 1; logMessage(LOG_DEBUG, "braille offline"); { KeyTable *keyTable = brl->keyTable; if (keyTable) releaseAllKeys(keyTable); } report(REPORT_BRAILLE_DEVICE_OFFLINE, NULL); } } void setBrailleOnline (BrailleDisplay *brl) { if (brl->isOffline) { brl->isOffline = 0; brl->writeDelay = 0; logMessage(LOG_DEBUG, "braille online"); report(REPORT_BRAILLE_DEVICE_ONLINE, NULL); } } int cellsHaveChanged ( unsigned char *cells, const unsigned char *new, unsigned int count, unsigned int *from, unsigned int *to, unsigned char *force ) { unsigned int first = 0; if (force && *force) { *force = 0; } else if (memcmp(cells, new, count) != 0) { if (to) { while (count) { unsigned int last = count - 1; if (cells[last] != new[last]) break; count = last; } } if (from) { while (first < count) { if (cells[first] != new[first]) break; first += 1; } } } else { return 0; } if (from) *from = first; if (to) *to = count; memcpy(cells+first, new+first, count-first); return 1; } int textHasChanged ( wchar_t *text, const wchar_t *new, unsigned int count, unsigned int *from, unsigned int *to, unsigned char *force ) { unsigned int first = 0; if (force && *force) { *force = 0; } else if (wmemcmp(text, new, count) != 0) { if (to) { while (count) { unsigned int last = count - 1; if (text[last] != new[last]) break; count = last; } } if (from) { while (first < count) { if (text[first] != new[first]) break; first += 1; } } } else { return 0; } if (from) *from = first; if (to) *to = count; wmemcpy(text+first, new+first, count-first); return 1; } int cursorHasChanged (int *cursor, int new, unsigned char *force) { if (force && *force) { *force = 0; } else if (new == *cursor) { return 0; } *cursor = new; return 1; } unsigned char toLowerDigit (unsigned char upper) { unsigned char lower = 0; if (upper & BRL_DOT_1) lower |= BRL_DOT_3; if (upper & BRL_DOT_2) lower |= BRL_DOT_7; if (upper & BRL_DOT_4) lower |= BRL_DOT_6; if (upper & BRL_DOT_5) lower |= BRL_DOT_8; return lower; } /* Dots for landscape (counterclockwise-rotated) digits. */ const DigitsTable landscapeDigits = { [ 0] = BRL_DOT_1 | BRL_DOT_5 | BRL_DOT_2, [ 1] = BRL_DOT_4, [ 2] = BRL_DOT_4 | BRL_DOT_1, [ 3] = BRL_DOT_4 | BRL_DOT_5, [ 4] = BRL_DOT_4 | BRL_DOT_5 | BRL_DOT_2, [ 5] = BRL_DOT_4 | BRL_DOT_2, [ 6] = BRL_DOT_4 | BRL_DOT_1 | BRL_DOT_5, [ 7] = BRL_DOT_4 | BRL_DOT_1 | BRL_DOT_5 | BRL_DOT_2, [ 8] = BRL_DOT_4 | BRL_DOT_1 | BRL_DOT_2, [ 9] = BRL_DOT_1 | BRL_DOT_5, [10] = BRL_DOT_1 | BRL_DOT_2 | BRL_DOT_4 | BRL_DOT_5 }; /* Format landscape representation of numbers 0 through 99. */ unsigned char makeLandscapeNumber (int x) { return landscapeDigits[(x / 10) % 10] | toLowerDigit(landscapeDigits[x % 10]); } /* Format landscape flag state indicator. */ unsigned char makeLandscapeFlag (int number, int on) { unsigned char dots = landscapeDigits[number % 10]; if (on) dots |= toLowerDigit(landscapeDigits[10]); return dots; } /* Dots for seascape (clockwise-rotated) digits. */ const DigitsTable seascapeDigits = { [ 0] = BRL_DOT_5 | BRL_DOT_1 | BRL_DOT_4, [ 1] = BRL_DOT_2, [ 2] = BRL_DOT_2 | BRL_DOT_5, [ 3] = BRL_DOT_2 | BRL_DOT_1, [ 4] = BRL_DOT_2 | BRL_DOT_1 | BRL_DOT_4, [ 5] = BRL_DOT_2 | BRL_DOT_4, [ 6] = BRL_DOT_2 | BRL_DOT_5 | BRL_DOT_1, [ 7] = BRL_DOT_2 | BRL_DOT_5 | BRL_DOT_1 | BRL_DOT_4, [ 8] = BRL_DOT_2 | BRL_DOT_5 | BRL_DOT_4, [ 9] = BRL_DOT_5 | BRL_DOT_1, [10] = BRL_DOT_1 | BRL_DOT_2 | BRL_DOT_4 | BRL_DOT_5 }; /* Format seascape representation of numbers 0 through 99. */ unsigned char makeSeascapeNumber (int x) { return toLowerDigit(seascapeDigits[(x / 10) % 10]) | seascapeDigits[x % 10]; } /* Format seascape flag state indicator. */ unsigned char makeSeascapeFlag (int number, int on) { unsigned char dots = toLowerDigit(seascapeDigits[number % 10]); if (on) dots |= seascapeDigits[10]; return dots; } /* Dots for portrait digits - 2 numbers in one cells */ const DigitsTable portraitDigits = { [ 0] = BRL_DOT_2 | BRL_DOT_4 | BRL_DOT_5, [ 1] = BRL_DOT_1, [ 2] = BRL_DOT_1 | BRL_DOT_2, [ 3] = BRL_DOT_1 | BRL_DOT_4, [ 4] = BRL_DOT_1 | BRL_DOT_4 | BRL_DOT_5, [ 5] = BRL_DOT_1 | BRL_DOT_5, [ 6] = BRL_DOT_1 | BRL_DOT_2 | BRL_DOT_4, [ 7] = BRL_DOT_1 | BRL_DOT_2 | BRL_DOT_4 | BRL_DOT_5, [ 8] = BRL_DOT_1 | BRL_DOT_2 | BRL_DOT_5, [ 9] = BRL_DOT_2 | BRL_DOT_4, [10] = BRL_DOT_1 | BRL_DOT_2 | BRL_DOT_4 | BRL_DOT_5 }; /* Format portrait representation of numbers 0 through 99. */ unsigned char makePortraitNumber (int x) { return portraitDigits[(x / 10) % 10] | toLowerDigit(portraitDigits[x % 10]); } /* Format portrait flag state indicator. */ unsigned char makePortraitFlag (int number, int on) { unsigned char dots = toLowerDigit(portraitDigits[number % 10]); if (on) dots |= portraitDigits[10]; return dots; }