- Add more detailed (and precise) comments. - Expand `cp850` macro to encode more code points; useful for German characters `ä` and `ü`. - Note: all of the current CP850 encodings map directly to CP437. Reviewed-on: KolibriOS/kolibrios#501 Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com> Reviewed-by: Burer <burer@kolibrios.org> Co-authored-by: Andrew <dent.ace@gmail.com> Co-committed-by: Andrew <dent.ace@gmail.com>
153 lines
4.7 KiB
FASM
153 lines
4.7 KiB
FASM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; Copyright (C) KolibriOS team 2013-2026. All rights reserved. ;;
|
|
;; Distributed under terms of the GNU General Public License ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
; fetch the UTF-8 character in addrspace:offs to char
|
|
macro fetch_utf8_char addrspace, offs, char
|
|
{ local first_byte, b
|
|
; fetch first byte
|
|
load first_byte byte from addrspace:offs
|
|
if first_byte < 0x80
|
|
char = first_byte
|
|
offs = offs + 1
|
|
else if first_byte < 0xC0
|
|
err Invalid UTF-8 string
|
|
else if first_byte < 0xE0
|
|
char = first_byte and 0x1F
|
|
load b byte from addrspace:offs + 1
|
|
char = (char shl 6) + (b and 0x3F)
|
|
offs = offs + 2
|
|
else if first_byte < 0xF0
|
|
char = first_byte and 0xF
|
|
load b byte from addrspace:offs + 1
|
|
char = (char shl 6) + (b and 0x3F)
|
|
load b byte from addrspace:offs + 2
|
|
char = (char shl 6) + (b and 0x3F)
|
|
offs = offs + 3
|
|
else if first_byte < 0xF8
|
|
char = first_byte and 0x7
|
|
load b byte from addrspace:offs + 1
|
|
char = (char shl 6) + (b and 0x3F)
|
|
load b byte from addrspace:offs + 2
|
|
char = (char shl 6) + (b and 0x3F)
|
|
load b byte from addrspace:offs + 3
|
|
char = (char shl 6) + (b and 0x3F)
|
|
offs = offs + 4
|
|
else
|
|
err Invalid UTF-8 string
|
|
end if
|
|
}
|
|
|
|
; Worker macro for all encodings.
|
|
; Common for all encodings: map characters 0-0x7F trivially,
|
|
; translate 'box drawing' pseudographics (used on boot screen).
|
|
macro convert_utf8 encoding, [arg]
|
|
{ common
|
|
local ..addrspace, offs, char
|
|
offs = 0
|
|
virtual at 0
|
|
..addrspace:: db arg
|
|
..addrspace#.size = $
|
|
end virtual
|
|
while offs < ..addrspace#.size
|
|
fetch_utf8_char ..addrspace, offs, char
|
|
; Encode 'Box Drawing' glyphs from Unicode into CP437/850/866
|
|
if char = 0x2500 ; '─' U+2500 - Box Drawings Light Horizontal
|
|
db 0xC4
|
|
else if char = 0x2502 ; '│' U+2502 - Box Drawings Light Vertical
|
|
db 0xB3
|
|
else if char = 0x250C ; '┌' U+250C - Box Drawings Light Down and Right
|
|
db 0xDA
|
|
else if char = 0x2510 ; '┐' U+2510 - Box Drawings Light Down and Left
|
|
db 0xBF
|
|
else if char = 0x2514 ; '└' U+2514 - Box Drawings Light Up and Right
|
|
db 0xC0
|
|
else if char = 0x2518 ; '┘' U+2518 - Box Drawings Light Up and Left
|
|
db 0xD9
|
|
else if char = 0x252C ; '┬' U+252C - Box Drawings Light Down and Horizontal
|
|
db 0xC2
|
|
else if char = 0x2534 ; '┴' U+2534 - Box Drawings Light Up and Horizontal
|
|
db 0xC1
|
|
else if char = 0x2551 ; '║' U+2551 - Box Drawings Double Vertical
|
|
db 0xBA
|
|
; Code points 0x20 to 0x7F are common for CP437/850/866, Latin-1 and UTF-8
|
|
else if char < 0x80
|
|
db char
|
|
else
|
|
encoding char
|
|
end if
|
|
end while
|
|
}
|
|
|
|
macro declare_encoding encoding
|
|
{
|
|
macro encoding [arg]
|
|
\{ common convert_utf8 encoding#char, arg \}
|
|
struc encoding [arg]
|
|
\{ common convert_utf8 encoding#char, arg \}
|
|
macro encoding#char char
|
|
}
|
|
|
|
; Russian: use CP866.
|
|
; 0x410-0x43F -> 0x80-0xAF
|
|
; 0x440-0x44F -> 0xE0-0xEF
|
|
; 0x401 -> 0xF0, 0x451 -> 0xF1
|
|
declare_encoding cp866
|
|
{
|
|
if char = 0x401
|
|
db 0xF0
|
|
else if char = 0x451
|
|
db 0xF1
|
|
else if (char < 0x410) | (char > 0x44F)
|
|
err Failed to convert to CP866
|
|
else if char < 0x440
|
|
db char - 0x410 + 0x80
|
|
else
|
|
db char - 0x440 + 0xE0
|
|
end if
|
|
}
|
|
|
|
; Latin-1 encoding
|
|
; Mapping is trivial, as Unicode defined the first 256 code points (0x00-0xFF)
|
|
; to correspond to the characters and numerical values of Latin-1.
|
|
declare_encoding latin1
|
|
{
|
|
if char < 0x100
|
|
db char
|
|
else
|
|
err Failed to convert to Latin-1
|
|
end if
|
|
}
|
|
|
|
; CP850 encoding
|
|
; Code points 0x00 to 0x7F are common for CP437/850/866
|
|
; Code points mapped below are common for CP437/850
|
|
declare_encoding cp850
|
|
{
|
|
if char = 0xBF ; '¿' U+00BF - Inverted Question Mark
|
|
db 0xA8
|
|
else if char = 0xE1 ; 'á' U+00E1 - Latin Small Letter A with Acute
|
|
db 0xA0
|
|
else if char = 0xE9 ; 'é' U+00E9 - Latin Small Letter E with Acute
|
|
db 0x82
|
|
else if char = 0xED ; 'í' U+00ED - Latin Small Letter I with Acute
|
|
db 0xA1
|
|
else if char = 0xF3 ; 'ó' U+00F3 - Latin Small Letter O with Acute
|
|
db 0xA2
|
|
else if char = 0xFA ; 'ú' U+00FA - Latin Small Letter U with Acute
|
|
db 0xA3
|
|
else if char = 0xF1 ; 'ñ' U+00F1 - Latin Small Letter N with Tilde
|
|
db 0xA4
|
|
else if char = 0xFC ; 'ü' U+00FC - Latin Small Letter U with Diaeresis
|
|
db 0x81
|
|
else if char = 0xE4 ; 'ä' U+00E4 - Latin Small Letter A with Diaeresis
|
|
db 0x84
|
|
else
|
|
err Failed to convert to CP850
|
|
end if
|
|
}
|