summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--doc/manual.txt8
-rw-r--r--lib/pure/os.nim68
-rw-r--r--lib/pure/osproc.nim15
-rw-r--r--lib/system/sysio.nim12
-rw-r--r--lib/system/widestrs.nim359
-rw-r--r--lib/windows/winlean.nim4
-rw-r--r--web/news.txt4
7 files changed, 164 insertions, 306 deletions
diff --git a/doc/manual.txt b/doc/manual.txt
index 4d2cd6a62..31bd7134d 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -2868,9 +2868,9 @@ Effect system
 Exception tracking
 ------------------
 
-Nimrod supports `exception tracking`:idx:. The `raises`:idx: pragma can used to
-explicitly define which exceptions a proc/iterator/method/converter is allowed
-to raise. The compiler verifies this:
+Nimrod supports `exception tracking`:idx:. The `raises`:idx: pragma can be used
+to explicitly define which exceptions a proc/iterator/method/converter is 
+allowed to raise. The compiler verifies this:
 
 .. code-block:: nimrod
   proc p(what: bool) {.raises: [EIO, EOS].} =
@@ -2878,7 +2878,7 @@ to raise. The compiler verifies this:
     else: raise newException(EOS, "OS")
 
 An empty ``raises`` list (``raises: []``) means that no exception may be raised:
-  
+
 .. code-block:: nimrod
   proc p(): bool {.raises: [].} =
     try:
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 433a79c5e..233967753 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -184,7 +184,7 @@ proc OSErrorMsg*(): string {.rtl, extern: "nos$1".} =
         if FormatMessageW(0x00000100 or 0x00001000 or 0x00000200,
                           nil, err, 0, addr(msgbuf), 0, nil) != 0'i32:
           result = $msgbuf
-          if msgbuf != nil: LocalFree(msgbuf)
+          if msgbuf != nil: LocalFree(cast[pointer](msgbuf))
       else:
         var msgbuf: cstring
         if FormatMessageA(0x00000100 or 0x00001000 or 0x00000200,
@@ -254,20 +254,14 @@ proc UnixToNativePath*(path: string): string {.
 
 when defined(windows):
   template wrapUnary(varname, winApiProc, arg: expr) {.immediate.} =
-    var tmp = allocWideCString(arg)
-    var varname = winApiProc(tmp)
-    dealloc tmp
+    var varname = winApiProc(newWideCString(arg))
 
   template wrapBinary(varname, winApiProc, arg, arg2: expr) {.immediate.} =
-    var tmp2 = allocWideCString(arg)
-    var varname = winApiProc(tmp2, arg2)
-    dealloc tmp2
+    var varname = winApiProc(newWideCString(arg), arg2)
 
   when useWinUnicode:
     proc FindFirstFile(a: string, b: var TWIN32_FIND_DATA): THandle =
-      var aa = allocWideCString(a)
-      result = FindFirstFileW(aa, b)
-      dealloc aa
+      result = FindFirstFileW(newWideCString(a), b)
     template FindNextFile(a, b: expr): expr = FindNextFileW(a, b)
     template getCommandLine(): expr = getCommandLineW()
 
@@ -363,11 +357,10 @@ proc getCurrentDir*(): string {.rtl, extern: "nos$1", tags: [].} =
   const bufsize = 512 # should be enough
   when defined(windows):
     when useWinUnicode:
-      var res = cast[wideCString](alloc0(bufsize+1))
+      var res = newWideCString("", bufsize)
       var L = GetCurrentDirectoryW(bufsize, res)
-      result = res$L
-      dealloc res
       if L == 0'i32: OSError()
+      result = res$L
     else:
       result = newString(bufsize)
       var L = GetCurrentDirectoryA(bufsize, result)
@@ -385,10 +378,7 @@ proc setCurrentDir*(newDir: string) {.inline, tags: [].} =
   ## `newDir` cannot been set.
   when defined(Windows):
     when useWinUnicode:
-      var x = allocWideCString(newDir)
-      let res = SetCurrentDirectoryW(x)
-      dealloc x
-      if res == 0'i32: OSError()
+      if SetCurrentDirectoryW(newWideCString(newDir)) == 0'i32: OSError()
     else:
       if SetCurrentDirectoryA(newDir) == 0'i32: OSError()
   else:
@@ -579,15 +569,11 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
     const bufsize = 3072'i32
     when useWinUnicode:
       var unused: widecstring
-      var res = cast[widecstring](alloc(bufsize*2+2))
-      var f = allocWideCString(filename)
-      var L = GetFullPathNameW(f, bufsize, res, unused)
-      dealloc f
+      var res = newWideCString("", bufsize div 2)
+      var L = GetFullPathNameW(newWideCString(filename), bufsize, res, unused)
       if L <= 0'i32 or L >= bufsize: 
-        dealloc res
         OSError()
       result = res$L
-      dealloc res
     else:
       var unused: cstring
       result = newString(bufsize)
@@ -673,8 +659,8 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
     var success = true
 
     when useWinUnicode:
-      var p1 = allocWideCString(path1)
-      var p2 = allocWideCString(path2)
+      var p1 = newWideCString(path1)
+      var p2 = newWideCString(path2)
       template OpenHandle(path: expr): expr =
         CreateFileW(path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or
           FILE_SHARE_WRITE, nil, OPEN_EXISTING,
@@ -705,9 +691,6 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
 
     discard CloseHandle(f1)
     discard CloseHandle(f2)
-    when useWinUnicode:
-      dealloc p1
-      dealloc p2
 
     if not success: OSError()
   else:
@@ -754,12 +737,9 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
   ## `EOS` is raised.
   when defined(Windows):
     when useWinUnicode:
-      var s = allocWideCString(source)
-      var d = allocWideCString(dest)
-      let res = CopyFileW(s, d, 0'i32)
-      dealloc s
-      dealloc d
-      if res == 0'i32: OSError()
+      let s = newWideCString(source)
+      let d = newWideCString(dest)
+      if CopyFileW(s, d, 0'i32) == 0'i32: OSError()
     else:
       if CopyFileA(source, dest, 0'i32) == 0'i32: OSError()
   else:
@@ -794,11 +774,8 @@ when not defined(ENOENT):
   var ENOENT {.importc, header: "<errno.h>".}: cint
 
 proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} =
-  ## Removes the `file`.
-  ##
-  ## If this fails, `EOS` is raised. This does not fail if the file never
-  ## existed in the first place. Despite the name of this proc you can also
-  ## call it on directories, but they will only be removed if they are empty.
+  ## Removes the `file`. If this fails, `EOS` is raised. This does not fail
+  ## if the file never existed in the first place.
   if cremove(file) != 0'i32 and errno != ENOENT: OSError()
 
 proc execShellCmd*(command: string): int {.rtl, extern: "nos$1", 
@@ -934,12 +911,9 @@ proc putEnv*(key, val: string) {.tags: [FWriteEnv].} =
       OSError()
   else:
     when useWinUnicode:
-      var k = allocWideCString(key)
-      var v = allocWideCString(val)
-      let res = SetEnvironmentVariableW(k, v)
-      dealloc k
-      dealloc v
-      if res == 0'i32: OSError()
+      var k = newWideCString(key)
+      var v = newWideCString(val)
+      if SetEnvironmentVariableW(k, v) == 0'i32: OSError()
     else:
       if SetEnvironmentVariableA(key, val) == 0'i32: OSError()
 
@@ -1082,9 +1056,7 @@ proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
   ## in `dir` (recursively).
   ##
   ## If this fails, `EOS` is raised. This does not fail if the directory never
-  ## existed in the first place. If you need non recursive directory removal
-  ## which fails when the directory contains files use the `removeFile` proc
-  ## instead.
+  ## existed in the first place.
   for kind, path in walkDir(dir): 
     case kind
     of pcFile, pcLinkToFile, pcLinkToDir: removeFile(path)
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index e627e73c8..aa4fbe32d 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -361,14 +361,12 @@ when defined(Windows) and not defined(useNimRtl):
     if env != nil: e = buildEnv(env)
     if poEchoCmd in options: echo($cmdl)
     when useWinUnicode:
-      var tmp = allocWideCString(cmdl)
-      var ee = allocWideCString(e)
-      var wwd = allocWideCString(wd)
+      var tmp = newWideCString(cmdl)
+      var ee = newWideCString(e)
+      var wwd = newWideCString(wd)
       success = winlean.CreateProcessW(nil,
-        tmp, nil, nil, 1, NORMAL_PRIORITY_CLASS, ee, wwd, SI, ProcInfo)
-      if tmp != nil: dealloc tmp
-      if ee != nil: dealloc ee
-      if wwd != nil: dealloc wwd
+        tmp, nil, nil, 1, NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT, 
+        ee, wwd, SI, ProcInfo)
     else:
       success = winlean.CreateProcessA(nil,
         cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, SI, ProcInfo)
@@ -445,10 +443,9 @@ when defined(Windows) and not defined(useNimRtl):
     SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE)
     SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
     when useWinUnicode:
-      var c = allocWideCString(command)
+      var c = newWideCString(command)
       var res = winlean.CreateProcessW(nil, c, nil, nil, 0,
         NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo)
-      dealloc c
     else:
       var res = winlean.CreateProcessA(nil, command, nil, nil, 0,
         NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo)
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index 3d5a53f03..31758eb45 100644
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -168,18 +168,14 @@ when defined(windows) and not defined(useWinAnsi):
     importc: "_wfreopen", nodecl.}
 
   proc fopen(filename, mode: CString): pointer =
-    var f = allocWideCString(filename)
-    var m = allocWideCString(mode)
+    var f = newWideCString(filename)
+    var m = newWideCString(mode)
     result = wfopen(f, m)
-    dealloc m
-    dealloc f
 
   proc freopen(filename, mode: cstring, stream: TFile): TFile =
-    var f = allocWideCString(filename)
-    var m = allocWideCString(mode)
+    var f = newWideCString(filename)
+    var m = newWideCString(mode)
     result = wfreopen(f, m, stream)
-    dealloc m
-    dealloc f
 
 else:
   proc fopen(filename, mode: CString): pointer {.importc: "fopen", noDecl.}
diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim
index 588093d10..cf1f0910c 100644
--- a/lib/system/widestrs.nim
+++ b/lib/system/widestrs.nim
@@ -12,249 +12,138 @@
 

 type

   TUtf16Char* = distinct int16

-  WideCString* = ptr array[0.. 1_000_000, TUtf16Char]

+  WideCString* = ref array[0.. 1_000_000, TUtf16Char]

 

 proc len*(w: WideCString): int =

   ## returns the length of a widestring. This traverses the whole string to

   ## find the binary zero end marker!

   while int16(w[result]) != 0'i16: inc result

 

-when true:

-  const

-    UNI_REPLACEMENT_CHAR = TUtf16Char(0xFFFD'i16)

-    UNI_MAX_BMP = 0x0000FFFF

-    UNI_MAX_UTF16 = 0x0010FFFF

-    UNI_MAX_UTF32 = 0x7FFFFFFF

-    UNI_MAX_LEGAL_UTF32 = 0x0010FFFF

-

-    halfShift = 10

-    halfBase = 0x0010000

-    halfMask = 0x3FF

-

-    UNI_SUR_HIGH_START = 0xD800

-    UNI_SUR_HIGH_END = 0xDBFF

-    UNI_SUR_LOW_START = 0xDC00

-    UNI_SUR_LOW_END = 0xDFFF

-

-  template ones(n: expr): expr = ((1 shl n)-1)

-

-  template fastRuneAt(s: cstring, i: int, result: expr, doInc = true) =

-    ## Returns the unicode character ``s[i]`` in `result`. If ``doInc == true``

-    ## `i` is incremented by the number of bytes that have been processed.

-    bind ones

-

-    if ord(s[i]) <=% 127:

-      result = ord(s[i])

-      when doInc: inc(i)

-    elif ord(s[i]) shr 5 == 0b110:

-      #assert(ord(s[i+1]) shr 6 == 0b10)

-      result = (ord(s[i]) and (ones(5))) shl 6 or (ord(s[i+1]) and ones(6))

-      when doInc: inc(i, 2)

-    elif ord(s[i]) shr 4 == 0b1110:

-      #assert(ord(s[i+1]) shr 6 == 0b10)

-      #assert(ord(s[i+2]) shr 6 == 0b10)

-      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)

-    elif ord(s[i]) shr 3 == 0b11110:

-      #assert(ord(s[i+1]) shr 6 == 0b10)

-      #assert(ord(s[i+2]) shr 6 == 0b10)

-      #assert(ord(s[i+3]) shr 6 == 0b10)

-      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 = 0xFFFD

-      when doInc: inc(i)

-

-  iterator runes(s: cstring): int =

-    var

-      i = 0

-      result: int

-    while s[i] != '\0':

-      fastRuneAt(s, i, result, true)

-      yield result

-

-  proc allocWideCString*(source: cstring, L: int): WideCString =

-    ## free after usage with `dealloc`.

-    result = cast[wideCString](alloc(L * 4 + 2))

-    var d = 0

-    for ch in runes(source):

-      if ch <=% UNI_MAX_BMP:

-        if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_LOW_END:

-          result[d] = UNI_REPLACEMENT_CHAR

-        else:

-          result[d] = TUtf16Char(toU16(ch))

-      elif ch >% UNI_MAX_UTF16:

+const

+  UNI_REPLACEMENT_CHAR = TUtf16Char(0xFFFD'i16)

+  UNI_MAX_BMP = 0x0000FFFF

+  UNI_MAX_UTF16 = 0x0010FFFF

+  UNI_MAX_UTF32 = 0x7FFFFFFF

+  UNI_MAX_LEGAL_UTF32 = 0x0010FFFF

+

+  halfShift = 10

+  halfBase = 0x0010000

+  halfMask = 0x3FF

+

+  UNI_SUR_HIGH_START = 0xD800

+  UNI_SUR_HIGH_END = 0xDBFF

+  UNI_SUR_LOW_START = 0xDC00

+  UNI_SUR_LOW_END = 0xDFFF

+

+template ones(n: expr): expr = ((1 shl n)-1)

+

+template fastRuneAt(s: cstring, i: int, result: expr, doInc = true) =

+  ## Returns the unicode character ``s[i]`` in `result`. If ``doInc == true``

+  ## `i` is incremented by the number of bytes that have been processed.

+  bind ones

+

+  if ord(s[i]) <=% 127:

+    result = ord(s[i])

+    when doInc: inc(i)

+  elif ord(s[i]) shr 5 == 0b110:

+    #assert(ord(s[i+1]) shr 6 == 0b10)

+    result = (ord(s[i]) and (ones(5))) shl 6 or (ord(s[i+1]) and ones(6))

+    when doInc: inc(i, 2)

+  elif ord(s[i]) shr 4 == 0b1110:

+    #assert(ord(s[i+1]) shr 6 == 0b10)

+    #assert(ord(s[i+2]) shr 6 == 0b10)

+    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)

+  elif ord(s[i]) shr 3 == 0b11110:

+    #assert(ord(s[i+1]) shr 6 == 0b10)

+    #assert(ord(s[i+2]) shr 6 == 0b10)

+    #assert(ord(s[i+3]) shr 6 == 0b10)

+    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 = 0xFFFD

+    when doInc: inc(i)

+

+iterator runes(s: cstring): int =

+  var

+    i = 0

+    result: int

+  while s[i] != '\0':

+    fastRuneAt(s, i, result, true)

+    yield result

+

+proc newWideCString*(source: cstring, L: int): WideCString =

+  unsafeNew(result, L * 4 + 2)
+  #result = cast[wideCString](alloc(L * 4 + 2))

+  var d = 0

+  for ch in runes(source):

+    if ch <=% UNI_MAX_BMP:

+      if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_LOW_END:

         result[d] = UNI_REPLACEMENT_CHAR

       else:

-        let ch = ch -% halfBase

-        result[d] = TUtf16Char(toU16((ch shr halfShift) +% UNI_SUR_HIGH_START))

-        inc d

-        result[d] = TUtf16Char(toU16((ch and halfMask) +% UNI_SUR_LOW_START))

+        result[d] = TUtf16Char(toU16(ch))

+    elif ch >% UNI_MAX_UTF16:

+      result[d] = UNI_REPLACEMENT_CHAR

+    else:

+      let ch = ch -% halfBase

+      result[d] = TUtf16Char(toU16((ch shr halfShift) +% UNI_SUR_HIGH_START))

       inc d

-    result[d] = TUtf16Char(0'i16)

-

-  proc allocWideCString*(s: cstring): WideCString =

-    ## free after usage with `dealloc`.

-    if s.isNil: return nil

-

-    when not defined(c_strlen):

-      proc c_strlen(a: CString): int {.nodecl, noSideEffect, importc: "strlen".}

-

-    let L = cstrlen(s)

-    result = allocWideCString(s, L)

-

-  proc allocWideCString*(s: string): WideCString =

-    ## free after usage with `dealloc`.

-    result = allocWideCString(s, s.len)

-

-  proc `$`*(w: wideCString, estimate: int): string =

-    result = newStringOfCap(estimate + estimate shr 2)

-

-    var i = 0

-    while w[i].int16 != 0'i16:

-      var ch = w[i].int

-      inc i

-      if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_HIGH_END:

-        # If the 16 bits following the high surrogate are in the source buffer...

-        let ch2 = w[i].int

-        # If it's a low surrogate, convert to UTF32:

-        if ch2 >=% UNI_SUR_LOW_START and ch2 <=% UNI_SUR_LOW_END:

-          ch = ((ch -% UNI_SUR_HIGH_START) shr halfShift) +%

-                (ch2 -% UNI_SUR_LOW_START) +% halfBase

-          inc i

-          

-      if ch <=% 127:

-        result.add chr(ch)

-      elif ch <=% 0x07FF:

-        result.add chr((ch shr 6) or 0b110_00000)

-        result.add chr((ch and ones(6)) or 0b10_000000)

-      elif ch <=% 0xFFFF:

-        result.add chr(ch shr 12 or 0b1110_0000)

-        result.add chr(ch shr 6 and ones(6) or 0b10_0000_00)

-        result.add chr(ch and ones(6) or 0b10_0000_00)

-      elif ch <=% 0x0010FFFF:

-        result.add chr(ch shr 18 or 0b1111_0000)

-        result.add chr(ch shr 12 and ones(6) or 0b10_0000_00)

-        result.add chr(ch shr 6 and ones(6) or 0b10_0000_00)

-        result.add chr(ch and ones(6) or 0b10_0000_00)

-      else:

-        # replacement char:

-        result.add chr(0xFFFD shr 12 or 0b1110_0000)

-        result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00)

-        result.add chr(0xFFFD and ones(6) or 0b10_0000_00)

-

-  proc `$`*(s: WideCString): string =

-    result = s $ 80

-

-else:

-  const

-    utf8Encoding = 65001

-    

-  proc MultiByteToWideChar*(

-    CodePage: int32,

-    dwFlags: int32,

-    lpMultiByteStr: cstring,

-    cbMultiByte: cint,

-    lpWideCharStr: WideCString,

-    cchWideChar: cint): cint {.

-      stdcall, importc: "MultiByteToWideChar", dynlib: "kernel32".}

-

-  proc WideCharToMultiByte*(

-    CodePage: int32,

-    dwFlags: int32,

-    lpWideCharStr: WideCString,

-    cchWideChar: cint,

-    lpMultiByteStr: cstring,

-    cbMultiByte: cint,

-    lpDefaultChar: cstring=nil,

-    lpUsedDefaultChar: pointer=nil): cint {.

-      stdcall, importc: "WideCharToMultiByte", dynlib: "kernel32".}

-

-  proc raiseEncodingError() {.noinline, noreturn.} =

-    raise newException(EOS, "error in unicode conversion")

-

-  proc `$`*(s: WideCString, len: int): string =

-    # special case: empty string: needed because MultiByteToWideChar

-    # returns 0 in case of error:

-    if len == 0: return ""

-

-    # educated guess of capacity:

-    var cap = len + len shr 2

-    result = newStringOfCap(cap)

-    

-    let m = WideCharToMultiByte(

-      CodePage = utf8Encoding,

-      dwFlags = 0'i32,

-      lpWideCharStr = s,

-      cchWideChar = cint(len),

-      lpMultiByteStr = cstring(result),

-      cbMultiByte = cap)

-    if m == 0:

-      # try again; ask for capacity:

-      cap = WideCharToMultiByte(

-        CodePage = utf8Encoding,

-        dwFlags = 0'i32,

-        lpWideCharStr = s,

-        cchWideChar = cint(len),

-        lpMultiByteStr = nil,

-        cbMultiByte = cint(0))

-      # and do the conversion properly:

-      result = newStringOfCap(cap)

-      let m = WideCharToMultiByte(

-        CodePage = utf8Encoding,

-        dwFlags = 0'i32,

-        lpWideCharStr = s,

-        cchWideChar = cint(len),

-        lpMultiByteStr = cstring(result),

-        cbMultiByte = cap)

-      if m == 0: raiseEncodingError()

-      setLen(result, m)

-    elif m <= cap:

-      setLen(result, m)

+      result[d] = TUtf16Char(toU16((ch and halfMask) +% UNI_SUR_LOW_START))

+    inc d

+  result[d] = TUtf16Char(0'i16)

+

+proc newWideCString*(s: cstring): WideCString =

+  if s.isNil: return nil

+

+  when not defined(c_strlen):

+    proc c_strlen(a: CString): int {.nodecl, noSideEffect, importc: "strlen".}

+

+  let L = cstrlen(s)

+  result = newWideCString(s, L)

+

+proc newWideCString*(s: string): WideCString =

+  result = newWideCString(s, s.len)

+

+proc `$`*(w: wideCString, estimate: int): string =

+  result = newStringOfCap(estimate + estimate shr 2)

+

+  var i = 0

+  while w[i].int16 != 0'i16:

+    var ch = w[i].int

+    inc i

+    if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_HIGH_END:

+      # If the 16 bits following the high surrogate are in the source buffer...

+      let ch2 = w[i].int

+      # If it's a low surrogate, convert to UTF32:

+      if ch2 >=% UNI_SUR_LOW_START and ch2 <=% UNI_SUR_LOW_END:

+        ch = ((ch -% UNI_SUR_HIGH_START) shr halfShift) +%

+              (ch2 -% UNI_SUR_LOW_START) +% halfBase

+        inc i

+        

+    if ch <=% 127:

+      result.add chr(ch)

+    elif ch <=% 0x07FF:

+      result.add chr((ch shr 6) or 0b110_00000)

+      result.add chr((ch and ones(6)) or 0b10_000000)

+    elif ch <=% 0xFFFF:

+      result.add chr(ch shr 12 or 0b1110_0000)

+      result.add chr(ch shr 6 and ones(6) or 0b10_0000_00)

+      result.add chr(ch and ones(6) or 0b10_0000_00)

+    elif ch <=% 0x0010FFFF:

+      result.add chr(ch shr 18 or 0b1111_0000)

+      result.add chr(ch shr 12 and ones(6) or 0b10_0000_00)

+      result.add chr(ch shr 6 and ones(6) or 0b10_0000_00)

+      result.add chr(ch and ones(6) or 0b10_0000_00)

     else:

-      sysAssert(false, "") # cannot happen

-    

-  proc `$`*(s: WideCString): string =

-    result = s $ s.len

-    

-  proc allocWideCString*(s: string): WideCString =

-    ## free after usage with `dealloc`.

-    let cap = s.len+1

-    result = cast[wideCString](alloc0(cap * 2))

-    # special case: empty string: needed because MultiByteToWideChar

-    # return 0 in case of error:

-    if s.len == 0: return

-    # convert to utf-16 LE

-    let m = MultiByteToWideChar(CodePage = utf8Encoding, dwFlags = 0'i32, 

-                                lpMultiByteStr = cstring(s),

-                                cbMultiByte = cint(s.len),

-                                lpWideCharStr = result,

-                                cchWideChar = cint(cap))

-    if m == 0: raiseEncodingError()

-

-  proc allocWideCString*(s: cstring): WideCString =

-    ## free after usage with `dealloc`.

-    if s.isNil: return nil

-

-    when not defined(c_strlen):

-      proc c_strlen(a: CString): int {.nodecl, noSideEffect, importc: "strlen".}

-

-    let len = cstrlen(s)

-    let cap = len+1

-    result = cast[wideCString](alloc0(cap * 2))

-    # special case: empty string: needed because MultiByteToWideChar

-    # return 0 in case of error:

-    if s.len == 0: return

-    # convert to utf-16 LE

-    let m = MultiByteToWideChar(CodePage = utf8Encoding, dwFlags = 0'i32, 

-                                lpMultiByteStr = s,

-                                cbMultiByte = cint(len),

-                                lpWideCharStr = result,

-                                cchWideChar = cint(cap))

-    if m == 0: raiseEncodingError()

+      # replacement char:

+      result.add chr(0xFFFD shr 12 or 0b1110_0000)

+      result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00)

+      result.add chr(0xFFFD and ones(6) or 0b10_0000_00)

 

+proc `$`*(s: WideCString): string =

+  result = s $ 80

diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 1ea00c737..fa4925ee6 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -93,6 +93,8 @@ const
   
   SW_SHOWNORMAL* = 1'i32
   INVALID_HANDLE_VALUE* = THANDLE(-1)
+  
+  CREATE_UNICODE_ENVIRONMENT* = 1024'i32
 
 proc CloseHandle*(hObject: THANDLE): WINBOOL {.stdcall, dynlib: "kernel32",
     importc: "CloseHandle".}
@@ -116,7 +118,7 @@ when useWinUnicode:
                      lpProcessAttributes: ptr TSECURITY_ATTRIBUTES,
                      lpThreadAttributes: ptr TSECURITY_ATTRIBUTES,
                      bInheritHandles: WINBOOL, dwCreationFlags: int32,
-                     lpEnvironment: pointer, lpCurrentDirectory: widecstring,
+                     lpEnvironment, lpCurrentDirectory: widecstring,
                      lpStartupInfo: var TSTARTUPINFO,
                      lpProcessInformation: var TPROCESS_INFORMATION): WINBOOL{.
     stdcall, dynlib: "kernel32", importc: "CreateProcessW".}
diff --git a/web/news.txt b/web/news.txt
index 906fb1108..57963407d 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -31,9 +31,9 @@ Bugfixes
   floating point values.
 - SCGI module's performance has been improved greatly, it will no longer block
   on many concurrent requests.
-
 - In total fixed over 70 github issues and merged over 60 pull requests.
 
+
 Library Additions
 -----------------
 
@@ -60,6 +60,8 @@ Changes affecting backwards compatibility
 - The expression/statement unification has been implemented. Again this
   only affects edge cases and no known real world code.
 - Changed the async interface of the ``scgi`` module.
+- WideStrings are now garbage collected like other string types.
+
 
 Compiler Additions
 ------------------