1 /*
2  21.04.2016 18:13 - Проверка ИНН на корректность
3  31.05.2014 7:36:58
4  Add x64
5  Repair LTrim and RTrim
6  */
7 /*
8  ё - 184  0451  d1-91
9  Ё - 168  0401  d0-81
10  » -      00BB
11  « -      00AB
12  */
13 module asc1251;
14 
15 import std.ascii;
16 import std.conv;
17 import std.utf;
18 
19 
20 bool isDigit1251(char c) pure nothrow {
21 	return (mm1251[c] & tDigit) != 0;
22 }
23 
24 bool isLower1251E(char c) pure nothrow {
25 	return (mm1251[c] & tEl) != 0;
26 }
27 
28 bool isUpper1251E(char c) pure nothrow {
29 	return (mm1251[c] & tEu) != 0;
30 }
31 
32 bool isLower1251R(char c) pure nothrow {
33 	return (mm1251[c] & tRl) != 0;
34 }
35 
36 bool isUpper1251R(char c) pure nothrow {
37 	return (mm1251[c] & tRu) != 0;
38 }
39 
40 bool isLetters1251E(char c) pure nothrow {
41 	return (mm1251[c] & (tEu + tEl)) != 0;
42 }
43 
44 bool isLetters1251R(char c) pure nothrow {
45 	return (mm1251[c] & (tRu + tRl)) != 0;
46 }
47 
48 bool isLetters1251(char c) pure nothrow {
49 	return (mm1251[c] & (tRu + tRl + tEu + tEl)) != 0;
50 }
51 
52 bool isPrintLetters1251(char c) pure nothrow {
53 	return (mm1251[c] & (tPrint)) != 0;
54 }
55 
56 unittest {
57 	foreach (char c; "0123456789")
58 		assert(asc1251.isDigit1251(c));
59 	foreach (char c; lowercase)
60 		assert(asc1251.isLower1251E(c));
61 	foreach (char c; uppercase)
62 		assert(asc1251.isUpper1251E(c));
63 	foreach (char c; lowercase1251R)
64 		assert(asc1251.isLower1251R(c));
65 	foreach (char c; uppercase1251R)
66 		assert(asc1251.isUpper1251R(c));
67 
68 	foreach (char c; uppercase ~ lowercase)
69 		assert(asc1251.isLetters1251E(c));
70 	foreach (char c; uppercase1251R ~ lowercase1251R)
71 		assert(asc1251.isLetters1251R(c));
72 
73 }
74 
75 char[] LTrim1251(char[] str) {
76 	char[] rez;
77 	if (str.length == 0)
78 		return rez;
79 	for (auto i = 0; i < str.length; i++) {
80 		if (!isPrintLetters1251(str[i]))
81 			continue;
82 		rez = str[i .. $];
83 		break;
84 	}
85 	return rez;
86 }
87 
88 char[] RTrim1251(char[] str) {
89 	char[] rez;
90 	if (str.length == 0)
91 		return rez;
92 	for (auto i = str.length; i != 0; i--) {
93 		if (!isPrintLetters1251(str[i - 1]))
94 			continue;
95 		rez = str[0 .. i];
96 		break;
97 	}
98 	return rez;
99 }
100 
101 char[] Trim1251(char[] str) {
102 	return LTrim1251(RTrim1251(str));
103 }
104 
105 unittest {
106 	assert(LTrim1251(cast(char[]) "") == cast(char[]) "");
107 	assert(RTrim1251(cast(char[]) "") == cast(char[]) "");
108 	assert(LTrim1251(cast(char[]) "   Hello  ") == cast(char[]) "Hello  ");
109 	assert(RTrim1251(cast(char[]) "   Hello  ") == cast(char[]) "   Hello");
110 	assert(LTrim1251(cast(char[]) "   " ~ uppercase1251R) == cast(char[]) uppercase1251R);
111 	assert(LTrim1251(cast(char[]) "   " ~ lowercase1251R) == cast(char[]) lowercase1251R);
112 	assert(RTrim1251(lowercase1251R ~ cast(char[]) "   ") == cast(char[]) lowercase1251R);
113 	assert(Trim1251(cast(char[]) "   " ~ "1234567890" ~ "\x0E\x0F") == cast(char[]) "1234567890");
114 	assert(LTrim1251(cast(char[]) " " ~ cast(char[]) "1") == cast(char[]) "1");
115 }
116 
117 char toUpper1251(char c) {
118 	return isLower1251E(c) | isLower1251R(c) ? cast(char)(c - 32) : c;
119 }
120 
121 char[] toUpper1251(char[] str) {
122 	char[] rez;
123 	foreach (char c; str) {
124 		rez ~= toUpper1251(c);
125 	}
126 	return rez;
127 }
128 
129 char toLower1251(char c) {
130 	return isUpper1251E(c) | isUpper1251R(c) ? cast(char)(c + 32) : c;
131 }
132 
133 char[] toLower1251(char[] str) {
134 	char[] rez;
135 	foreach (char c; str) {
136 		rez ~= toLower1251(c);
137 	}
138 	return rez;
139 }
140 
141 char[] toFio1251(char[] str) {
142 	if (str.length == 0) {
143 		return str;
144 	} else {
145 		if (str.length == 1) {
146 			char[] rez;
147 			return rez ~= toUpper1251(str[0]);
148 		} else {
149 			return toUpper1251(str[0]) ~ toLower1251(str[1 .. $]);
150 		}
151 	}
152 }
153 
154 unittest {
155 	assert(toUpper1251('a') == 'A');
156 	foreach (char c; lowercase)
157 		assert(toUpper1251(c) == std.ascii.toUpper(c));
158 	foreach (char c; lowercase1251R)
159 		assert(toUpper1251(c) == uppercase1251R[c - 224]);
160 	assert(toUpper1251(cast(char[]) "hello[23]") == "HELLO[23]");
161 	assert(toUpper1251(cast(char[]) "") == "");
162 	assert(toLower1251(cast(char[]) "17(HELLO)") == "17(hello)");
163 	assert(toFio1251(cast(char[]) "HELLO!!!") == "Hello!!!");
164 	assert(toFio1251(cast(char[]) "") == "");
165 	assert(toFio1251(cast(char[]) "a") == "A");
166 }
167 
168 // Функция, возвращает подстроку используя разделитель.
169 char[] Split1251(char[] from, char rz, int poz) {
170 	char[] rez;
171 	int i, b, e, k;
172 	auto dLfrom = from.length;
173 	for (i = 0; i < dLfrom; i++) {
174 		if (from[i] == rz) {
175 			e = i;
176 			if (k == poz) {
177 				rez = from[b .. e]; // Есть начало и есть конец. Надо переписать
178 				return rez;
179 			} else {
180 				b = i + 1;
181 				k++;
182 			}
183 		}
184 	}
185 	if (poz == k)
186 		rez ~= from[b .. $];
187 	return rez;
188 }
189 
190 unittest {
191 	assert(Split1251(cast(char[]) "ABC|DEF", '|', 0) == "ABC");
192 	assert(Split1251(cast(char[]) "ABC|DEF", '|', 1) == "DEF");
193 	assert(Split1251(cast(char[]) "ABC|DEF", '|', 2) == "");
194 	assert(Split1251(cast(char[]) "ABC|DEF", '#', 2) == "");
195 	assert(Split1251(cast(char[]) "ABC|DEF", '#', 0) == "ABC|DEF");
196 }
197 // Шифрация-Дешифрация осуществляется в том же буфере в Win-1251 и AsciiZ
198 // sh  - T - шифрация, F - дешифрция
199 // str - указатель на строку
200 void shifr(bool sh, char* str) {
201 	char ch;
202 	int z;
203 
204 	if (sh) {
205 		z = -1;
206 	} else {
207 		z = +1;
208 	}
209 	for (char* i = str;; i++) {
210 		ch = *i;
211 		if (ch == 0)
212 			break;
213 		*i = cast(char)(ch + z);
214 	}
215 }
216 /* // Шифрует строки utf-8
217  // T - зашифровать, F - расшифровать
218  string shifr8(bool sh, string str) {
219  string rez; ubyte b;
220  if(str.length == 0) return rez;
221  if(sh) {
222  for(int i; i != str.length; i++) {
223  b = cast(ubyte)str[i];
224  if(b > 31) rez ~= "B" ~ (cast(char)(str[i]-1)); else rez ~= "A" ~ (cast(char)(str[i]+1));
225  }
226  }
227  else {
228  for(int i; i != str.length; i+=2) {
229  b = cast(ubyte)str[i];
230  if(b == 66) rez ~= (cast(char)(str[i+1]+1)); else rez ~= (cast(char)(str[i+1]-1));
231  }
232  }
233  return rez;
234  }
235  */
236 string shifr8(T)(bool sh, T inStr) {
237 	string rez;
238 	ubyte b;
239 	string str = cast(string) inStr;
240 	return str;
241 	if (str.length == 0)
242 		return rez;
243 	if (sh) {
244 		for (int i; i != str.length; i++) {
245 			b = cast(ubyte) str[i];
246 			if (b > 31)
247 				rez ~= "B" ~ (cast(char)(str[i] - 1));
248 			else
249 				rez ~= "A" ~ (cast(char)(str[i] + 1));
250 		}
251 	} else {
252 		for (int i; i != str.length; i += 2) {
253 			b = cast(ubyte) str[i];
254 			if (b == 66)
255 				rez ~= (cast(char)(str[i + 1] + 1));
256 			else
257 				rez ~= (cast(char)(str[i + 1] - 1));
258 		}
259 	}
260 	return rez;
261 }
262 
263 // Проверка даты вида '27.12.2014' на корректность
264 // str = '27.12.2014'
265 // Return: T - коррктная дата
266 bool TestDate1251(char[] str) {
267 	bool rez = true;
268 	char[] s;
269 	char r = '.';
270 	if (str.length != 10)
271 		return false;
272 	s = Split1251(str, r, 0);
273 	if (s.length != 2)
274 		return false;
275 	else {
276 		if (!isDigit1251(s[0]) || !isDigit1251(s[1]))
277 			return false;
278 		int day = to!int(s);
279 		if (!(day > 0 && day < 32))
280 			return false;
281 	}
282 	s = Split1251(str, r, 1);
283 	if (s.length != 2)
284 		return false;
285 	else {
286 		if (!isDigit1251(s[0]) || !isDigit1251(s[1]))
287 			return false;
288 		int mes = to!int(s);
289 		if (!(mes > 0 && mes < 13))
290 			return false;
291 	}
292 	s = Split1251(str, r, 2);
293 	if (s.length != 4)
294 		return false;
295 	else {
296 		if (!isDigit1251(s[0]) || !isDigit1251(s[1]) || !isDigit1251(s[2]) || !isDigit1251(s[3]))
297 			return false;
298 		int yar = to!int(s);
299 		if (!(yar > 1900 && yar < 3000))
300 			return false;
301 	}
302 	return rez;
303 }
304 
305 // Проверка на соответствие ФИО, 'Иванов А.Н.', 1 большая, остальные маленькие и в конце инициалы
306 bool isFioii1251(char[] str) {
307 	bool rez = true;
308 	bool b1 = true;
309 	bool b2 = true;
310 	if (str.length < 6)
311 		return false;
312 	if (!(isUpper1251E(str[0]) || isUpper1251R(str[0])))
313 		return false;
314 	if (!((str[$ - 1] == '.') && (str[$ - 3] == '.')))
315 		return false;
316 	if (!(isUpper1251E(str[$ - 2]) || isUpper1251R(str[$ - 2])))
317 		return false;
318 	if (!(isUpper1251E(str[$ - 4]) || isUpper1251R(str[$ - 4])))
319 		return false;
320 	if (!(str[$ - 5] == ' '))
321 		return false;
322 	if (str.length > 6)
323 	foreach (char c; str[1 .. $ - 6]) {
324 		if (!(isLower1251E(c) || isLower1251R(c)))
325 			return false;
326 	}
327 	return rez;
328 }
329 
330 // Проверка на соответствие ФИО, 'Иванов', 1 большая, остальные маленькие
331 bool isFio1251(char[] str) {
332 	bool rez = true;
333 	bool b1 = true;
334 	bool b2 = true;
335 	if (str.length == 0)
336 		return false;
337 	if (!(isUpper1251E(str[0]) || isUpper1251R(str[0])))
338 		return false;
339 	foreach (char c; str[1 .. $]) {
340 		if (!(isLower1251E(c) || isLower1251R(c)))
341 			return false;
342 	}
343 	return rez;
344 }
345 // Проверка на соответствие 987, целое число
346 bool isInt1251(char[] str) {
347 	bool rez = true;
348 	bool b1 = true;
349 	bool b2 = true;
350 	if (str.length == 0)
351 		return false;
352 	foreach (char c; str[0 .. $]) {
353 		if (!isDigit(c))
354 			return false;
355 	}
356 	return rez;
357 }
358 
359 unittest {
360 	assert(TestDate1251(cast(char[]) "12.10.1961") == true);
361 	assert(TestDate1251(cast(char[]) "10.10.161") == false);
362 	assert(TestDate1251(cast(char[]) "00.10.1621") == false);
363 	assert(TestDate1251(cast(char[]) "31.10.1621") == false);
364 	assert(TestDate1251(cast(char[]) "32.10.2001") == false);
365 	assert(TestDate1251(cast(char[]) "31.12.1621") == false);
366 	assert(TestDate1251(cast(char[]) "31.13.2621") == false);
367 	assert(TestDate1251(cast(char[]) "31.13.3001") == false);
368 	// ------------------
369 	assert(isFio1251(cast(char[]) "Gena") == true);
370 	assert(isFio1251(cast(char[]) "Ge na") == false);
371 	assert(isFio1251(cast(char[]) "\xC3\xE5\xED\xE0") == true);
372 	assert(isFio1251(cast(char[]) "GenA") == false);
373 	assert(isFio1251(cast(char[]) "\xC3\xE5\xED\xC0") == false);
374 }
375 
376 // Проверка правильности ИНН string[10]
377 bool tstINN(string s) {
378 	string s1;
379 	bool rez;
380 	int[10] weights = [2, 4, 10, 3, 5, 9, 4, 6, 8, 0];
381 	int summ;
382 	
383 	if((s.length == 0) || (s.length > 10) ) return rez;
384 	foreach(ch; s) {
385 		if(!isDigit1251(ch)) return rez;
386 	}
387 	import std..string: format, strip;
388 	import std.conv: to;
389 	try {
390 		s1 = format("%.10s", to!long(strip(s)));
391 	} catch {
392 		return rez;			// Ошибка конвертации
393 	}
394 	if(s1 == "0000000000") return true;
395 	// Перебор цифр и вычисление суммы
396 	for(int i; i != 9; i++) {
397 		auto digit = s1[i] - 48; 
398 		summ += digit * weights[i];
399 	}
400 	auto ost = summ % 11;
401 	if (ost > 9) ost = ost % 10;
402 	if (ost == (s1[9] - 48)) rez = true;
403 	return rez;
404 }
405 
406 unittest {
407 	assert(tstINN("") == false);
408 	assert(tstINN("0000000000") == true);
409 	assert(tstINN("0") == true);
410 	assert(tstINN("0000A00000") == false);
411 	assert(tstINN("+000000000") == false);
412 	assert(tstINN("9999999999") == false);
413 	assert(tstINN("05911013765") == false);
414 
415 	assert(tstINN("5905033450") == true);
416 	assert(tstINN("5913001268") == true);
417 	assert(tstINN("6607000556") == true);
418 	assert(tstINN("5911013765") == true);
419 }
420 
421 
422 char[] from1251toUtf8(char[] str) {
423 	char[] rez;
424 	foreach (char c1; str) {
425 		string str1 = mm1251_Utf8[c1];
426 		foreach (char c2; str1) {
427 			rez ~= c2;
428 		}
429 	}
430 	return rez;
431 }
432 
433 char[] fromUtf8to1251(char[] str) {
434 	char[] rez;
435 	int id;
436 	auto dl = str.length;
437 	if (dl == 0)
438 		return rez;
439 	// writeln("---------", str,  "----------" );
440 	for (int i;;) {
441 		id = stride(str, i);
442 		/*
443 		 if(id == 1) writeln(id, " -- ", str[i], "--@@@-- str[i]=", cast(int)(str[i]));
444 		 if(id == 2) writeln(id, " -- ", str[i], "--@@@-- str[i]=", cast(int)(str[i]), "   str[i+1]=", cast(int)(str[i+1]));
445 		 if(id == 3) writeln(id, " -- ", str[i], "--@@@-- str[i]=", cast(int)(str[i]), "   str[i+1]=", cast(int)(str[i+1]), "   str[i+2]=", cast(int)(str[i+2])     );
446 		 */
447 		if (id == 1)
448 			rez ~= str[i];
449 		if (id == 3) {
450 			if (str[i] == '\xE2') {
451 				if (str[i + 1] == '\x80') {
452 					switch (str[i + 2]) {
453 						case '\x9A':
454 							rez ~= 130;
455 							break;
456 						case '\x9E':
457 							rez ~= 132;
458 							break;
459 						case '\xA6':
460 							rez ~= 133;
461 							break;
462 						case '\xA0':
463 							rez ~= 134;
464 							break;
465 						case '\xA1':
466 							rez ~= 135;
467 							break;
468 							//                    case '\xAC': rez ~= 136; break;
469 						case '\xB0':
470 							rez ~= 137;
471 							break;
472 						case '\xB9':
473 							rez ~= 139;
474 							break;
475 						case '\x98':
476 							rez ~= 145;
477 							break;
478 						case '\x99':
479 							rez ~= 146;
480 							break;
481 						case '\x9C':
482 							rez ~= 147;
483 							break;
484 						case '\x9D':
485 							rez ~= 148;
486 							break;
487 						case '\xA2':
488 							rez ~= 149;
489 							break;
490 						case '\x93':
491 							rez ~= 150;
492 							break;
493 						case '\x94':
494 							rez ~= 151;
495 							break;
496 						case '\xBA':
497 							rez ~= 155;
498 							break;
499 						default:
500 							// writeln("-- length 3 --> no str[2] == ???");
501 							rez ~= '?';
502 							break;
503 					}
504 				} else {
505 					if (str[i + 1] == '\x82') {
506 						switch (str[i + 2]) {
507 							//                      case '\xAC': rez ~= 128; break;
508 							case '\xAC':
509 								rez ~= 136;
510 								break;
511 							default:
512 								//writeln("-- length 3 --> no str[2] == ???");
513 								rez ~= '?';
514 								break;
515 						}
516 					} else {
517 						if (str[i + 1] == '\x84') {
518 							switch (str[i + 2]) {
519 								case '\x96':
520 									rez ~= 185;
521 									break;
522 								case '\xA2':
523 									rez ~= 153;
524 									break;
525 								default:
526 									//writeln("-- length 3 --> no str[2] == ???");
527 									rez ~= '?';
528 									break;
529 							}
530 						}
531 						//writeln("-- length 3 --> no str[1] <> x80");
532 					}
533 				}
534 			} else {
535 				//writeln("-- length 3 --> no str[0] <> xE2");
536 			}
537 			//writeln("--103-- str[i]=", to!int(str[i]), "   str[i+1]=", to!int(str[i+1]), "   str[i+2]=", to!int(str[i+2])     );
538 		}
539 		if (id == 4) {
540 			/* writeln("--104--"); */
541 		}
542 		if (id == 2) {
543 			switch (str[i]) {
544 				case '\xD0':
545 					switch (str[i + 1]) {
546 
547 						case '\x86':
548 							rez ~= 178;
549 							break;
550 						case '\x87':
551 							rez ~= 175;
552 							break;
553 						case '\x84':
554 							rez ~= 170;
555 							break;
556 						case '\x88':
557 							rez ~= 163;
558 							break;
559 						case '\x8E':
560 							rez ~= 161;
561 							break;
562 						case '\x8F':
563 							rez ~= 143;
564 							break;
565 						case '\x8B':
566 							rez ~= 142;
567 							break;
568 						case '\x8C':
569 							rez ~= 141;
570 							break;
571 						case '\x8A':
572 							rez ~= 140;
573 							break;
574 						case '\x89':
575 							rez ~= 138;
576 							break;
577 						case '\x81':
578 							rez ~= 168;
579 							break;
580 						case '\x82':
581 							rez ~= 128;
582 							break;
583 						case '\x83':
584 							rez ~= 129;
585 							break;
586 						case '\x85':
587 							rez ~= 189;
588 							break;
589 						case '\x90':
590 							rez ~= 192;
591 							break;
592 						case '\x91':
593 							rez ~= 193;
594 							break;
595 						case '\x92':
596 							rez ~= 194;
597 							break;
598 						case '\x93':
599 							rez ~= 195;
600 							break;
601 						case '\x94':
602 							rez ~= 196;
603 							break;
604 						case '\x95':
605 							rez ~= 197;
606 							break;
607 						case '\x96':
608 							rez ~= 198;
609 							break;
610 						case '\x97':
611 							rez ~= 199;
612 							break;
613 						case '\x98':
614 							rez ~= 200;
615 							break;
616 						case '\x99':
617 							rez ~= 201;
618 							break;
619 						case '\x9A':
620 							rez ~= 202;
621 							break;
622 						case '\x9B':
623 							rez ~= 203;
624 							break;
625 						case '\x9C':
626 							rez ~= 204;
627 							break;
628 						case '\x9D':
629 							rez ~= 205;
630 							break;
631 						case '\x9E':
632 							rez ~= 206;
633 							break;
634 						case '\x9F':
635 							rez ~= 207;
636 							break;
637 						case '\xA0':
638 							rez ~= 208;
639 							break;
640 						case '\xA1':
641 							rez ~= 209;
642 							break;
643 						case '\xA2':
644 							rez ~= 210;
645 							break;
646 						case '\xA3':
647 							rez ~= 211;
648 							break;
649 						case '\xA4':
650 							rez ~= 212;
651 							break;
652 						case '\xA5':
653 							rez ~= 213;
654 							break;
655 						case '\xA6':
656 							rez ~= 214;
657 							break;
658 						case '\xA7':
659 							rez ~= 215;
660 							break;
661 						case '\xA8':
662 							rez ~= 216;
663 							break;
664 						case '\xA9':
665 							rez ~= 217;
666 							break;
667 						case '\xAA':
668 							rez ~= 218;
669 							break;
670 						case '\xAB':
671 							rez ~= 219;
672 							break;
673 						case '\xAC':
674 							rez ~= 220;
675 							break;
676 						case '\xAD':
677 							rez ~= 221;
678 							break;
679 						case '\xAE':
680 							rez ~= 222;
681 							break;
682 						case '\xAF':
683 							rez ~= 223;
684 							break;
685 						case '\xB0':
686 							rez ~= 224;
687 							break;
688 						case '\xB1':
689 							rez ~= 225;
690 							break;
691 						case '\xB2':
692 							rez ~= 226;
693 							break;
694 						case '\xB3':
695 							rez ~= 227;
696 							break;
697 						case '\xB4':
698 							rez ~= 228;
699 							break;
700 						case '\xB5':
701 							rez ~= 229;
702 							break;
703 						case '\xB6':
704 							rez ~= 230;
705 							break;
706 						case '\xB7':
707 							rez ~= 231;
708 							break;
709 						case '\xB8':
710 							rez ~= 232;
711 							break;
712 						case '\xB9':
713 							rez ~= 233;
714 							break;
715 						case '\xBA':
716 							rez ~= 234;
717 							break;
718 						case '\xBB':
719 							rez ~= 235;
720 							break;
721 						case '\xBC':
722 							rez ~= 236;
723 							break;
724 						case '\xBD':
725 							rez ~= 237;
726 							break;
727 						case '\xBE':
728 							rez ~= 238;
729 							break;
730 						case '\xBF':
731 							rez ~= 239;
732 							break;
733 						default:
734 							// writeln("--10--");
735 							rez ~= '?';
736 							break;
737 					}
738 					break;
739 				case '\xD1':
740 					switch (str[i + 1]) {
741 						case '\x97':
742 							rez ~= 191;
743 							break;
744 						case '\x95':
745 							rez ~= 190;
746 							break;
747 						case '\x98':
748 							rez ~= 188;
749 							break;
750 						case '\x94':
751 							rez ~= 186;
752 							break;
753 						case '\x96':
754 							rez ~= 179;
755 							break;
756 						case '\x9E':
757 							rez ~= 162;
758 							break;
759 						case '\x9F':
760 							rez ~= 159;
761 							break;
762 						case '\x9B':
763 							rez ~= 158;
764 							break;
765 						case '\x9C':
766 							rez ~= 157;
767 							break;
768 						case '\x9A':
769 							rez ~= 156;
770 							break;
771 						case '\x99':
772 							rez ~= 154;
773 							break;
774 						case '\x91':
775 							rez ~= 184;
776 							break;
777 						case '\x93':
778 							rez ~= 131;
779 							break;
780 						case '\x92':
781 							rez ~= 144;
782 							break;
783 						case '\x80':
784 							rez ~= 240;
785 							break;
786 						case '\x81':
787 							rez ~= 241;
788 							break;
789 						case '\x82':
790 							rez ~= 242;
791 							break;
792 						case '\x83':
793 							rez ~= 243;
794 							break;
795 						case '\x84':
796 							rez ~= 244;
797 							break;
798 						case '\x85':
799 							rez ~= 245;
800 							break;
801 						case '\x86':
802 							rez ~= 246;
803 							break;
804 						case '\x87':
805 							rez ~= 247;
806 							break;
807 						case '\x88':
808 							rez ~= 248;
809 							break;
810 						case '\x89':
811 							rez ~= 249;
812 							break;
813 						case '\x8A':
814 							rez ~= 250;
815 							break;
816 						case '\x8B':
817 							rez ~= 251;
818 							break;
819 						case '\x8C':
820 							rez ~= 252;
821 							break;
822 						case '\x8D':
823 							rez ~= 253;
824 							break;
825 						case '\x8E':
826 							rez ~= 254;
827 							break;
828 						case '\x8F':
829 							rez ~= 255;
830 							break;
831 						case '\xA2':
832 							rez ~= 210;
833 							break;
834 						case '\xA3':
835 							rez ~= 211;
836 							break;
837 						case '\xA4':
838 							rez ~= 212;
839 							break;
840 						case '\xA5':
841 							rez ~= 213;
842 							break;
843 						case '\xA6':
844 							rez ~= 214;
845 							break;
846 						case '\xA7':
847 							rez ~= 215;
848 							break;
849 						case '\xA8':
850 							rez ~= 216;
851 							break;
852 						case '\xA9':
853 							rez ~= 217;
854 							break;
855 						case '\xAA':
856 							rez ~= 218;
857 							break;
858 						case '\xAB':
859 							rez ~= 219;
860 							break;
861 						case '\xAC':
862 							rez ~= 220;
863 							break;
864 						case '\xAD':
865 							rez ~= 221;
866 							break;
867 						case '\xAE':
868 							rez ~= 222;
869 							break;
870 						case '\xAF':
871 							rez ~= 223;
872 							break;
873 						case '\xB0':
874 							rez ~= 224;
875 							break;
876 						case '\xB1':
877 							rez ~= 225;
878 							break;
879 						case '\xB2':
880 							rez ~= 226;
881 							break;
882 						case '\xB3':
883 							rez ~= 227;
884 							break;
885 						case '\xB4':
886 							rez ~= 228;
887 							break;
888 						case '\xB5':
889 							rez ~= 229;
890 							break;
891 						case '\xB6':
892 							rez ~= 230;
893 							break;
894 						case '\xB7':
895 							rez ~= 231;
896 							break;
897 						case '\xB8':
898 							rez ~= 232;
899 							break;
900 						case '\xB9':
901 							rez ~= 233;
902 							break;
903 						case '\xBA':
904 							rez ~= 234;
905 							break;
906 						case '\xBB':
907 							rez ~= 235;
908 							break;
909 						case '\xBC':
910 							rez ~= 236;
911 							break;
912 						case '\xBD':
913 							rez ~= 237;
914 							break;
915 						default:
916 							// writeln("--0--");
917 							// writeln("--0-- str[i]=", to!int(str[i]), "   str[i+1]=", to!int(str[i+1]), "   str[i+2]=", to!int(str[i+2])     );
918 							rez ~= '2';
919 							break;
920 					}
921 					break;
922 				case '\xD2':
923 					switch (str[i + 1]) {
924 						case '\x91':
925 							rez ~= 180;
926 							break;
927 						case '\x90':
928 							rez ~= 165;
929 							break;
930 						default:
931 							rez ~= '7';
932 							break;
933 					}
934 					break;
935 				case '\xD3':
936 					//writeln("--2--");
937 					break;
938 				case '\xC2':
939 					switch (str[i + 1]) {
940 						case '\x98':
941 							rez ~= 152;
942 							break;
943 						case '\xA0':
944 							rez ~= 160;
945 							break;
946 						case '\xA4':
947 							rez ~= 164;
948 							break;
949 						case '\xA6':
950 							rez ~= 166;
951 							break;
952 						case '\xA7':
953 							rez ~= 167;
954 							break;
955 						case '\xA9':
956 							rez ~= 169;
957 							break;
958 						case '\xAC':
959 							rez ~= 172;
960 							break;
961 						case '\xAD':
962 							rez ~= 173;
963 							break;
964 						case '\xAE':
965 							rez ~= 174;
966 							break;
967 						case '\xB0':
968 							rez ~= 176;
969 							break;
970 						case '\xB1':
971 							rez ~= 177;
972 							break;
973 						case '\xB5':
974 							rez ~= 181;
975 							break;
976 						case '\xB6':
977 							rez ~= 182;
978 							break;
979 						case '\xB7':
980 							rez ~= 183;
981 							break;
982 						case '\xBB':
983 							rez ~= 187;
984 							break;
985 						case '\xAB':
986 							rez ~= 171;
987 							break;
988 						default:
989 							//writeln("--3--");
990 							rez ~= '3';
991 							break;
992 					}
993 					break;
994 				default:
995 					//writeln("--4--");
996 					rez ~= '4';
997 					break;
998 			}
999 		}
1000 		i = i + id;
1001 		if (i >= dl)
1002 			break;
1003 	}
1004 	return rez;
1005 }
1006 
1007 unittest {
1008 	assert(from1251toUtf8(cast(char[]) "\xC3\xE5\xED\xE0") == "Гена");
1009 	assert(from1251toUtf8(cast(char[]) "Gena123") == "Gena123");
1010 
1011 	assert(fromUtf8to1251(cast(char[]) "Гена") == "\xC3\xE5\xED\xE0");
1012 	assert(fromUtf8to1251(cast(char[]) "Gena123") == "Gena123");
1013 
1014 }
1015 
1016 char[] from1251to866(char[] str) {
1017 	char[] rez; foreach (ch; str) rez ~= _1251_866[ch];
1018 	return rez;
1019 }
1020 
1021 string toCON(T)(T s) {
1022 	version (Windows) {
1023 		return to!string(from1251to866(fromUtf8to1251(cast(char[]) s)));
1024 		// char[] zz = [ 'A', 'B', 'C' ];
1025 		// return to!string(zz);
1026 	}
1027 	version (linux) {
1028 		return cast(string)s;
1029 	}
1030 }
1031 string char1251toUtf8(char ch) {
1032 	return mm1251_Utf8[ch];
1033 }
1034 
1035 private:
1036 
1037 const int sByte = ubyte.max + 1;
1038 
1039 const tBad = 0; // Бяка
1040 const tDigit = 1; // Цифра
1041 const tEl = 2; // Анг Маленькие
1042 const tEu = 4; // Анг Большие
1043 const tPrint = 8; // Печатные
1044 const tRl = 16; // Рус Маленькие
1045 const tRu = 32; // Рус Большие
1046 
1047 private immutable char[][sByte]  mm1251_Utf8= [
1048 	/* 0 */
1049 	"\x00", /* 1 */ "\x01", /* 2 */ "\x02", /* 3 */ "\x03", /* 4 */ "\x04",/* 5 */
1050 	"\x05", /* 6 */ "\x06", /* 7 */ "\x07", /* 8 */ "\x08", /* 9 */ "\x09",/* 10 */
1051 	"\x0A", /* 11 */ "\x0B", /* 12 */ "\x0C", /* 13 */ "\x0D", /* 14 */ "\x0E",/* 15 */
1052 	"\x0F", /* 16 */ "\x10", /* 17 */ "\x11", /* 18 */ "\x12", /* 19 */ "\x13",/* 20 */
1053 	"\x14", /* 21 */ "\x15", /* 22 */ "\x16", /* 23 */ "\x17", /* 24 */ "\x18",/* 25 */
1054 	"\x19", /* 26 */ "\x1A", /* 27 */ "\x1B", /* 28 */ "\x1C", /* 29 */ "\x1D",/* 30 */
1055 	"\x1E", /* 31 */ "\x1F", /* 32 */ "\x20", /* 33 */ "\x21", /* 34 */ "\x22",/* 35 */
1056 	"\x23", /* 36 */ "\x24", /* 37 */ "\x25", /* 38 */ "\x26", /* 39 */ "\x27",/* 40 */
1057 	"\x28", /* 41 */ "\x29", /* 42 */ "\x2A", /* 43 */ "\x2B", /* 44 */ "\x2C",/* 45 */
1058 	"\x2D", /* 46 */ "\x2E", /* 47 */ "\x2F", /* 48 */ "\x30", /* 49 */ "\x31",/* 50 */
1059 	"\x32", /* 51 */ "\x33", /* 52 */ "\x34", /* 53 */ "\x35", /* 54 */ "\x36",/* 55 */
1060 	"\x37", /* 56 */ "\x38", /* 57 */ "\x39", /* 58 */ "\x3A", /* 59 */ "\x3B",/* 60 */
1061 	"\x3C", /* 61 */ "\x3D", /* 62 */ "\x3E", /* 63 */ "\x3F", /* 64 */ "\x40",/* 65 */
1062 	"\x41", /* 66 */ "\x42", /* 67 */ "\x43", /* 68 */ "\x44", /* 69 */ "\x45",/* 70 */
1063 	"\x46", /* 71 */ "\x47", /* 72 */ "\x48", /* 73 */ "\x49", /* 74 */ "\x4A",/* 75 */
1064 	"\x4B", /* 76 */ "\x4C", /* 77 */ "\x4D", /* 78 */ "\x4E", /* 79 */ "\x4F",/* 80 */
1065 	"\x50", /* 81 */ "\x51", /* 82 */ "\x52", /* 83 */ "\x53", /* 84 */ "\x54",/* 85 */
1066 	"\x55", /* 86 */ "\x56", /* 87 */ "\x57", /* 88 */ "\x58", /* 89 */ "\x59",/* 90 */
1067 	"\x5A", /* 91 */ "\x5B", /* 92 */ "\x5C", /* 93 */ "\x5D", /* 94 */ "\x5E",/* 95 */
1068 	"\x5F", /* 96 */ "\x60", /* 97 */ "\x61", /* 98 */ "\x62", /* 99 */ "\x63",/* 100 */
1069 	"\x64", /* 101 */ "\x65", /* 102 */ "\x66", /* 103 */ "\x67", /* 104 */ "\x68",/* 105 */
1070 	"\x69", /* 106 */ "\x6A", /* 107 */ "\x6B", /* 108 */ "\x6C", /* 109 */ "\x6D",/* 110 */
1071 	"\x6E", /* 111 */ "\x6F", /* 112 */ "\x70", /* 113 */ "\x71", /* 114 */ "\x72",/* 115 */
1072 	"\x73", /* 116 */ "\x74", /* 117 */ "\x75", /* 118 */ "\x76", /* 119 */ "\x77",/* 120 */
1073 	"\x78", /* 121 */ "\x79", /* 122 */ "\x7A", /* 123 */ "\x7B", /* 124 */ "\x7C",/* 125 */
1074 	"\x7D", /* 126 */ "\x7E", /* 127 */ "\x7F", /* 128 */ "\xD0\x82", /* 129 */ "\xD0\x83",
1075 	/* 130 */
1076 	"\xE2\x80\x9A", /* 131 */ "\xD1\x93", /* 132 */ "\xE2\x80\x9E", /* 133 */ "\xE2\x80\xA6", /* 134 */ "\xE2\x80\xA0", /* 135 */ "\xE2\x80\xA1",
1077 	/* 136 */
1078 	"\xE2\x82\xAC", /* 137 */ "\xE2\x80\xB0", /* 138 */ "\xD0\x89", /* 139 */ "\xE2\x80\xB9", /* 140 */ "\xD0\x8A", /* 141 */ "\xD0\x8C",
1079 	/* 142 */
1080 	"\xD0\x8B", /* 143 */ "\xD0\x8F", /* 144 */ "\xD1\x92", /* 145 */ "\xE2\x80\x98", /* 146 */ "\xE2\x80\x99", /* 147 */ "\xE2\x80\x9C",
1081 	/* 148 */
1082 	"\xE2\x80\x9D", /* 149 */ "\xE2\x80\xA2", /* 150 */ "\xE2\x80\x93", /* 151 */ "\xE2\x80\x94", /* 152 */ "\xC2\x98", /* 153 */ "\xE2\x84\xA2",
1083 	/* 154 */
1084 	"\xD1\x99", /* 155 */ "\xE2\x80\xBA", /* 156 */ "\xD1\x9A", /* 157 */ "\xD1\x9C", /* 158 */ "\xD1\x9B", /* 159 */ "\xD1\x9F",
1085 	/* 160 */
1086 	"\xC2\xA0", /* 161 */ "\xD0\x8E", /* 162 */ "\xD1\x9E", /* 163 */ "\xD0\x88", /* 164 */ "\xC2\xA4", /* 165 */ "\xD2\x90",
1087 	/* 166 */
1088 	"\xC2\xA6", /* 167 */ "\xC2\xA7", /* 168 */ "\xD0\x81", /* 169 */ "\xC2\xA9", /* 170 */ "\xD0\x84", /* 171 */ "\xC2\xAB",
1089 	/* 172 */
1090 	"\xC2\xAC", /* 173 */ "\xC2\xAD", /* 174 */ "\xC2\xAE", /* 175 */ "\xD0\x87", /* 176 */ "\xC2\xB0", /* 177 */ "\xC2\xB1",
1091 	/* 178 */
1092 	"\xD0\x86", /* 179 */ "\xD1\x96", /* 180 */ "\xD2\x91", /* 181 */ "\xC2\xB5", /* 182 */ "\xC2\xB6", /* 183 */ "\xC2\xB7",
1093 	/* 184 */
1094 	"\xD1\x91", /* 185 */ "\xE2\x84\x96", /* 186 */ "\xD1\x94", /* 187 */ "\xC2\xBB", /* 188 */ "\xD1\x98", /* 189 */ "\xD0\x85",
1095 	/* 190 */
1096 	"\xD1\x95", /* 191 */ "\xD1\x97", /* 192 */ "\xD0\x90", /* 193 */ "\xD0\x91",/* 194 */
1097 	"\xD0\x92", /* 195 */ "\xD0\x93", /* 196 */ "\xD0\x94", /* 197 */ "\xD0\x95",
1098 	/* 198 */
1099 	"\xD0\x96", /* 199 */ "\xD0\x97", /* 200 */ "\xD0\x98", /* 201 */ "\xD0\x99",/* 202 */
1100 	"\xD0\x9A", /* 203 */ "\xD0\x9B", /* 204 */ "\xD0\x9C", /* 205 */ "\xD0\x9D",
1101 	/* 206 */
1102 	"\xD0\x9E", /* 207 */ "\xD0\x9F", /* 208 */ "\xD0\xA0", /* 209 */ "\xD0\xA1",/* 210 */
1103 	"\xD0\xA2", /* 211 */ "\xD0\xA3", /* 212 */ "\xD0\xA4", /* 213 */ "\xD0\xA5",
1104 	/* 214 */
1105 	"\xD0\xA6", /* 215 */ "\xD0\xA7", /* 216 */ "\xD0\xA8", /* 217 */ "\xD0\xA9",/* 218 */
1106 	"\xD0\xAA", /* 219 */ "\xD0\xAB", /* 220 */ "\xD0\xAC", /* 221 */ "\xD0\xAD",
1107 	/* 222 */
1108 	"\xD0\xAE", /* 223 */ "\xD0\xAF", /* 224 */ "\xD0\xB0", /* 225 */ "\xD0\xB1",/* 226 */
1109 	"\xD0\xB2", /* 227 */ "\xD0\xB3", /* 228 */ "\xD0\xB4", /* 229 */ "\xD0\xB5",
1110 	/* 230 */
1111 	"\xD0\xB6", /* 231 */ "\xD0\xB7", /* 232 */ "\xD0\xB8", /* 233 */ "\xD0\xB9",/* 234 */
1112 	"\xD0\xBA", /* 235 */ "\xD0\xBB", /* 236 */ "\xD0\xBC", /* 237 */ "\xD0\xBD",
1113 	/* 238 */
1114 	"\xD0\xBE", /* 239 */ "\xD0\xBF", /* 240 */ "\xD1\x80", /* 241 */ "\xD1\x81",/* 242 */
1115 	"\xD1\x82", /* 243 */ "\xD1\x83", /* 244 */ "\xD1\x84", /* 245 */ "\xD1\x85",
1116 	/* 246 */
1117 	"\xD1\x86", /* 247 */ "\xD1\x87", /* 248 */ "\xD1\x88", /* 249 */ "\xD1\x89",/* 250 */
1118 	"\xD1\x8A", /* 251 */ "\xD1\x8B", /* 252 */ "\xD1\x8C", /* 253 */ "\xD1\x8D",
1119 	/* 254 */
1120 	"\xD1\x8E", /* 255 */ "\xD1\x8F"
1121 ];
1122 
1123 private immutable int[sByte]  mm1251= [/* 0 */
1124 	tBad, /* 1 */ tBad, /* 2 */ tBad, /* 3 */ tBad, /* 4 */ tBad, /* 5 */ tBad, /* 6 */ tBad, /* 7 */ tBad, /* 8 */ tBad,
1125 	/* 9 */
1126 	tBad, /* 10 */ tBad, /* 11 */ tBad, /* 12 */ tBad, /* 13 */ tBad, /* 14 */ tBad, /* 15 */ tBad, /* 16 */ tBad, /* 17 */ tBad,
1127 	/* 18 */
1128 	tBad, /* 19 */ tBad, /* 20 */ tBad, /* 21 */ tBad, /* 22 */ tBad, /* 23 */ tBad, /* 24 */ tBad, /* 25 */ tBad, /* 26 */ tBad,
1129 	/* 27 */
1130 	tBad, /* 28 */ tBad, /* 29 */ tBad, /* 30 */ tBad, /* 31 */ tBad, /* 32 */ tBad, /* 33 */ tPrint, /* 34 */ tPrint, /* 35 */ tPrint,
1131 	/* 36 */
1132 	tPrint, /* 37 */ tPrint, /* 38 */ tPrint, /* 39 */ tPrint, /* 40 */ tPrint, /* 41 */ tPrint, /* 42 */ tPrint, /* 43 */ tPrint, /* 44 */ tPrint,
1133 	/* 45 */
1134 	tPrint, /* 46 */ tPrint, /* 47 */ tPrint, /* 48 */ tPrint + tDigit, /* 49 */ tPrint + tDigit, /* 50 */ tPrint + tDigit, /* 51 */ tPrint + tDigit,
1135 	/* 52 */
1136 	tPrint + tDigit, /* 53 */ tPrint + tDigit, /* 54 */ tPrint + tDigit, /* 55 */ tPrint + tDigit,
1137 	/* 56 */
1138 	tPrint + tDigit, /* 57 */ tPrint + tDigit, /* 58 */ tPrint, /* 59 */ tPrint, /* 60 */ tPrint, /* 61 */ tPrint,
1139 	/* 62 */
1140 	tPrint, /* 63 */ tPrint, /* 64 */ tPrint,/* 65 */
1141 	tPrint + tEu, /* 66 */ tPrint + tEu, /* 67 */ tPrint + tEu, /* 68 */ tPrint + tEu, /* 69 */ tPrint + tEu, /* 70 */ tPrint + tEu,
1142 	/* 71 */
1143 	tPrint + tEu, /* 72 */ tPrint + tEu, /* 73 */ tPrint + tEu, /* 74 */ tPrint + tEu, /* 75 */ tPrint + tEu, /* 76 */ tPrint + tEu,
1144 	/* 77 */
1145 	tPrint + tEu, /* 78 */ tPrint + tEu, /* 79 */ tPrint + tEu, /* 80 */ tPrint + tEu, /* 81 */ tPrint + tEu, /* 82 */ tPrint + tEu,
1146 	/* 83 */
1147 	tPrint + tEu, /* 84 */ tPrint + tEu, /* 85 */ tPrint + tEu, /* 86 */ tPrint + tEu, /* 87 */ tPrint + tEu, /* 88 */ tPrint + tEu,
1148 	/* 89 */
1149 	tPrint + tEu, /* 90 */ tPrint + tEu,/* 91 */
1150 	tPrint, /* 92 */ tPrint, /* 93 */ tPrint, /* 94 */ tPrint, /* 95 */ tPrint,
1151 	/* 96 */
1152 	tPrint,/* 97 */
1153 	tPrint + tEl, /* 98 */ tPrint + tEl, /* 99 */ tPrint + tEl, /* 100 */ tPrint + tEl, /* 101 */ tPrint + tEl, /* 102 */ tPrint + tEl,
1154 	/* 103 */
1155 	tPrint + tEl, /* 104 */ tPrint + tEl, /* 105 */ tPrint + tEl, /* 106 */ tPrint + tEl, /* 107 */ tPrint + tEl, /* 108 */ tPrint + tEl,
1156 	/* 109 */
1157 	tPrint + tEl, /* 110 */ tPrint + tEl, /* 111 */ tPrint + tEl, /* 112 */ tPrint + tEl, /* 113 */ tPrint + tEl, /* 114 */ tPrint + tEl,
1158 	/* 115 */
1159 	tPrint + tEl, /* 116 */ tPrint + tEl, /* 117 */ tPrint + tEl, /* 118 */ tPrint + tEl, /* 119 */ tPrint + tEl, /* 120 */ tPrint + tEl,
1160 	/* 121 */
1161 	tPrint + tEl, /* 122 */ tPrint + tEl, /* 123 */ tPrint, /* 124 */ tPrint, /* 125 */ tPrint, /* 126 */ tPrint, /* 127 */ tPrint, /* 128 */ tPrint,
1162 	/* 129 */
1163 	tPrint,/* 130 */
1164 	tPrint, /* 131 */ tPrint, /* 132 */ tPrint, /* 133 */ tPrint, /* 134 */ tPrint, /* 135 */ tPrint, /* 136 */ tPrint, /* 137 */ tPrint,/* 138 */
1165 	tPrint, /* 139 */ tPrint, /* 140 */ tPrint, /* 141 */ tPrint, /* 142 */ tPrint, /* 143 */ tPrint, /* 144 */ tPrint, /* 145 */ tPrint,/* 146 */
1166 	tPrint, /* 147 */ tPrint, /* 148 */ tPrint, /* 149 */ tPrint, /* 150 */ tPrint, /* 151 */ tPrint, /* 152 */ tPrint, /* 153 */ tPrint,/* 154 */
1167 	tPrint, /* 155 */ tPrint, /* 156 */ tPrint, /* 157 */ tPrint, /* 158 */ tPrint, /* 159 */ tPrint, /* 160 */ tPrint, /* 161 */ tPrint,/* 162 */
1168 	tPrint, /* 163 */ tPrint, /* 164 */ tPrint, /* 165 */ tPrint, /* 166 */ tPrint, /* 167 */ tPrint, /* 168 */ tPrint + tRu, /* 169 */ tPrint,
1169 	/* 170 */
1170 	tPrint, /* 171 */ tPrint, /* 172 */ tPrint, /* 173 */ tPrint, /* 174 */ tPrint, /* 175 */ tPrint, /* 176 */ tPrint, /* 177 */ tPrint,/* 178 */
1171 	tPrint, /* 179 */ tPrint, /* 180 */ tPrint, /* 181 */ tPrint, /* 182 */ tPrint, /* 183 */ tPrint, /* 184 */ tPrint + tRl, /* 185 */ tPrint,
1172 	/* 186 */
1173 	tPrint, /* 187 */ tPrint, /* 188 */ tPrint, /* 189 */ tPrint, /* 190 */ tPrint, /* 191 */ tPrint, /* 192 */ tPrint + tRu,
1174 	/* 193 */
1175 	tPrint + tRu, /* 194 */ tPrint + tRu, /* 195 */ tPrint + tRu, /* 196 */ tPrint + tRu, /* 197 */ tPrint + tRu, /* 198 */ tPrint + tRu,
1176 	/* 199 */
1177 	tPrint + tRu, /* 200 */ tPrint + tRu, /* 201 */ tPrint + tRu, /* 202 */ tPrint + tRu, /* 203 */ tPrint + tRu, /* 204 */ tPrint + tRu,
1178 	/* 205 */
1179 	tPrint + tRu, /* 206 */ tPrint + tRu, /* 207 */ tPrint + tRu, /* 208 */ tPrint + tRu, /* 209 */ tPrint + tRu, /* 210 */ tPrint + tRu,
1180 	/* 211 */
1181 	tPrint + tRu, /* 212 */ tPrint + tRu, /* 213 */ tPrint + tRu, /* 214 */ tPrint + tRu, /* 215 */ tPrint + tRu, /* 216 */ tPrint + tRu,
1182 	/* 217 */
1183 	tPrint + tRu, /* 218 */ tPrint + tRu, /* 219 */ tPrint + tRu, /* 220 */ tPrint + tRu, /* 221 */ tPrint + tRu, /* 222 */ tPrint + tRu,
1184 	/* 223 */
1185 	tPrint + tRu, /* 224 */ tPrint + tRl, /* 225 */ tPrint + tRl, /* 226 */ tPrint + tRl, /* 227 */ tPrint + tRl, /* 228 */ tPrint + tRl,
1186 	/* 229 */
1187 	tPrint + tRl, /* 230 */ tPrint + tRl, /* 231 */ tPrint + tRl, /* 232 */ tPrint + tRl, /* 233 */ tPrint + tRl, /* 234 */ tPrint + tRl,
1188 	/* 235 */
1189 	tPrint + tRl, /* 236 */ tPrint + tRl, /* 237 */ tPrint + tRl, /* 238 */ tPrint + tRl, /* 239 */ tPrint + tRl, /* 240 */ tPrint + tRl,
1190 	/* 241 */
1191 	tPrint + tRl, /* 242 */ tPrint + tRl, /* 243 */ tPrint + tRl, /* 244 */ tPrint + tRl, /* 245 */ tPrint + tRl, /* 246 */ tPrint + tRl,
1192 	/* 247 */
1193 	tPrint + tRl, /* 248 */ tPrint + tRl, /* 249 */ tPrint + tRl, /* 250 */ tPrint + tRl, /* 251 */ tPrint + tRl, /* 252 */ tPrint + tRl,
1194 	/* 253 */
1195 	tPrint + tRl, /* 254 */ tPrint + tRl, /* 255 */ tPrint + tRl];
1196 
1197 // char mm1251u[sByte];
1198 private immutable uppercase1251R = "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF"; /// А..Я
1199 private immutable lowercase1251R = "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"; /// А..Я
1200 private immutable _1251_866 = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x18\x19\x1A\x1B......\x20!\x22#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.+++++++++++++++++++++++++++++++++++++++1\xF0345+++++++++++1\xF1\xFC++++++\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF";
1201 
1202 bool isAtr1251(char c, int atr) {
1203 	return (mm1251[c] & atr) != 0;
1204 }