import winim/[ lean
, winstr
]
# if a win32 window does a bad
# this will call into M$ land
# and get the associated err code's reason
proc why*(err: DWORD): auto =
var
theDWord: lean.DWORD = FORMAT_MESSAGE_ALLOCATE_BUFFER or
FORMAT_MESSAGE_FROM_SYSTEM or
FORMAT_MESSAGE_IGNORE_INSERTS
theOtherdWord: lean.DWORD = cast [lean.DWORD](MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT))
messageBuffer: LPSTR
size = FormatMessageA( theDWord
, nil
, err
, theOtherDWord
, cast[LPSTR](addr messageBuffer)
, 0
, nil)
result = messageBuffer
proc ctNewWString(s: static[string]): wstring =
# copy from widestrs.nim, use WCHAR instead of Utf16Char
const
UNI_REPLACEMENT_CHAR = WCHAR(0xFFFD'u16)
UNI_MAX_BMP = 0x0000FFFF
UNI_MAX_UTF16 = 0x0010FFFF
halfShift = 10
halfBase = 0x0010000
halfMask = 0x3FF
UNI_SUR_HIGH_START = 0xD800
UNI_SUR_LOW_START = 0xDC00
UNI_SUR_LOW_END = 0xDFFF
UNI_REPL = 0xFFFD
template ones(n: untyped): untyped = ((1 shl n)-1)
template fastRuneAt(s: cstring, i, L: int, result: untyped, doInc = true) =
if ord(s[i]) <= 127:
result = ord(s[i])
when doInc: inc(i)
elif ord(s[i]) shr 5 == 0b110:
if i <= L - 2:
result = (ord(s[i]) and (ones(5))) shl 6 or (ord(s[i+1]) and ones(6))
when doInc: inc(i, 2)
else:
result = UNI_REPL
when doInc: inc(i)
elif ord(s[i]) shr 4 == 0b1110:
if i <= L - 3:
result = (ord(s[i]) and ones(4)) shl 12 or
(ord(s[i+1]) and ones(6)) shl 6 or
(ord(s[i+2]) and ones(6))
when doInc: inc(i, 3)
else:
result = UNI_REPL
when doInc: inc(i)
elif ord(s[i]) shr 3 == 0b11110:
if i <= L - 4:
result = (ord(s[i]) and ones(3)) shl 18 or
(ord(s[i+1]) and ones(6)) shl 12 or
(ord(s[i+2]) and ones(6)) shl 6 or
(ord(s[i+3]) and ones(6))
when doInc: inc(i, 4)
else:
result = UNI_REPL
when doInc: inc(i)
else:
result = 0xFFFD
when doInc: inc(i)
iterator runes(s: cstring, L: int): int =
var
i = 0
ret: int
while i < L:
fastRuneAt(s, i, L, ret, true)
yield ret
iterator WCHARs(source: cstring, L: int): WCHAR =
for ch in runes(source, L):
if ch <=% UNI_MAX_BMP:
if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_LOW_END:
yield UNI_REPLACEMENT_CHAR
else:
yield WCHAR(ch)
elif ch >% UNI_MAX_UTF16:
yield UNI_REPLACEMENT_CHAR
else:
let ch = ch -% halfBase
yield WCHAR((ch shr halfShift) +% UNI_SUR_HIGH_START)
yield WCHAR((ch and halfMask) +% UNI_SUR_LOW_START)
var ret: string
for u in WCHARs(s, s.len):
ret.add char(u and 0xFF)
ret.add char(u shr 8)
ret.add "\0\0"
result = wstring ret
# no const to avoid Error: "VM does not support cast from tyCstring to tyPtr"
template L_no_const*(x: string): wstring =
## Generate const wstring from `static[string]` at compile-time.
var thing = ctNewWString(x)
thing