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