blob: c3bb6b6ed491012564073808c817ab4ce1c70fce [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 "charset_internal.h"
#include "unicode.h"
#include "system_msdos.h"
#define CHARACTER_SET_SIZE 0X100
static const uint16_t toUnicode_Latin1[CHARACTER_SET_SIZE] = {
/* 00 */ 0X0000, 0X0001, 0X0002, 0X0003, 0X0004, 0X0005, 0X0006, 0X0007,
/* 08 */ 0X0008, 0X0009, 0X000A, 0X000B, 0X000C, 0X000D, 0X000E, 0X000F,
/* 10 */ 0X0010, 0X0011, 0X0012, 0X0013, 0X0014, 0X0015, 0X0016, 0X0017,
/* 18 */ 0X0018, 0X0019, 0X001A, 0X001B, 0X001C, 0X001D, 0X001E, 0X001F,
/* 20 */ 0X0020, 0X0021, 0X0022, 0X0023, 0X0024, 0X0025, 0X0026, 0X0027,
/* 28 */ 0X0028, 0X0029, 0X002A, 0X002B, 0X002C, 0X002D, 0X002E, 0X002F,
/* 30 */ 0X0030, 0X0031, 0X0032, 0X0033, 0X0034, 0X0035, 0X0036, 0X0037,
/* 38 */ 0X0038, 0X0039, 0X003A, 0X003B, 0X003C, 0X003D, 0X003E, 0X003F,
/* 40 */ 0X0040, 0X0041, 0X0042, 0X0043, 0X0044, 0X0045, 0X0046, 0X0047,
/* 48 */ 0X0048, 0X0049, 0X004A, 0X004B, 0X004C, 0X004D, 0X004E, 0X004F,
/* 50 */ 0X0050, 0X0051, 0X0052, 0X0053, 0X0054, 0X0055, 0X0056, 0X0057,
/* 58 */ 0X0058, 0X0059, 0X005A, 0X005B, 0X005C, 0X005D, 0X005E, 0X005F,
/* 60 */ 0X0060, 0X0061, 0X0062, 0X0063, 0X0064, 0X0065, 0X0066, 0X0067,
/* 68 */ 0X0068, 0X0069, 0X006A, 0X006B, 0X006C, 0X006D, 0X006E, 0X006F,
/* 70 */ 0X0070, 0X0071, 0X0072, 0X0073, 0X0074, 0X0075, 0X0076, 0X0077,
/* 78 */ 0X0078, 0X0079, 0X007A, 0X007B, 0X007C, 0X007D, 0X007E, 0X007F,
/* 80 */ 0X0080, 0X0081, 0X0082, 0X0083, 0X0084, 0X0085, 0X0086, 0X0087,
/* 88 */ 0X0088, 0X0089, 0X008A, 0X008B, 0X008C, 0X008D, 0X008E, 0X008F,
/* 90 */ 0X0090, 0X0091, 0X0092, 0X0093, 0X0094, 0X0095, 0X0096, 0X0097,
/* 98 */ 0X0098, 0X0099, 0X009A, 0X009B, 0X009C, 0X009D, 0X009E, 0X009F,
/* A0 */ 0X00A0, 0X00A1, 0X00A2, 0X00A3, 0X00A4, 0X00A5, 0X00A6, 0X00A7,
/* A8 */ 0X00A8, 0X00A9, 0X00AA, 0X00AB, 0X00AC, 0X00AD, 0X00AE, 0X00AF,
/* B0 */ 0X00B0, 0X00B1, 0X00B2, 0X00B3, 0X00B4, 0X00B5, 0X00B6, 0X00B7,
/* B8 */ 0X00B8, 0X00B9, 0X00BA, 0X00BB, 0X00BC, 0X00BD, 0X00BE, 0X00BF,
/* C0 */ 0X00C0, 0X00C1, 0X00C2, 0X00C3, 0X00C4, 0X00C5, 0X00C6, 0X00C7,
/* C8 */ 0X00C8, 0X00C9, 0X00CA, 0X00CB, 0X00CC, 0X00CD, 0X00CE, 0X00CF,
/* D0 */ 0X00D0, 0X00D1, 0X00D2, 0X00D3, 0X00D4, 0X00D5, 0X00D6, 0X00D7,
/* D8 */ 0X00D8, 0X00D9, 0X00DA, 0X00DB, 0X00DC, 0X00DD, 0X00DE, 0X00DF,
/* E0 */ 0X00E0, 0X00E1, 0X00E2, 0X00E3, 0X00E4, 0X00E5, 0X00E6, 0X00E7,
/* E8 */ 0X00E8, 0X00E9, 0X00EA, 0X00EB, 0X00EC, 0X00ED, 0X00EE, 0X00EF,
/* F0 */ 0X00F0, 0X00F1, 0X00F2, 0X00F3, 0X00F4, 0X00F5, 0X00F6, 0X00F7,
/* F8 */ 0X00F8, 0X00F9, 0X00FA, 0X00FB, 0X00FC, 0X00FD, 0X00FE, 0X00FF,
};
static const uint16_t toUnicode_CP437[CHARACTER_SET_SIZE] = {
/* 00 */ 0X0000, 0X0001, 0X0002, 0X0003, 0X0004, 0X0005, 0X0006, 0X0007,
/* 08 */ 0X0008, 0X0009, 0X000A, 0X000B, 0X000C, 0X000D, 0X000E, 0X000F,
/* 10 */ 0X0010, 0X0011, 0X0012, 0X0013, 0X0014, 0X0015, 0X0016, 0X0017,
/* 18 */ 0X0018, 0X0019, 0X001A, 0X001B, 0X001C, 0X001D, 0X001E, 0X001F,
/* 20 */ 0X0020, 0X0021, 0X0022, 0X0023, 0X0024, 0X0025, 0X0026, 0X0027,
/* 28 */ 0X0028, 0X0029, 0X002A, 0X002B, 0X002C, 0X002D, 0X002E, 0X002F,
/* 30 */ 0X0030, 0X0031, 0X0032, 0X0033, 0X0034, 0X0035, 0X0036, 0X0037,
/* 38 */ 0X0038, 0X0039, 0X003A, 0X003B, 0X003C, 0X003D, 0X003E, 0X003F,
/* 40 */ 0X0040, 0X0041, 0X0042, 0X0043, 0X0044, 0X0045, 0X0046, 0X0047,
/* 48 */ 0X0048, 0X0049, 0X004A, 0X004B, 0X004C, 0X004D, 0X004E, 0X004F,
/* 50 */ 0X0050, 0X0051, 0X0052, 0X0053, 0X0054, 0X0055, 0X0056, 0X0057,
/* 58 */ 0X0058, 0X0059, 0X005A, 0X005B, 0X005C, 0X005D, 0X005E, 0X005F,
/* 60 */ 0X0060, 0X0061, 0X0062, 0X0063, 0X0064, 0X0065, 0X0066, 0X0067,
/* 68 */ 0X0068, 0X0069, 0X006A, 0X006B, 0X006C, 0X006D, 0X006E, 0X006F,
/* 70 */ 0X0070, 0X0071, 0X0072, 0X0073, 0X0074, 0X0075, 0X0076, 0X0077,
/* 78 */ 0X0078, 0X0079, 0X007A, 0X007B, 0X007C, 0X007D, 0X007E, 0X007F,
/* 80 */ 0X00C7, 0X00FC, 0X00E9, 0X00E2, 0X00E4, 0X00E0, 0X00E5, 0X00E7,
/* 88 */ 0X00EA, 0X00EB, 0X00E8, 0X00EF, 0X00EE, 0X00EC, 0X00C4, 0X00C5,
/* 90 */ 0X00C9, 0X00E6, 0X00C6, 0X00F4, 0X00F6, 0X00F2, 0X00FB, 0X00F9,
/* 98 */ 0X00FF, 0X00D6, 0X00DC, 0X00A2, 0X00A3, 0X00A5, 0X20A7, 0X0192,
/* A0 */ 0X00E1, 0X00ED, 0X00F3, 0X00FA, 0X00F1, 0X00D1, 0X00AA, 0X00BA,
/* A8 */ 0X00BF, 0X2310, 0X00AC, 0X00BD, 0X00BC, 0X00A1, 0X00AB, 0X00BB,
/* B0 */ 0X2591, 0X2592, 0X2593, 0X2502, 0X2524, 0X2561, 0X2562, 0X2556,
/* B8 */ 0X2555, 0X2563, 0X2551, 0X2557, 0X255D, 0X255C, 0X255B, 0X2510,
/* C0 */ 0X2514, 0X2534, 0X252C, 0X251C, 0X2500, 0X253C, 0X255E, 0X255F,
/* C8 */ 0X255A, 0X2554, 0X2569, 0X2566, 0X2560, 0X2550, 0X256C, 0X2567,
/* D0 */ 0X2568, 0X2564, 0X2565, 0X2559, 0X2558, 0X2552, 0X2553, 0X256B,
/* D8 */ 0X256A, 0X2518, 0X250C, 0X2588, 0X2584, 0X258C, 0X2590, 0X2580,
/* E0 */ 0X03B1, 0X00DF, 0X0393, 0X03C0, 0X03A3, 0X03C3, 0X00B5, 0X03C4,
/* E8 */ 0X03A6, 0X0398, 0X03A9, 0X03B4, 0X221E, 0X03C6, 0X03B5, 0X2229,
/* F0 */ 0X2261, 0X00B1, 0X2265, 0X2264, 0X2320, 0X2321, 0X00F7, 0X2248,
/* F8 */ 0X00B0, 0X2219, 0X00B7, 0X221A, 0X207F, 0X00B2, 0X25A0, 0X00A0
};
static const uint16_t toUnicode_CP850[CHARACTER_SET_SIZE] = {
/* 00 */ 0X0000, 0X0001, 0X0002, 0X0003, 0X0004, 0X0005, 0X0006, 0X0007,
/* 08 */ 0X0008, 0X0009, 0X000A, 0X000B, 0X000C, 0X000D, 0X000E, 0X000F,
/* 10 */ 0X0010, 0X0011, 0X0012, 0X0013, 0X0014, 0X0015, 0X0016, 0X0017,
/* 18 */ 0X0018, 0X0019, 0X001A, 0X001B, 0X001C, 0X001D, 0X001E, 0X001F,
/* 20 */ 0X0020, 0X0021, 0X0022, 0X0023, 0X0024, 0X0025, 0X0026, 0X0027,
/* 28 */ 0X0028, 0X0029, 0X002A, 0X002B, 0X002C, 0X002D, 0X002E, 0X002F,
/* 30 */ 0X0030, 0X0031, 0X0032, 0X0033, 0X0034, 0X0035, 0X0036, 0X0037,
/* 38 */ 0X0038, 0X0039, 0X003A, 0X003B, 0X003C, 0X003D, 0X003E, 0X003F,
/* 40 */ 0X0040, 0X0041, 0X0042, 0X0043, 0X0044, 0X0045, 0X0046, 0X0047,
/* 48 */ 0X0048, 0X0049, 0X004A, 0X004B, 0X004C, 0X004D, 0X004E, 0X004F,
/* 50 */ 0X0050, 0X0051, 0X0052, 0X0053, 0X0054, 0X0055, 0X0056, 0X0057,
/* 58 */ 0X0058, 0X0059, 0X005A, 0X005B, 0X005C, 0X005D, 0X005E, 0X005F,
/* 60 */ 0X0060, 0X0061, 0X0062, 0X0063, 0X0064, 0X0065, 0X0066, 0X0067,
/* 68 */ 0X0068, 0X0069, 0X006A, 0X006B, 0X006C, 0X006D, 0X006E, 0X006F,
/* 70 */ 0X0070, 0X0071, 0X0072, 0X0073, 0X0074, 0X0075, 0X0076, 0X0077,
/* 78 */ 0X0078, 0X0079, 0X007A, 0X007B, 0X007C, 0X007D, 0X007E, 0X007F,
/* 80 */ 0X00C7, 0X00FC, 0X00E9, 0X00E2, 0X00E4, 0X00E0, 0X00E5, 0X00E7,
/* 88 */ 0X00EA, 0X00EB, 0X00E8, 0X00EF, 0X00EE, 0X00EC, 0X00C4, 0X00C5,
/* 90 */ 0X00C9, 0X00E6, 0X00C6, 0X00F4, 0X00F6, 0X00F2, 0X00FB, 0X00F9,
/* 98 */ 0X00FF, 0X00D6, 0X00DC, 0X00F8, 0X00A3, 0X00D8, 0X00D7, 0X0192,
/* A0 */ 0X00E1, 0X00ED, 0X00F3, 0X00FA, 0X00F1, 0X00D1, 0X00AA, 0X00BA,
/* A8 */ 0X00BF, 0X00AE, 0X00AC, 0X00BD, 0X00BC, 0X00A1, 0X00AB, 0X00BB,
/* B0 */ 0X2591, 0X2592, 0X2593, 0X2502, 0X2524, 0X00C1, 0X00C2, 0X00C0,
/* B8 */ 0X00A9, 0X2563, 0X2551, 0X2557, 0X255D, 0X00A2, 0X00A5, 0X2510,
/* C0 */ 0X2514, 0X2534, 0X252C, 0X251C, 0X2500, 0X253C, 0X00E3, 0X00C3,
/* C8 */ 0X255A, 0X2554, 0X2569, 0X2566, 0X2560, 0X2550, 0X256C, 0X00A4,
/* D0 */ 0X00F0, 0X00D0, 0X00CA, 0X00CB, 0X00C8, 0X0131, 0X00CD, 0X00CE,
/* D8 */ 0X00CF, 0X2518, 0X250C, 0X2588, 0X2584, 0X00A6, 0X00CC, 0X2580,
/* E0 */ 0X00D3, 0X00DF, 0X00D4, 0X00D2, 0X00F5, 0X00D5, 0X00B5, 0X00FE,
/* E8 */ 0X00DE, 0X00DA, 0X00DB, 0X00D9, 0X00FD, 0X00DD, 0X00AF, 0X00B4,
/* F0 */ 0X00AD, 0X00B1, 0X2017, 0X00BE, 0X00B6, 0X00A7, 0X00F7, 0X00B8,
/* F8 */ 0X00B0, 0X00A8, 0X00B7, 0X00B9, 0X00B3, 0X00B2, 0X25A0, 0X00A0
};
typedef struct {
const char *name;
const uint16_t *toUnicode;
} CharacterSet;
static const CharacterSet characterSets[] = {
{.name="iso-8859-1", .toUnicode=toUnicode_Latin1},
{.name="cp437", .toUnicode=toUnicode_CP437},
{.name="cp850", .toUnicode=toUnicode_CP850},
{}
};
static const CharacterSet *characterSet;
static char *unicodeRows[UNICODE_ROWS_PER_PLANE];
static void
clearUnicodeRow (char *row) {
memset(row, 0, UNICODE_CELLS_PER_ROW);
}
static void
clearUnicodeRows (void) {
int rowNumber;
for (rowNumber=0; rowNumber<UNICODE_ROWS_PER_PLANE; ++rowNumber) {
char *row = unicodeRows[rowNumber];
if (row) clearUnicodeRow(row);
}
}
static char *
getUnicodeCell (uint16_t unicode, int allocate) {
unsigned char cellNumber = unicode & 0XFF;
unsigned char rowNumber = unicode >> 8;
char **rowAddress = &unicodeRows[rowNumber];
if (!*rowAddress) {
if (!allocate) return NULL;
{
char *row = malloc(UNICODE_CELLS_PER_ROW);
if (!row) return NULL;
clearUnicodeRow(row);
*rowAddress = row;
}
}
return &(*rowAddress)[cellNumber];
}
static int
setCharacterSet (const char *name) {
const CharacterSet *set = characterSets;
while (set->name) {
if (strcasecmp(name, set->name) == 0) {
clearUnicodeRows();
characterSet = NULL;
{
int character;
for (character=CHARACTER_SET_SIZE-1; character>=0; --character) {
char *cell = getUnicodeCell(set->toUnicode[character], 1);
if (!cell) return 0;
*cell = character;
}
}
characterSet = set;
return 1;
}
++set;
}
return 0;
}
wint_t
convertCharToWchar (char c) {
if (getCharset()) {
uint16_t wc = characterSet->toUnicode[(unsigned char)c & 0XFF];
if (wc || !c)
if ((sizeof(wchar_t) > 1) || iswLatin1(wc))
return wc;
}
return WEOF;
}
int
convertWcharToChar (wchar_t wc) {
if (getCharset()) {
char *cell = getUnicodeCell(wc, 0);
if (cell)
if (*cell || !wc)
return *cell & 0XFF;
}
return EOF;
}
const char *
getLocaleCharset (void) {
static char codepage[8];
snprintf(codepage, sizeof(codepage), "CP%03u", msdosGetCodePage());
return codepage;
}
int
registerCharacterSet (const char *charset) {
return setCharacterSet(charset);
}