Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. (*
  2.     Copyright 2016, 2023 Anton Krotov
  3.  
  4.     This file is part of fb2read.
  5.  
  6.     fb2read 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.     fb2read 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 fb2read. If not, see <http://www.gnu.org/licenses/>.
  18. *)
  19.  
  20. MODULE Encoding;
  21.  
  22. IMPORT SYSTEM;
  23.  
  24.  
  25. CONST
  26.         TABLE_SIZE = 65536;
  27.  
  28.  
  29. TYPE
  30.         tUtf8* = ARRAY 4 OF CHAR;
  31.         tCodePage* = ARRAY 256 OF RECORD code*, len*: INTEGER; utf8*: tUtf8 END;
  32.  
  33.  
  34. VAR
  35.         cp1250*, cp1251*, cp1252*, cp866*: tCodePage;
  36.  
  37.         table1251: ARRAY TABLE_SIZE OF BYTE;
  38.  
  39.  
  40. PROCEDURE getUtf8Char* (VAR ptr, size: INTEGER): INTEGER;
  41. VAR
  42.         c: BYTE;
  43.         n, k, code: INTEGER;
  44.         end: BOOLEAN;
  45. BEGIN
  46.         code := 0;
  47.         end := FALSE;
  48.         REPEAT
  49.                 SYSTEM.GET(ptr, c);
  50.                 INC(ptr);
  51.                 DEC(size);
  52.                 CASE c OF
  53.                 |  0..127:
  54.                         code := c;
  55.                         end := TRUE
  56.  
  57.                 |128..191:
  58.                         code := code * 64 + c MOD 64;
  59.                         DEC(n);
  60.                         end := n <= 0
  61.  
  62.                 |192..255:
  63.                         k := LSL(c, 24);
  64.                         n := -2;
  65.                         REPEAT
  66.                                 k := ROR(k, -1);
  67.                                 INC(n)
  68.                         UNTIL k MOD 2 = 0;
  69.                         k := LSL(c, n + 25);
  70.                         code := LSR(k, n + 25)
  71.  
  72.                 END
  73.         UNTIL (size = 0) OR end
  74.         RETURN code
  75. END getUtf8Char;
  76.  
  77.  
  78. PROCEDURE convert1251* (src, dst: INTEGER; len: INTEGER);
  79. VAR
  80.         val, size: INTEGER;
  81. BEGIN
  82.         WHILE len > 0 DO
  83.                 size := 0;
  84.                 val := getUtf8Char(src, size);
  85.                 IF (0 <= val) & (val < TABLE_SIZE) THEN
  86.                         SYSTEM.PUT8(dst, table1251[val])
  87.                 ELSE
  88.                         SYSTEM.PUT8(dst, ORD("?"))
  89.                 END;
  90.                 INC(dst);
  91.                 DEC(len)
  92.         END
  93. END convert1251;
  94.  
  95.  
  96. PROCEDURE utf8* (code: INTEGER; VAR utf8char: tUtf8);
  97. BEGIN
  98.         utf8char[0] := 0X;
  99.         IF code < 80H THEN
  100.                 utf8char[0] := CHR(code);
  101.                 utf8char[1] := 0X
  102.         ELSIF code < 800H THEN
  103.                 utf8char[1] := CHR(code MOD 64 + 80H);
  104.                 utf8char[0] := CHR(code DIV 64 + 0C0H);
  105.                 utf8char[2] := 0X
  106.         ELSIF code < 10000H THEN
  107.                 utf8char[2] := CHR(code MOD 64 + 80H);
  108.                 code := code DIV 64;
  109.                 utf8char[1] := CHR(code MOD 64 + 80H);
  110.                 utf8char[0] := CHR(code DIV 64 + 0E0H);
  111.                 utf8char[3] := 0X
  112.         (*
  113.         ELSIF code < 200000H THEN
  114.         ELSIF code < 4000000H THEN
  115.         ELSE *)
  116.         END
  117. END utf8;
  118.  
  119.  
  120. PROCEDURE ucs2to1251 (code: INTEGER): BYTE;
  121. VAR
  122.         i: INTEGER;
  123. BEGIN
  124.         i := 255;
  125.         WHILE (i >= 0) & (cp1251[i].code # code) DO
  126.                 DEC(i)
  127.         END;
  128.         IF i < 0 THEN
  129.                 i := ORD("?")
  130.         END
  131.         RETURN i
  132. END ucs2to1251;
  133.  
  134.  
  135. PROCEDURE initCP (VAR cp: tCodePage);
  136. VAR
  137.         i: INTEGER;
  138. BEGIN
  139.         FOR i := 0H TO 7FH DO
  140.                 cp[i].code := i
  141.         END;
  142.         FOR i := 0H TO 0FFH DO
  143.                 utf8(cp[i].code, cp[i].utf8);
  144.                 cp[i].len := LENGTH(cp[i].utf8)
  145.         END
  146. END initCP;
  147.  
  148.  
  149. PROCEDURE init8 (VAR cp: tCodePage; VAR n: INTEGER; a, b, c, d, e, f, g, h: INTEGER);
  150. BEGIN
  151.         cp[n].code := a; INC(n);
  152.         cp[n].code := b; INC(n);
  153.         cp[n].code := c; INC(n);
  154.         cp[n].code := d; INC(n);
  155.         cp[n].code := e; INC(n);
  156.         cp[n].code := f; INC(n);
  157.         cp[n].code := g; INC(n);
  158.         cp[n].code := h; INC(n);
  159. END init8;
  160.  
  161.  
  162. PROCEDURE init1250 (VAR cp: tCodePage);
  163. VAR
  164.         n: INTEGER;
  165. BEGIN
  166.         n := 80H;
  167.         init8(cp, n, 20ACH,   20H, 201AH,   20H, 201EH, 2026H, 2020H, 2021H);
  168.         init8(cp, n,   20H, 2030H, 0160H, 2039H, 015AH, 0164H, 017DH, 0179H);
  169.         init8(cp, n,   20H, 2018H, 2019H, 201CH, 201DH, 2022H, 2013H, 2014H);
  170.         init8(cp, n,   20H, 2122H, 0161H, 203AH, 015BH, 0165H, 017EH, 017AH);
  171.         init8(cp, n, 00A0H, 02C7H, 02D8H, 0141H, 00A4H, 0104H, 00A6H, 00A7H);
  172.         init8(cp, n, 00A8H, 00A9H, 015EH, 00ABH, 00ACH, 00ADH, 00AEH, 017BH);
  173.         init8(cp, n, 00B0H, 00B1H, 02DBH, 0142H, 00B4H, 00B5H, 00B6H, 00B7H);
  174.         init8(cp, n, 00B8H, 0105H, 015FH, 00BBH, 013DH, 02DDH, 013EH, 017CH);
  175.         init8(cp, n, 0154H, 00C1H, 00C2H, 0102H, 00C4H, 0139H, 0106H, 00C7H);
  176.         init8(cp, n, 010CH, 00C9H, 0118H, 00CBH, 011AH, 00CDH, 00CEH, 010EH);
  177.         init8(cp, n, 0110H, 0143H, 0147H, 00D3H, 00D4H, 0150H, 00D6H, 00D7H);
  178.         init8(cp, n, 0158H, 016EH, 00DAH, 0170H, 00DCH, 00DDH, 0162H, 00DFH);
  179.         init8(cp, n, 0155H, 00E1H, 00E2H, 0103H, 00E4H, 013AH, 0107H, 00E7H);
  180.         init8(cp, n, 010DH, 00E9H, 0119H, 00EBH, 011BH, 00EDH, 00EEH, 010FH);
  181.         init8(cp, n, 0111H, 0144H, 0148H, 00F3H, 00F4H, 0151H, 00F6H, 00F7H);
  182.         init8(cp, n, 0159H, 016FH, 00FAH, 0171H, 00FCH, 00FDH, 0163H, 02D9H);
  183.         initCP(cp)
  184. END init1250;
  185.  
  186.  
  187. PROCEDURE init1251 (VAR cp: tCodePage);
  188. VAR
  189.         n, i: INTEGER;
  190. BEGIN
  191.         n := 80H;
  192.         init8(cp, n, 0402H, 0403H, 201AH, 0453H, 201EH, 2026H, 2020H, 2021H);
  193.         init8(cp, n, 20ACH, 2030H, 0409H, 2039H, 040AH, 040CH, 040BH, 040FH);
  194.         init8(cp, n, 0452H, 2018H, 2019H, 201CH, 201DH, 2022H, 2013H, 2014H);
  195.         init8(cp, n,   20H, 2122H, 0459H, 203AH, 045AH, 045CH, 045BH, 045FH);
  196.         init8(cp, n, 00A0H, 040EH, 045EH, 0408H, 00A4H, 0490H, 00A6H, 00A7H);
  197.         init8(cp, n, 0401H, 00A9H, 0404H, 00ABH, 00ACH, 00ADH, 00AEH, 0407H);
  198.         init8(cp, n, 00B0H, 00B1H, 0406H, 0456H, 0491H, 00B5H, 00B6H, 00B7H);
  199.         init8(cp, n, 0451H, 2116H, 0454H, 00BBH, 0458H, 0405H, 0455H, 0457H);
  200.         FOR i := 0410H TO 044FH DO
  201.                 cp[i - 350H].code := i
  202.         END;
  203.         initCP(cp)
  204. END init1251;
  205.  
  206.  
  207. PROCEDURE init1252 (VAR cp: tCodePage);
  208. VAR
  209.         n, i: INTEGER;
  210. BEGIN
  211.         n := 80H;
  212.         init8(cp, n, 20ACH,   20H, 201AH, 0192H, 201EH, 2026H, 2020H, 2021H);
  213.         init8(cp, n, 02C6H, 2030H, 0160H, 2039H, 0152H,   20H, 017DH,   20H);
  214.         init8(cp, n,   20H, 2018H, 2019H, 201CH, 201DH, 2022H, 2013H, 2014H);
  215.         init8(cp, n, 02DCH, 2122H, 0161H, 203AH, 0153H,   20H, 017EH, 0178H);
  216.         FOR i := 0A0H TO 0FFH DO
  217.                 cp[i].code := i
  218.         END;
  219.         initCP(cp)
  220. END init1252;
  221.  
  222.  
  223. PROCEDURE init866 (VAR cp: tCodePage);
  224. VAR
  225.         n, i: INTEGER;
  226. BEGIN
  227.         FOR i := 0410H TO 043FH DO
  228.                 cp[i - 0410H + 80H].code := i
  229.         END;
  230.         FOR i := 0440H TO 044FH DO
  231.                 cp[i - 0440H + 0E0H].code := i
  232.         END;
  233.  
  234.         n := 0B0H;
  235.         init8(cp, n, 2591H, 2592H, 2593H, 2502H, 2524H, 2561H, 2562H, 2556H);
  236.         init8(cp, n, 2555H, 2563H, 2551H, 2557H, 255DH, 255CH, 255BH, 2510H);
  237.         init8(cp, n, 2514H, 2534H, 252CH, 251CH, 2500H, 253CH, 255EH, 255FH);
  238.         init8(cp, n, 255AH, 2554H, 2569H, 2566H, 2560H, 2550H, 256CH, 2567H);
  239.         init8(cp, n, 2568H, 2564H, 2565H, 2559H, 2558H, 2552H, 2553H, 256BH);
  240.         init8(cp, n, 256AH, 2518H, 250CH, 2588H, 2584H, 258CH, 2590H, 2580H);
  241.  
  242.         n := 0F0H;
  243.         init8(cp, n, 0401H, 0451H, 0404H, 0454H, 0407H, 0457H, 040EH, 045EH);
  244.         init8(cp, n, 00B0H, 2219H, 00B7H, 221AH, 2116H, 00A4H, 25A0H, 00A0H);
  245.  
  246.         initCP(cp)
  247. END init866;
  248.  
  249.  
  250. PROCEDURE init;
  251. VAR
  252.         i: INTEGER;
  253. BEGIN
  254.         init1250(cp1250);
  255.         init1251(cp1251);
  256.         init1252(cp1252);
  257.         init866(cp866);
  258.         FOR i := 0 TO TABLE_SIZE - 1 DO
  259.                 table1251[i] := ucs2to1251(i)
  260.         END
  261. END init;
  262.  
  263.  
  264. BEGIN
  265.         init
  266. END Encoding.
  267.