1 /*
2 * morse.c -- morse code tables
3 *
4 * Copyright (C) 2017
5 *
6 * Fldigi is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Fldigi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with fldigi. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #include <config.h>
22 #include <cstring>
23 #include <iostream>
24
25 #include "morse.h"
26 #include "configuration.h"
27
28 /* ---------------------------------------------------------------------- */
29
30 /*
31 * Morse code characters table. This table allows lookup of the Morse
32 * shape of a given alphanumeric character. Shapes are held as a string,
33 * with "-' representing dash, and ".' representing dot. The table ends
34 * with a NULL entry.
35 *
36 * This is the main table from which the other tables are computed.
37 *
38 * The Prosigns are also defined in the configuration.h file
39 * The user can specify the character which substitutes for the prosign
40 */
41
42 bool CW_table_changed = false;
43
44 CWstruct cMorse::cw_table[] = {
45 // Prosigns
46 {1, "=", "<BT>", "-...-" }, // 0
47 {0, "~", "<AA>", ".-.-" }, // 1
48 {1, "<", "<AS>", ".-..." }, // 2
49 {1, ">", "<AR>", ".-.-." }, // 3
50 {1, "%", "<SK>", "...-.-" }, // 4
51 {1, "+", "<KN>", "-.--." }, // 5
52 {1, "&", "<INT>", "..-.-" }, // 6
53 {1, "{", "<HM>", "....--" }, // 7
54 {1, "}", "<VE>", "...-." }, // 8
55 // ASCII 7bit letters
56 {1, "A", "A", ".-" },
57 {1, "B", "B", "-..." },
58 {1, "C", "C", "-.-." },
59 {1, "D", "D", "-.." },
60 {1, "E", "E", "." },
61 {1, "F", "F", "..-." },
62 {1, "G", "G", "--." },
63 {1, "H", "H", "...." },
64 {1, "I", "I", ".." },
65 {1, "J", "J", ".---" },
66 {1, "K", "K", "-.-" },
67 {1, "L", "L", ".-.." },
68 {1, "M", "M", "--" },
69 {1, "N", "N", "-." },
70 {1, "O", "O", "---" },
71 {1, "P", "P", ".--." },
72 {1, "Q", "Q", "--.-" },
73 {1, "R", "R", ".-." },
74 {1, "S", "S", "..." },
75 {1, "T", "T", "-" },
76 {1, "U", "U", "..-" },
77 {1, "V", "V", "...-" },
78 {1, "W", "W", ".--" },
79 {1, "X", "X", "-..-" },
80 {1, "Y", "Y", "-.--" },
81 {1, "Z", "Z", "--.." },
82 //
83 {1, "a", "A", ".-" },
84 {1, "b", "B", "-..." },
85 {1, "c", "C", "-.-." },
86 {1, "d", "D", "-.." },
87 {1, "e", "E", "." },
88 {1, "f", "F", "..-." },
89 {1, "g", "G", "--." },
90 {1, "h", "H", "...." },
91 {1, "i", "I", ".." },
92 {1, "j", "J", ".---" },
93 {1, "k", "K", "-.-" },
94 {1, "l", "L", ".-.." },
95 {1, "m", "M", "--" },
96 {1, "n", "N", "-." },
97 {1, "o", "O", "---" },
98 {1, "p", "P", ".--." },
99 {1, "q", "Q", "--.-" },
100 {1, "r", "R", ".-." },
101 {1, "s", "S", "..." },
102 {1, "t", "T", "-" },
103 {1, "u", "U", "..-" },
104 {1, "v", "V", "...-" },
105 {1, "w", "W", ".--" },
106 {1, "x", "X", "-..-" },
107 {1, "y", "Y", "-.--" },
108 {1, "z", "Z", "--.." },
109 // Numerals
110 {1, "0", "0", "-----" },
111 {1, "1", "1", ".----" },
112 {1, "2", "2", "..---" },
113 {1, "3", "3", "...--" },
114 {1, "4", "4", "....-" },
115 {1, "5", "5", "....." },
116 {1, "6", "6", "-...." },
117 {1, "7", "7", "--..." },
118 {1, "8", "8", "---.." },
119 {1, "9", "9", "----." },
120 // Punctuation
121 {1, "\\", "\\", ".-..-." },
122 {1, "\'", "'", ".----." },
123 {1, "$", "$", "...-..-" },
124 {1, "(", "(", "-.--." },
125 {1, ")", ")", "-.--.-" },
126 {1, ",", ",", "--..--" },
127 {1, "-", "-", "-....-" },
128 {1, ".", ".", ".-.-.-" },
129 {1, "/", "/", "-..-." },
130 {1, ":", ":", "---..." },
131 {1, ";", ";", "-.-.-." },
132 {1, "?", "?", "..--.." },
133 {1, "_", "_", "..--.-" },
134 {1, "@", "@", ".--.-." },
135 {1, "!", "!", "-.-.--" },
136 // accented characters
137 {1, "Ä", "Ä", ".-.-" }, // A umlaut
138 {1, "ä", "Ä", ".-.-" }, // A umlaut
139 {0, "Æ", "Æ", ".-.-" }, // A aelig
140 {0, "æ", "Æ", ".-.-" }, // A aelig
141 {0, "Å", "Å", ".--.-" }, // A ring
142 {0, "å", "Å", ".--.-" }, // A ring
143 {1, "Ç", "Ç", "-.-.." }, // C cedilla
144 {1, "ç", "Ç", "-.-.." }, // C cedilla
145 {0, "È", "È", ".-..-" }, // E grave
146 {0, "è", "È", ".-..-" }, // E grave
147 {1, "É", "É", "..-.." }, // E acute
148 {1, "é", "É", "..-.." }, // E acute
149 {0, "Ó", "Ó", "---." }, // O acute
150 {0, "ó", "Ó", "---." }, // O acute
151 {1, "Ö", "Ö", "---." }, // O umlaut
152 {1, "ö", "Ö", "---." }, // O umlaut
153 {0, "Ø", "Ø", "---." }, // O slash
154 {0, "ø", "Ø", "---." }, // O slash
155 {1, "Ñ", "Ñ", "--.--" }, // N tilde
156 {1, "ñ", "Ñ", "--.--" }, // N tilde
157 {1, "Ü", "Ü", "..--" }, // U umlaut
158 {1, "ü", "Ü", "..--" }, // U umlaut
159 {0, "Û", "Û", "..--" }, // U circ
160 {0, "û", "Û", "..--" }, // U circ
161 // array termination
162 {0, "", "", ""}
163 };
164
165 /* ---------------------------------------------------------------------- */
166
enable(std::string s,bool val)167 void cMorse::enable(std::string s, bool val)
168 {
169 for (int i = 0; cw_table[i].rpr.length(); i++) {
170 if (cw_table[i].chr == s || cw_table[i].prt == s) {
171 cw_table[i].enabled = val;
172 return;
173 }
174 }
175 }
176
init()177 void cMorse::init()
178 {
179 // Update the char / prosign relationship
180 if (progdefaults.CW_prosigns.length() == 9) {
181 for (int i = 0; i < 9; i++) {
182 cw_table[i].chr = progdefaults.CW_prosigns[i];
183 }
184 }
185 enable("<AA>", 1);
186 enable("Ä", 0); enable("ä", 0);
187 enable("Æ", 0); enable("æ", 0);
188 enable("Å", 0); enable("å", 0);
189 enable("Ç", 0); enable("ç", 0);
190 enable("È", 0); enable("è", 0);
191 enable("É", 0); enable("é", 0);
192 enable("Ó", 0); enable("ó", 0);
193 enable("Ö", 0); enable("ö", 0);
194 enable("Ø", 0); enable("ø", 0);
195 enable("Ñ", 0); enable("ñ", 0);
196 enable("Ü", 0); enable("ü", 0);
197 enable("Û", 0); enable("û", 0);
198
199 if (progdefaults.A_umlaut)
200 { enable("Ä", 1); enable("ä", 1); enable("<AA>", 0); }
201 if (progdefaults.A_aelig)
202 { enable("Æ", 1); enable("æ", 1); enable("<AA>", 0); }
203 if (progdefaults.A_ring)
204 { enable("Å", 1); enable("å", 1); }
205 if (progdefaults.C_cedilla)
206 { enable("Ç", 1); enable("ç", 1); }
207 if (progdefaults.E_grave)
208 { enable("È", 1); enable("è", 1); }
209 if (progdefaults.E_acute)
210 { enable("É", 1); enable("é", 1); }
211 if (progdefaults.O_acute)
212 { enable("Ó", 1); enable("ó", 1); }
213 if (progdefaults.O_umlaut)
214 { enable("Ö", 1); enable("ö", 1); }
215 if (progdefaults.O_slash)
216 { enable("Ø", 1); enable("ø", 1); }
217 if (progdefaults.N_tilde)
218 { enable("Ñ", 1); enable("ñ", 1); }
219 if (progdefaults.U_umlaut)
220 { enable("Ü", 1); enable("ü", 1); }
221 if (progdefaults.U_circ)
222 { enable("Û", 1); enable("û", 1); }
223
224 enable ("\\", progdefaults.CW_backslash);
225 enable ("\'", progdefaults.CW_single_quote);
226 enable ("$", progdefaults.CW_dollar_sign);
227 enable ("(", progdefaults.CW_open_paren);
228 enable (")", progdefaults.CW_close_paren);
229 enable (":", progdefaults.CW_colon);
230 enable (";", progdefaults.CW_semi_colon);
231 enable ("_", progdefaults.CW_underscore);
232 enable ("@", progdefaults.CW_at_symbol);
233 enable ("!", progdefaults.CW_exclamation);
234
235 CW_table_changed = false;
236 utf8.reserve(4);
237 utf8.clear();
238 ptr = 0;
239 toprint.clear();
240 }
241
rx_lookup(std::string rx)242 std::string cMorse::rx_lookup(std::string rx)
243 {
244 if (CW_table_changed) init();
245 for (int i = 0; cw_table[i].rpr.length(); i++) {
246 if (rx == cw_table[i].rpr) {
247 if (cw_table[i].enabled) {
248 if (progdefaults.CW_prosign_display)
249 return cw_table[i].chr;
250 return cw_table[i].prt;
251 }
252 }
253 }
254 return "";
255 }
256
tx_lookup(int c)257 std::string cMorse::tx_lookup(int c)
258 {
259 if (CW_table_changed) init();
260 toprint.clear();
261
262 c &= 0xFF;
263 utf8 += c;
264 // if (ptr < 4) utf8[ptr++] = c;
265
266 // if ( c > 0x7F && ptr == 1 )
267 // return "";
268 if (((utf8[0] & 0xFF) > 0x7F) && (utf8.length() == 1)) {
269 return "";
270 }
271
272 for (int i = 0; cw_table[i].rpr.length(); i++) {
273 if (utf8 == cw_table[i].chr) {
274 if (!cw_table[i].enabled) {
275 utf8.clear();
276 ptr = 0;
277 return "";
278 }
279 toprint = cw_table[i].prt;
280 utf8.clear();
281 ptr = 0;
282 return cw_table[i].rpr;
283 }
284 }
285 utf8.clear();
286 ptr = 0;
287 return "";
288
289 }
290
tx_length(int c)291 int cMorse::tx_length(int c)
292 {
293 if (c == ' ') return 4;
294 std::string ms = tx_lookup(c);
295 if (ms.empty()) return 0;
296 int len = 0;
297 for (size_t i = 0; i < ms.length(); i++)
298 if (ms[i] == '.') len += 2;
299 else len += 4;
300 len += 2;
301 return len;
302 }
303
304
305 /* ---------------------------------------------------------------------- */
306
307