/* Conversion of files between different charsets and surfaces. Copyright © 1990, 93, 94, 97, 98, 99, 00 Free Software Foundation, Inc. Contributed by François Pinard , 1988. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the `recode' Library; see the file `COPYING.LIB'. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "common.h" /* Baudot module This module implements some of the oldest character sets used by mankind. It is a generic implementation of 5-bit encodings. These were all based on the "Baudot" character set, which is often erroneously mistaken for ITA 2. For convinience, the alias "Baudot" is assiciated with ITA 2, though it is technically incorrect. ITA 1 (International Telegraph Alphabet #1) Murray (Invented by Donald Murray between 1899 and 1901) ITA 2 (International Telegraph Alphabet #2) US TTY (United States Teletype Alphabet) ITA 1 was the first international Baudot-based character set. Murray was a forerunner to ITA 2 ITA 2 was the same that was used in the German crypto machines during WW II. Alan Turing is said to have known this code by head. This code is still in operation amongst radio amateurs around the world. US TTY was the American variant. To be added: * The original Baudot alphabet (useful?) Documentation used: "Five-unit codes" by Alan G Hobbs http://www.nadcomm.com/fiveunit/fiveunits.htm "Annotated history of character codes" by Tom Jennings http://www.wps.com/texts/codes/ "Fish and I" by W. T. Tutte http://frode.home.cern.ch/frode/crypto/tutte.pdf */ enum baudot_mutations { ita1, murray, ita2, us_tty }; static int mutation; char letter_shift; char figure_shift; static bool init_ita1 (RECODE_STEP step, RECODE_CONST_REQUEST request, RECODE_CONST_OPTION_LIST before_options, RECODE_CONST_OPTION_LIST after_options) { mutation = ita1; letter_shift = 0x0F; figure_shift = 0x17; return true; } static bool init_murray (RECODE_STEP step, RECODE_CONST_REQUEST request, RECODE_CONST_OPTION_LIST before_options, RECODE_CONST_OPTION_LIST after_options) { mutation = murray; letter_shift = 0x04; figure_shift = 0x1B; return true; } static bool init_ita2 (RECODE_STEP step, RECODE_CONST_REQUEST request, RECODE_CONST_OPTION_LIST before_options, RECODE_CONST_OPTION_LIST after_options) { mutation = ita2; letter_shift = 0x1F; figure_shift = 0x1B; return true; } static bool init_us_tty (RECODE_STEP step, RECODE_CONST_REQUEST request, RECODE_CONST_OPTION_LIST before_options, RECODE_CONST_OPTION_LIST after_options) { mutation = us_tty; letter_shift = 0x1F; figure_shift = 0x1B; return true; } static bool transform_ucs2_baudot (RECODE_SUBTASK subtask) { unsigned input_char; bool mode_figs = false; char queue = '\0'; while (get_ucs2 (&input_char, subtask)) { /* Convert all lower-case to upper-case */ if (input_char >= 'a' && input_char <= 'z') { RETURN_IF_NOGO (RECODE_AMBIGUOUS_OUTPUT, subtask); input_char = (unsigned) toupper ((char) input_char); } /* Detect switching */ if (mode_figs && (input_char >= 'A' && input_char <= 'Z')) { mode_figs = false; if (mutation == ita1 || mutation == murray) { if (queue == figure_shift) queue = '\0'; put_byte(letter_shift, subtask); /* Letters + space */ } else put_byte(letter_shift, subtask); } else if (!mode_figs && (index("-?:().,\'\%;/+0123456789\a", (char) input_char) != NULL)) { mode_figs = true; if (mutation == ita1 || mutation == murray) { if (queue == letter_shift) queue = '\0'; put_byte(figure_shift, subtask); } else put_byte(figure_shift, subtask); } /* Empty queue */ if (queue != '\0') { put_byte(queue, subtask); queue = '\0'; } if (mutation == ita1) { /* Recode individual characters */ if (!mode_figs) { switch (input_char) { /* Characters in the letter mode */ case 'A': put_byte(0x1E, subtask); break; case 'B': put_byte(0x13, subtask); break; case 'C': put_byte(0x12, subtask); break; case 'D': put_byte(0x10, subtask); break; case 'E': put_byte(0x1D, subtask); break; case 'F': put_byte(0x11, subtask); break; case 'G': put_byte(0x15, subtask); break; case 'H': put_byte(0x14, subtask); break; case 'I': put_byte(0x19, subtask); break; case 'J': put_byte(0x16, subtask); break; case 'K': put_byte(0x06, subtask); break; case 'L': put_byte(0x04, subtask); break; case 'M': put_byte(0x05, subtask); break; case 'N': put_byte(0x01, subtask); break; case 'O': put_byte(0x18, subtask); break; case 'P': put_byte(0x00, subtask); break; case 'Q': put_byte(0x02, subtask); break; case 'R': put_byte(0x03, subtask); break; case 'S': put_byte(0x0B, subtask); break; case 'T': put_byte(0x0A, subtask); break; case 'U': put_byte(0x1A, subtask); break; case 'V': put_byte(0x08, subtask); break; case 'W': put_byte(0x09, subtask); break; case 'X': put_byte(0x0D, subtask); break; case 'Y': put_byte(0x1B, subtask); break; case 'Z': put_byte(0x0C, subtask); break; case 0x0D: put_byte(0x1C, subtask); break; case 0x0A: put_byte(0x0E, subtask); break; case ' ': queue = letter_shift; break; /* letter space */ default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } else { switch (input_char) { /* Characters in the figure mode, custom characters not here. */ case '1': put_byte(0x1E, subtask); break; case '8': put_byte(0x13, subtask); break; case '9': put_byte(0x12, subtask); break; case '0': put_byte(0x10, subtask); break; case '2': put_byte(0x1D, subtask); break; case '7': put_byte(0x15, subtask); break; case '+': put_byte(0x14, subtask); break; case '6': put_byte(0x16, subtask); break; case '(': put_byte(0x06, subtask); break; case '-': put_byte(0x04, subtask); break; case ')': put_byte(0x05, subtask); break; case '5': put_byte(0x18, subtask); break; case '%': put_byte(0x00, subtask); break; case '/': put_byte(0x02, subtask); break; /* FIXME: case '-': put_byte(0x03, subtask); break; */ case '.': put_byte(0x0B, subtask); break; case '4': put_byte(0x1A, subtask); break; case '\'': put_byte(0x08, subtask); break; case '?': put_byte(0x09, subtask); break; case ',': put_byte(0x0D, subtask); break; case '3': put_byte(0x1B, subtask); break; case ':': put_byte(0x0C, subtask); break; case 0x0D: put_byte(0x1C, subtask); break; case 0x0A: put_byte(0x0E, subtask); break; case ' ': queue = figure_shift; break; /* figure space */ default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } } else if (mutation == murray) { /* Recode individual characters */ if (!mode_figs) { switch (input_char) { /* Characters in the letter mode */ case 0x00: put_byte(0x00, subtask); break; case 'A': put_byte(0x03, subtask); break; case 'B': put_byte(0x19, subtask); break; case 'C': put_byte(0x0E, subtask); break; case 'D': put_byte(0x09, subtask); break; case 'E': put_byte(0x01, subtask); break; case 'F': put_byte(0x0D, subtask); break; case 'G': put_byte(0x1A, subtask); break; case 'H': put_byte(0x14, subtask); break; case 'I': put_byte(0x06, subtask); break; case 'J': put_byte(0x0B, subtask); break; case 'K': put_byte(0x0F, subtask); break; case 'L': put_byte(0x12, subtask); break; case 'M': put_byte(0x1C, subtask); break; case 'N': put_byte(0x0C, subtask); break; case 'O': put_byte(0x18, subtask); break; case 'P': put_byte(0x16, subtask); break; case 'Q': put_byte(0x17, subtask); break; case 'R': put_byte(0x0A, subtask); break; case 'S': put_byte(0x05, subtask); break; case 'T': put_byte(0x10, subtask); break; case 'U': put_byte(0x07, subtask); break; case 'V': put_byte(0x1E, subtask); break; case 'W': put_byte(0x13, subtask); break; case 'X': put_byte(0x1D, subtask); break; case 'Y': put_byte(0x15, subtask); break; case 'Z': put_byte(0x11, subtask); break; case 0x0D: put_byte(0x08, subtask); break; case 0x0A: put_byte(0x02, subtask); break; case 0x7F: put_byte(0x1F, subtask); break; case ' ': queue = letter_shift; break; /* letter space */ default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } else { switch (input_char) { /* Characters in the figure mode, custom characters not here. */ case 0x00: put_byte(0x00, subtask); break; case '3': put_byte(0x01, subtask); break; case '\'': put_byte(0x05, subtask); break; case '8': put_byte(0x06, subtask); break; case '7': put_byte(0x07, subtask); break; case '4': put_byte(0x0A, subtask); break; case '-': put_byte(0x0C, subtask); break; case '(': put_byte(0x0E, subtask); break; case '5': put_byte(0x10, subtask); break; case '.': put_byte(0x11, subtask); break; case '/': put_byte(0x12, subtask); break; case '2': put_byte(0x13, subtask); break; case '6': put_byte(0x15, subtask); break; case '0': put_byte(0x16, subtask); break; case '1': put_byte(0x17, subtask); break; case '9': put_byte(0x18, subtask); break; case '?': put_byte(0x19, subtask); break; case ',': put_byte(0x1C, subtask); break; case ')': put_byte(0x1E, subtask); break; case 0x0D: put_byte(0x08, subtask); break; case 0x0A: put_byte(0x02, subtask); break; case 0x7F: put_byte(0x1F, subtask); break; case ' ': queue = figure_shift; break; /* figure space */ default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } } else /* mutation == ita2 || mutation == us_tty */ { /* Recode individual characters */ if (!mode_figs) { switch (input_char) { /* Characters in the letter mode */ case 0x00: put_byte(0x00, subtask); break; case 'A': put_byte(0x03, subtask); break; case 'B': put_byte(0x19, subtask); break; case 'C': put_byte(0x0E, subtask); break; case 'D': put_byte(0x09, subtask); break; case 'E': put_byte(0x01, subtask); break; case 'F': put_byte(0x0D, subtask); break; case 'G': put_byte(0x1A, subtask); break; case 'H': put_byte(0x14, subtask); break; case 'I': put_byte(0x06, subtask); break; case 'J': put_byte(0x0B, subtask); break; case 'K': put_byte(0x0F, subtask); break; case 'L': put_byte(0x12, subtask); break; case 'M': put_byte(0x1C, subtask); break; case 'N': put_byte(0x0C, subtask); break; case 'O': put_byte(0x18, subtask); break; case 'P': put_byte(0x16, subtask); break; case 'Q': put_byte(0x17, subtask); break; case 'R': put_byte(0x0A, subtask); break; case 'S': put_byte(0x05, subtask); break; case 'T': put_byte(0x10, subtask); break; case 'U': put_byte(0x07, subtask); break; case 'V': put_byte(0x1E, subtask); break; case 'W': put_byte(0x13, subtask); break; case 'X': put_byte(0x1D, subtask); break; case 'Y': put_byte(0x15, subtask); break; case 'Z': put_byte(0x11, subtask); break; case 0x0D: put_byte(0x08, subtask); break; case 0x0A: put_byte(0x02, subtask); break; case ' ': put_byte(0x04, subtask); break; default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } else { switch (input_char) { /* Characters in the figure mode */ case 0x00: put_byte(0x00, subtask); break; case '-': put_byte(0x03, subtask); break; case '?': put_byte(0x19, subtask); break; case ':': put_byte(0x0E, subtask); break; case '$': if (mutation == us_tty) put_byte(0x09, subtask); else RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; case '3': put_byte(0x01, subtask); break; case '!': if (mutation == us_tty) put_byte(0x0D, subtask); else RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; case '&': if (mutation == us_tty) put_byte(0x1A, subtask); else RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; case '#': if (mutation == us_tty) put_byte(0x14, subtask); else RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; case '8': put_byte(0x06, subtask); break; case '\a': if (mutation == us_tty) put_byte(0x05, subtask); else put_byte(0x0B, subtask); break; case '(': put_byte(0x0F, subtask); break; case ')': put_byte(0x12, subtask); break; case '.': put_byte(0x1C, subtask); break; case ',': put_byte(0x0C, subtask); break; case '9': put_byte(0x18, subtask); break; case '0': put_byte(0x16, subtask); break; case '1': put_byte(0x17, subtask); break; case '4': put_byte(0x0A, subtask); break; case '\'': if (mutation == us_tty) put_byte(0x0B, subtask); else put_byte(0x05, subtask); break; case '5': put_byte(0x10, subtask); break; case '7': put_byte(0x07, subtask); break; case ';': put_byte(0x1E, subtask); break; case '2': put_byte(0x13, subtask); break; case '/': put_byte(0x1D, subtask); break; case '6': put_byte(0x15, subtask); break; case '+': if (mutation == ita2) put_byte(0x11, subtask); else RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; case '\"': if (mutation == us_tty) put_byte(0x11, subtask); else RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; case 0x0D: put_byte(0x08, subtask); break; case 0x0A: put_byte(0x02, subtask); break; case ' ': put_byte(0x04, subtask); break; default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } } } } static bool transform_baudot_ucs2 (RECODE_SUBTASK subtask) { int input_char; bool mode_figs = false; input_char = get_byte (subtask); if (input_char != EOF) put_ucs2 (BYTE_ORDER_MARK, subtask); /* FIXME: experimental */ while (input_char != EOF) { /* Detect switching */ if (input_char == letter_shift) { mode_figs = false; if (mutation == ita1 || mutation == murray) put_ucs2(' ', subtask); } else if (input_char == figure_shift) { mode_figs = true; if (mutation == ita1 || mutation == murray) put_ucs2(' ', subtask); } /* Convert... */ else if (mutation == ita1) { /* Recode individual characters */ if (!mode_figs) { switch (input_char) { /* Characters in the letter mode */ case 0x1E: put_ucs2('A', subtask); break; case 0x13: put_ucs2('B', subtask); break; case 0x12: put_ucs2('C', subtask); break; case 0x10: put_ucs2('D', subtask); break; case 0x1D: put_ucs2('E', subtask); break; case 0x11: put_ucs2('F', subtask); break; case 0x15: put_ucs2('G', subtask); break; case 0x14: put_ucs2('H', subtask); break; case 0x19: put_ucs2('I', subtask); break; case 0x16: put_ucs2('J', subtask); break; case 0x06: put_ucs2('K', subtask); break; case 0x04: put_ucs2('L', subtask); break; case 0x05: put_ucs2('M', subtask); break; case 0x01: put_ucs2('N', subtask); break; case 0x18: put_ucs2('O', subtask); break; case 0x00: put_ucs2('P', subtask); break; case 0x02: put_ucs2('Q', subtask); break; case 0x03: put_ucs2('R', subtask); break; case 0x0B: put_ucs2('S', subtask); break; case 0x0A: put_ucs2('T', subtask); break; case 0x1A: put_ucs2('U', subtask); break; case 0x08: put_ucs2('V', subtask); break; case 0x09: put_ucs2('W', subtask); break; case 0x0D: put_ucs2('X', subtask); break; case 0x1B: put_ucs2('Y', subtask); break; case 0x0C: put_ucs2('Z', subtask); break; case 0x1C: put_ucs2(0x0D, subtask); break; case 0x0E: put_ucs2(0x0A, subtask); break; default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } else { switch (input_char) { /* Characters in the figure mode, custom characters not here. */ case 0x1E: put_ucs2('1', subtask); break; case 0x13: put_ucs2('8', subtask); break; case 0x12: put_ucs2('9', subtask); break; case 0x10: put_ucs2('0', subtask); break; case 0x1D: put_ucs2('2', subtask); break; case 0x15: put_ucs2('7', subtask); break; case 0x14: put_ucs2('+', subtask); break; case 0x16: put_ucs2('6', subtask); break; case 0x06: put_ucs2('(', subtask); break; case 0x04: put_ucs2('-', subtask); break; case 0x05: put_ucs2(')', subtask); break; case 0x18: put_ucs2('5', subtask); break; case 0x00: put_ucs2('%', subtask); break; case 0x02: put_ucs2('/', subtask); break; case 0x03: put_ucs2('-', subtask); break; case 0x0B: put_ucs2('.', subtask); break; case 0x1A: put_ucs2('4', subtask); break; case 0x08: put_ucs2('\'', subtask); break; case 0x09: put_ucs2('?', subtask); break; case 0x0D: put_ucs2(',', subtask); break; case 0x1B: put_ucs2('3', subtask); break; case 0x0C: put_ucs2(':', subtask); break; case 0x1C: put_ucs2(0x0D, subtask); break; case 0x0E: put_ucs2(0x0A, subtask); break; default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } } else if (mutation == murray) { /* Recode individual characters */ if (!mode_figs) { switch (input_char) { /* Characters in the letter mode */ case 0x00: put_ucs2(0x00, subtask); break; case 0x03: put_ucs2('A', subtask); break; case 0x19: put_ucs2('B', subtask); break; case 0x0E: put_ucs2('C', subtask); break; case 0x09: put_ucs2('D', subtask); break; case 0x01: put_ucs2('E', subtask); break; case 0x0D: put_ucs2('F', subtask); break; case 0x1A: put_ucs2('G', subtask); break; case 0x14: put_ucs2('H', subtask); break; case 0x06: put_ucs2('I', subtask); break; case 0x0B: put_ucs2('J', subtask); break; case 0x0F: put_ucs2('K', subtask); break; case 0x12: put_ucs2('L', subtask); break; case 0x1C: put_ucs2('M', subtask); break; case 0x0C: put_ucs2('N', subtask); break; case 0x18: put_ucs2('O', subtask); break; case 0x16: put_ucs2('P', subtask); break; case 0x17: put_ucs2('Q', subtask); break; case 0x0A: put_ucs2('R', subtask); break; case 0x05: put_ucs2('S', subtask); break; case 0x10: put_ucs2('T', subtask); break; case 0x07: put_ucs2('U', subtask); break; case 0x1E: put_ucs2('V', subtask); break; case 0x13: put_ucs2('W', subtask); break; case 0x1D: put_ucs2('X', subtask); break; case 0x15: put_ucs2('Y', subtask); break; case 0x11: put_ucs2('Z', subtask); break; case 0x08: put_ucs2(0x0D, subtask); break; case 0x02: put_ucs2(0x0A, subtask); break; case 0x1F: put_ucs2(0x7F, subtask); break; default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } else { switch (input_char) { /* Characters in the figure mode, custom characters not here. */ case 0x00: put_ucs2(0x00, subtask); break; case 0x01: put_ucs2('3', subtask); break; case 0x05: put_ucs2('\'', subtask); break; case 0x06: put_ucs2('8', subtask); break; case 0x07: put_ucs2('7', subtask); break; case 0x0A: put_ucs2('4', subtask); break; case 0x0C: put_ucs2('-', subtask); break; case 0x0E: put_ucs2('(', subtask); break; case 0x10: put_ucs2('5', subtask); break; case 0x11: put_ucs2('.', subtask); break; case 0x12: put_ucs2('/', subtask); break; case 0x13: put_ucs2('2', subtask); break; case 0x15: put_ucs2('6', subtask); break; case 0x16: put_ucs2('0', subtask); break; case 0x17: put_ucs2('1', subtask); break; case 0x18: put_ucs2('9', subtask); break; case 0x19: put_ucs2('?', subtask); break; case 0x1C: put_ucs2(',', subtask); break; case 0x1E: put_ucs2(')', subtask); break; case 0x08: put_ucs2(0x0D, subtask); break; case 0x02: put_ucs2(0x0A, subtask); break; case 0x1F: put_ucs2(0x7F, subtask); break; /* Vulgar fractions used in Murray code */ case 0x0D: put_ucs2('1', subtask); put_ucs2('/', subtask); break; case 0x09: put_ucs2('2', subtask); put_ucs2('/', subtask); break; case 0x1A: put_ucs2('3', subtask); put_ucs2('/', subtask); break; case 0x14: put_ucs2('5', subtask); put_ucs2('/', subtask); break; case 0x0B: put_ucs2('7', subtask); put_ucs2('/', subtask); break; case 0x0F: put_ucs2('9', subtask); put_ucs2('/', subtask); break; default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } } else /* mutation == ata2 || mutation == us_tty */ { if (!mode_figs) { switch (input_char) { /* Characters in the letter mode */ case 0x00: put_ucs2(0x00, subtask); break; case 0x03: put_ucs2('A', subtask); break; case 0x19: put_ucs2('B', subtask); break; case 0x0E: put_ucs2('C', subtask); break; case 0x09: put_ucs2('D', subtask); break; case 0x01: put_ucs2('E', subtask); break; case 0x0D: put_ucs2('F', subtask); break; case 0x1A: put_ucs2('G', subtask); break; case 0x14: put_ucs2('H', subtask); break; case 0x06: put_ucs2('I', subtask); break; case 0x0B: put_ucs2('J', subtask); break; case 0x0F: put_ucs2('K', subtask); break; case 0x12: put_ucs2('L', subtask); break; case 0x1C: put_ucs2('M', subtask); break; case 0x0C: put_ucs2('N', subtask); break; case 0x18: put_ucs2('O', subtask); break; case 0x16: put_ucs2('P', subtask); break; case 0x17: put_ucs2('Q', subtask); break; case 0x0A: put_ucs2('R', subtask); break; case 0x05: put_ucs2('S', subtask); break; case 0x10: put_ucs2('T', subtask); break; case 0x07: put_ucs2('U', subtask); break; case 0x1E: put_ucs2('V', subtask); break; case 0x13: put_ucs2('W', subtask); break; case 0x1D: put_ucs2('X', subtask); break; case 0x15: put_ucs2('Y', subtask); break; case 0x11: put_ucs2('Z', subtask); break; case 0x08: put_ucs2(0x0D, subtask); break; case 0x02: put_ucs2(0x0A, subtask); break; case 0x04: put_ucs2(' ', subtask); break; default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } else { switch (input_char) { /* Characters in the figure mode */ case 0x00: put_ucs2(0x00, subtask); break; case 0x03: put_ucs2('-', subtask); break; case 0x19: put_ucs2('?', subtask); break; case 0x0E: put_ucs2(':', subtask); break; case 0x09: if (mutation == us_tty) put_ucs2('$', subtask); else RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; case 0x01: put_ucs2('3', subtask); break; case 0x0D: if (mutation == us_tty) put_ucs2('!', subtask); else RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; case 0x1A: if (mutation == us_tty) put_ucs2('&', subtask); else RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; case 0x14: if (mutation == us_tty) put_ucs2('#', subtask); else RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; case 0x06: put_ucs2('8', subtask); break; case 0x0B: if (mutation == ita2) put_ucs2('\a', subtask); else put_ucs2('\'', subtask); break; case 0x0F: put_ucs2('(', subtask); break; case 0x12: put_ucs2(')', subtask); break; case 0x1C: put_ucs2('.', subtask); break; case 0x0C: put_ucs2(',', subtask); break; case 0x18: put_ucs2('9', subtask); break; case 0x16: put_ucs2('0', subtask); break; case 0x17: put_ucs2('1', subtask); break; case 0x0A: put_ucs2('4', subtask); break; case 0x05: if (mutation == ita2) put_ucs2('\'', subtask); else put_ucs2('\a', subtask); break; case 0x10: put_ucs2('5', subtask); break; case 0x07: put_ucs2('7', subtask); break; case 0x1E: put_ucs2(';', subtask); break; case 0x13: put_ucs2('2', subtask); break; case 0x1D: put_ucs2('/', subtask); break; case 0x15: put_ucs2('6', subtask); break; case 0x11: if (mutation == ita2) put_ucs2('+', subtask); else put_ucs2('\"', subtask); break; case 0x08: put_ucs2(0x0D, subtask); break; case 0x02: put_ucs2(0x0A, subtask); break; case 0x04: put_ucs2(' ', subtask); break; default: RETURN_IF_NOGO (RECODE_UNTRANSLATABLE, subtask); break; } } } input_char = get_byte (subtask); } } /* A surface for 5bit data */ static bool transform_data_5bit (RECODE_SUBTASK subtask) { bool strict = subtask->step->fallback_routine != reversibility; int character, buffer, i; int bits_in_buffer = 0; while (character = get_byte (subtask), character != EOF) { if ((character & 0xE0) && strict) RETURN_IF_NOGO (RECODE_AMBIGUOUS_OUTPUT, subtask); character = character & 0x1F; character = character << 3; /* Shift bits into the buffer one at a time */ for (i = 0; i < 5; i++) { buffer = buffer << 1; if (character & 0x80) buffer = buffer | 1; character = character << 1; bits_in_buffer++; if (bits_in_buffer == 8) { put_byte (buffer, subtask); buffer = 0; bits_in_buffer = 0; } } } /* Take care of bits left in the buffer, * shift in zeroes and write out. */ if (bits_in_buffer) { while (bits_in_buffer < 8) { buffer = buffer << 1; buffer = buffer & 0xFE; bits_in_buffer++; } put_byte(buffer, subtask); } SUBTASK_RETURN (subtask); } static bool transform_5bit_data (RECODE_SUBTASK subtask) { int character, buffer, i; int bits_in_buffer = 0; int bits_in_character = 0; while (buffer = get_byte (subtask), buffer != EOF) { bits_in_buffer = 8; while (true) { character = character << 1; if (buffer & 0x80) character = character | 1; bits_in_character++; if (bits_in_character == 5) { character = character & 0x1F; /* We don't print NULL characters */ if (character) put_byte(character, subtask); bits_in_character = 0; } buffer = buffer << 1; bits_in_buffer--; if (bits_in_buffer == 0) { /* Empty buffer - break loop and read next byte */ buffer = 0; break; } } } SUBTASK_RETURN (subtask); } /* Module declaration */ bool module_baudot (RECODE_OUTER outer) { return declare_single (outer, "ISO-10646-UCS-2", "ITA-1", outer->quality_variable_to_variable, init_ita1, transform_ucs2_baudot) && declare_single (outer, "ITA-1", "ISO-10646-UCS-2", outer->quality_variable_to_variable, init_ita1, transform_baudot_ucs2) && declare_single (outer, "ISO-10646-UCS-2", "Murray", outer->quality_variable_to_variable, init_murray, transform_ucs2_baudot) && declare_single (outer, "Murray", "ISO-10646-UCS-2", outer->quality_variable_to_variable, init_murray, transform_baudot_ucs2) && declare_single (outer, "ISO-10646-UCS-2", "ITA-2", outer->quality_variable_to_variable, init_ita2, transform_ucs2_baudot) && declare_single (outer, "ITA-2", "ISO-10646-UCS-2", outer->quality_variable_to_variable, init_ita2, transform_baudot_ucs2) && declare_single (outer, "ISO-10646-UCS-2", "US-TTY", outer->quality_variable_to_variable, init_us_tty, transform_ucs2_baudot) && declare_single (outer, "US-TTY", "ISO-10646-UCS-2", outer->quality_variable_to_variable, init_us_tty, transform_baudot_ucs2) && declare_single (outer, "5bit", "data", outer->quality_variable_to_variable, NULL, transform_5bit_data) && declare_single (outer, "data", "5bit", outer->quality_variable_to_variable, NULL, transform_data_5bit) && declare_alias (outer, "Baudot", "ITA-2") && declare_alias (outer, "Teletype", "ITA-2") && declare_alias (outer, "US_Teletype", "US-TTY"); } void delmodule_baudot (RECODE_OUTER outer) { }