Index: src/branch.c
==================================================================
--- src/branch.c
+++ src/branch.c
@@ -1,7 +1,7 @@
 /*
-** Copyright (c) 2007 D. Richard Hipp
+** Copyright © 2007 D. Richard Hipp
 **
 ** This program is free software; you can redistribute it and/or
 ** modify it under the terms of the Simplified BSD License (also
 ** known as the "2-Clause License" or "FreeBSD License".)
 
@@ -355,11 +355,11 @@
       cnt++;
     }
     if( colorTest ){
       const char *zColor = hash_color(zBr);
       @ <li><span style="background-color: %s(zColor)">
-      @ %h(zBr) &rarr; %s(zColor)</span></li>
+      @ %h(zBr) → %s(zColor)</span></li>
     }else{
       @ <li>%z(href("%R/timeline?r=%T",zBr))%h(zBr)</a></li>
     }
   }
   if( cnt ){

Index: src/export.c
==================================================================
--- src/export.c
+++ src/export.c
@@ -1,7 +1,7 @@
 /*
-** Copyright (c) 2010 D. Richard Hipp
+** Copyright © 2010 D. Richard Hipp
 **
 ** This program is free software; you can redistribute it and/or
 ** modify it under the terms of the Simplified BSD License (also
 ** known as the "2-Clause License" or "FreeBSD License".)
 
@@ -136,11 +136,11 @@
   if( markfile_in!=0 ){
     Stmt qb,qc;
     char line[100];
     FILE *f;
 
-    f = fopen(markfile_in, "r");
+    f = fossil_fopen(markfile_in, "r");
     if( f==0 ){
       fossil_panic("cannot open %s for reading", markfile_in);
     }
     db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)");
     db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)");
@@ -325,11 +325,11 @@
   db_finalize(&q);
   bag_clear(&vers);
 
   if( markfile_out!=0 ){
     FILE *f;
-    f = fopen(markfile_out, "w");
+    f = fossil_fopen(markfile_out, "w");
     if( f == 0 ){
       fossil_panic("cannot open %s for writing", markfile_out);
     }
     db_prepare(&q, "SELECT rid FROM oldblob");
     while( db_step(&q)==SQLITE_ROW ){

Index: src/file.c
==================================================================
--- src/file.c
+++ src/file.c
@@ -1,7 +1,7 @@
 /*
-** Copyright (c) 2006 D. Richard Hipp
+** Copyright © 2006 D. Richard Hipp
 **
 ** This program is free software; you can redistribute it and/or
 ** modify it under the terms of the Simplified BSD License (also
 ** known as the "2-Clause License" or "FreeBSD License".)
 
@@ -32,10 +32,11 @@
 
 /*
 ** On Windows, include the Platform SDK header file.
 */
 #ifdef _WIN32
+# include <direct.h>
 # include <windows.h>
 #endif
 
 /*
 ** The file status information from the most recent stat() call.
@@ -68,12 +69,12 @@
   }else{
     return stat(zFilename, buf);
   }
 #else
   int rc = 0;
-  char *zMbcs = fossil_utf8_to_mbcs(zFilename);
-  rc = stat(zMbcs, buf);
+  wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename);
+  rc = _wstati64(zMbcs, buf);
   fossil_mbcs_free(zMbcs);
   return rc;
 #endif
 }
 
@@ -298,13 +299,17 @@
 
 /*
 ** Wrapper around the access() system call.
 */
 int file_access(const char *zFilename, int flags){
-  char *zMbcs = fossil_utf8_to_mbcs(zFilename);
-  int rc = access(zMbcs, flags);
+#ifdef _WIN32
+  wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename);
+  int rc = _waccess(zMbcs, flags);
   fossil_mbcs_free(zMbcs);
+#else
+  int rc = access(zFilename, flags);
+#endif
   return rc;
 }
 
 /*
 ** Find an unused filename similar to zBase with zSuffix appended.
@@ -389,13 +394,17 @@
 
 /*
 ** Delete a file.
 */
 void file_delete(const char *zFilename){
-  char *z = fossil_utf8_to_mbcs(zFilename);
-  unlink(z);
+#ifdef _WIN32
+  wchar_t *z = fossil_utf8_to_unicode(zFilename);
+  _wunlink(z);
   fossil_mbcs_free(z);
+#else
+  unlink(zFilename);
+#endif
 }
 
 /*
 ** Create the directory named in the argument, if it does not already
 ** exist.  If forceFlag is 1, delete any prior non-directory object 
@@ -410,12 +419,12 @@
     file_delete(zName);
   }
   if( rc!=1 ){
 #if defined(_WIN32)
     int rc;
-    char *zMbcs = fossil_utf8_to_mbcs(zName);
-    rc = mkdir(zMbcs);
+    wchar_t *zMbcs = fossil_utf8_to_unicode(zName);
+    rc = _wmkdir(zMbcs);
     fossil_mbcs_free(zMbcs);
     return rc;
 #else
     return mkdir(zName, 0755);
 #endif
@@ -561,24 +570,24 @@
 }
 
 /*
 ** Get the current working directory.
 **
-** On windows, the name is converted from MBCS to UTF8 and all '\\'
+** On windows, the name is converted from unicode to UTF8 and all '\\'
 ** characters are converted to '/'.  No conversions are needed on
 ** unix.
 */
 void file_getcwd(char *zBuf, int nBuf){
 #ifdef _WIN32
   char *zPwdUtf8;
   int nPwd;
   int i;
-  char zPwd[2000];
-  if( getcwd(zPwd, sizeof(zPwd)-1)==0 ){
+  wchar_t zPwd[2000];
+  if( _wgetcwd(zPwd, sizeof(zPwd)-1)==0 ){
     fossil_fatal("cannot find the current working directory.");
   }
-  zPwdUtf8 = fossil_mbcs_to_utf8(zPwd);
+  zPwdUtf8 = fossil_unicode_to_utf8(zPwd);
   nPwd = strlen(zPwdUtf8);
   if( nPwd > nBuf-1 ){
     fossil_fatal("pwd too big: max %d\n", nBuf-1);
   }
   for(i=0; zPwdUtf8[i]; i++) if( zPwdUtf8[i]=='\\' ) zPwdUtf8[i] = '/';
@@ -928,14 +937,14 @@
   unsigned int i, j;
   const char *zDir = ".";
   int cnt = 0;
 
 #if defined(_WIN32)
-  char zTmpPath[MAX_PATH];
+  wchar_t zTmpPath[MAX_PATH];
 
-  if( GetTempPath(sizeof(zTmpPath), zTmpPath) ){
-    azDirs[0] = zTmpPath;
+  if( GetTempPathW(MAX_PATH, zTmpPath) ){
+    azDirs[0] = fossil_unicode_to_utf8(zTmpPath);
   }
 
   azDirs[1] = fossil_getenv("TEMP");
   azDirs[2] = fossil_getenv("TMP");
 #endif
@@ -1014,10 +1023,29 @@
   return sqlite3_win32_mbcs_to_utf8(zMbcs);
 #else
   return (char*)zMbcs;  /* No-op on unix */
 #endif  
 }
+
+/*
+** Translate Unicode to UTF8.  Return a pointer to the translated text.
+** Call fossil_mbcs_free() to deallocate any memory used to store the
+** returned pointer when done.
+*/
+char *fossil_unicode_to_utf8(const void *zUnicode){
+#ifdef _WIN32
+  int nByte = WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, 0, 0, 0, 0);
+  char *zUtf = sqlite3_malloc( nByte );
+  if( zUtf==0 ){
+    return 0;
+  }
+  WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, zUtf, nByte, 0, 0);
+  return zUtf;
+#else
+  return (char *)zUnicode;  /* No-op on unix */
+#endif
+}
 
 /*
 ** Translate UTF8 to MBCS for use in system calls.  Return a pointer to the
 ** translated text..  Call fossil_mbcs_free() to deallocate any memory
 ** used to store the returned pointer when done.
@@ -1028,18 +1056,41 @@
   return sqlite3_win32_utf8_to_mbcs(zUtf8);
 #else
   return (char*)zUtf8;  /* No-op on unix */
 #endif  
 }
+
+/*
+** Translate UTF8 to unicode for use in system calls.  Return a pointer to the
+** translated text..  Call fossil_mbcs_free() to deallocate any memory
+** used to store the returned pointer when done.
+*/
+void *fossil_utf8_to_unicode(const char *zUtf8){
+#ifdef _WIN32
+  int nByte = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
+  wchar_t *zUnicode = sqlite3_malloc( nByte * 2 );
+  if( zUnicode==0 ){
+    return 0;
+  }
+  MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
+  return zUnicode;
+#else
+  return (void *)zUtf8;  /* No-op on unix */
+#endif
+}
 
 /*
 ** Return the value of an environment variable as UTF8.
 */
 char *fossil_getenv(const char *zName){
-  char *zValue = getenv(zName);
 #ifdef _WIN32
-  if( zValue ) zValue = fossil_mbcs_to_utf8(zValue);
+  wchar_t *uName = fossil_utf8_to_unicode(zName);
+  void *zValue = _wgetenv(uName);
+  fossil_mbcs_free(uName);
+  if( zValue ) zValue = fossil_unicode_to_utf8(zValue);
+#else
+  char *zValue = getenv(zName);
 #endif
   return zValue;
 }
 
 /*
@@ -1085,11 +1136,11 @@
 
 /*
 ** Translate MBCS to UTF8.  Return a pointer.  Call fossil_mbcs_free()
 ** to deallocate any memory used to store the returned pointer when done.
 */
-void fossil_mbcs_free(char *zOld){
+void fossil_mbcs_free(void *zOld){
 #ifdef _WIN32
   extern void sqlite3_free(void*);
   sqlite3_free(zOld);
 #else
   /* No-op on unix */
@@ -1098,10 +1149,16 @@
 
 /*
 ** Like fopen() but always takes a UTF8 argument.
 */
 FILE *fossil_fopen(const char *zName, const char *zMode){
-  char *zMbcs = fossil_utf8_to_mbcs(zName);
-  FILE *f = fopen(zMbcs, zMode);
-  fossil_mbcs_free(zMbcs);
+#ifdef _WIN32
+  wchar_t *uMode = fossil_utf8_to_unicode(zMode);
+  wchar_t *uName = fossil_utf8_to_unicode(zName);
+  FILE *f = _wfopen(uName, uMode);
+  fossil_mbcs_free(uName);
+  fossil_mbcs_free(uMode);
+#else
+  FILE *f = fopen(zName, zMode);
+#endif
   return f;
 }

Index: src/import.c
==================================================================
--- src/import.c
+++ src/import.c
@@ -1,7 +1,7 @@
 /*
-** Copyright (c) 2010 D. Richard Hipp
+** Copyright © 2010 D. Richard Hipp
 **
 ** This program is free software; you can redistribute it and/or
 ** modify it under the terms of the Simplified BSD License (also
 ** known as the "2-Clause License" or "FreeBSD License".)
 
@@ -732,11 +732,11 @@
   verify_all_options();
   if( g.argc!=3  && g.argc!=4 ){
     usage("REPOSITORY-NAME");
   }
   if( g.argc==4 ){
-    pIn = fopen(g.argv[3], "rb");
+    pIn = fossil_fopen(g.argv[3], "rb");
   }else{
     pIn = stdin;
     fossil_binary_mode(pIn);
   }
   if( !incrFlag ){

Index: src/rebuild.c
==================================================================
--- src/rebuild.c
+++ src/rebuild.c
@@ -21,10 +21,19 @@
 #include "rebuild.h"
 #include <assert.h>
 #include <dirent.h>
 #include <errno.h>
 
+#ifndef _WIN32
+#define _WDIR DIR
+#define _wdirent dirent
+#define _wopendir opendir
+#define _wreaddir readdir
+#define _wclosedir closedir
+#define wchar_t char
+#endif
+
 /*
 ** Make changes to the stable part of the schema (the part that is not
 ** simply deleted and reconstructed on a rebuild) to bring the schema
 ** up to the latest.
 */
@@ -818,28 +827,28 @@
 /*
 ** Recursively read all files from the directory zPath and install
 ** every file read as a new artifact in the repository.
 */
 void recon_read_dir(char *zPath){
-  DIR *d;
-  struct dirent *pEntry;
+  _WDIR *d;
+  struct _wdirent *pEntry;
   Blob aContent; /* content of the just read artifact */
   static int nFileRead = 0;
-  char *zMbcsPath;
+  wchar_t *zMbcsPath;
   char *zUtf8Name;
 
-  zMbcsPath = fossil_utf8_to_mbcs(zPath);
-  d = opendir(zMbcsPath);
+  zMbcsPath = fossil_utf8_to_unicode(zPath);
+  d = _wopendir(zMbcsPath);
   if( d ){
-    while( (pEntry=readdir(d))!=0 ){
+    while( (pEntry=_wreaddir(d))!=0 ){
       Blob path;
       char *zSubpath;
 
       if( pEntry->d_name[0]=='.' ){
         continue;
       }
-      zUtf8Name = fossil_mbcs_to_utf8(pEntry->d_name);
+      zUtf8Name = fossil_unicode_to_utf8(pEntry->d_name);
       zSubpath = mprintf("%s/%s", zPath, zUtf8Name);
       fossil_mbcs_free(zUtf8Name);
       if( file_isdir(zSubpath)==1 ){
         recon_read_dir(zSubpath);
       }
@@ -854,11 +863,11 @@
       blob_reset(&aContent);
       free(zSubpath);
       fossil_print("\r%d", ++nFileRead);
       fflush(stdout);
     }
-    closedir(d);
+    _wclosedir(d);
   }else {
     fossil_panic("encountered error %d while trying to open \"%s\".",
                   errno, g.argv[3]);
   }
   fossil_mbcs_free(zMbcsPath);

Index: src/setup.c
==================================================================
--- src/setup.c
+++ src/setup.c
@@ -1,7 +1,7 @@
 /*
-** Copyright (c) 2007 D. Richard Hipp
+** Copyright © 2007 D. Richard Hipp
 **
 ** This program is free software; you can redistribute it and/or
 ** modify it under the terms of the Simplified BSD License (also
 ** known as the "2-Clause License" or "FreeBSD License".)
 
@@ -496,38 +496,38 @@
   if( fossil_strcmp(zLogin, "developer") ){
     char *z1, *z2;
     z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='developer'");
     while( z1 && *z1 ){
       inherit[0x7f & *(z1++)] =
-         "<span class=\"ueditInheritDeveloper\">&bull;</span>";
+         "<span class=\"ueditInheritDeveloper\">•</span>";
     }
     free(z2);
   }
   if( fossil_strcmp(zLogin, "reader") ){
     char *z1, *z2;
     z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='reader'");
     while( z1 && *z1 ){
       inherit[0x7f & *(z1++)] =
-          "<span class=\"ueditInheritReader\">&bull;</span>";
+          "<span class=\"ueditInheritReader\">•</span>";
     }
     free(z2);
   }
   if( fossil_strcmp(zLogin, "anonymous") ){
     char *z1, *z2;
     z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='anonymous'");
     while( z1 && *z1 ){
       inherit[0x7f & *(z1++)] =
-           "<span class=\"ueditInheritAnonymous\">&bull;</span>";
+           "<span class=\"ueditInheritAnonymous\">•</span>";
     }
     free(z2);
   }
   if( fossil_strcmp(zLogin, "nobody") ){
     char *z1, *z2;
     z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='nobody'");
     while( z1 && *z1 ){
       inherit[0x7f & *(z1++)] =
-           "<span class=\"ueditInheritNobody\">&bull;</span>";
+           "<span class=\"ueditInheritNobody\">•</span>";
     }
     free(z2);
   }
 
   /* Begin generating the page
@@ -662,30 +662,30 @@
   @ and reset user passwords.  Both automatically get all other privileges
   @ listed below.  Use these two settings with discretion.
   @ </p></li>
   @
   @ <li><p>
-  @ The "<span class="ueditInheritNobody"><big>&bull;</big></span>" mark
+  @ The "<span class="ueditInheritNobody"><big>•</big></span>" mark
   @ indicates the privileges of <span class="usertype">nobody</span> that
   @ are available to all users regardless of whether or not they are logged in.
   @ </p></li>
   @
   @ <li><p>
-  @ The "<span class="ueditInheritAnonymous"><big>&bull;</big></span>" mark
+  @ The "<span class="ueditInheritAnonymous"><big>•</big></span>" mark
   @ indicates the privileges of <span class="usertype">anonymous</span> that
   @ are inherited by all logged-in users.
   @ </p></li>
   @
   @ <li><p>
-  @ The "<span class="ueditInheritDeveloper"><big>&bull;</big></span>" mark
+  @ The "<span class="ueditInheritDeveloper"><big>•</big></span>" mark
   @ indicates the privileges of <span class="usertype">developer</span> that
   @ are inherited by all users with the
   @ <span class="capability">Developer</span> privilege.
   @ </p></li>
   @
   @ <li><p>
-  @ The "<span class="ueditInheritReader"><big>&bull;</big></span>" mark
+  @ The "<span class="ueditInheritReader"><big>•</big></span>" mark
   @ indicates the privileges of <span class="usertype">reader</span> that
   @ are inherited by all users with the <span class="capability">Reader</span>
   @ privilege.
   @ </p></li>
   @
@@ -1616,16 +1616,16 @@
   style_header("Raw SQL Commands");
   @ <p><b>Caution:</b> There are no restrictions on the SQL that can be
   @ run by this page.  You can do serious and irrepairable damage to the
   @ repository.  Proceed with extreme caution.</p>
   @
-  @ <p>Database names:<ul><li>repository &rarr; %s(db_name("repository"))
+  @ <p>Database names:<ul><li>repository → %s(db_name("repository"))
   if( g.configOpen ){
-    @ <li>config &rarr; %s(db_name("configdb"))
+    @ <li>config → %s(db_name("configdb"))
   }
   if( g.localOpen ){
-    @ <li>local-checkout &rarr; %s(db_name("localdb"))
+    @ <li>local-checkout → %s(db_name("localdb"))
   }
   @ </ul></p>
   @
   @ <form method="post" action="%s(g.zTop)/admin_sql">
   login_insert_csrf_secret();

Index: src/timeline.c
==================================================================
--- src/timeline.c
+++ src/timeline.c
@@ -1,7 +1,7 @@
 /*
-** Copyright (c) 2007 D. Richard Hipp
+** Copyright © 2007 D. Richard Hipp
 **
 ** This program is free software; you can redistribute it and/or
 ** modify it under the terms of the Simplified BSD License (also
 ** known as the "2-Clause License" or "FreeBSD License".)
 
@@ -318,11 +318,11 @@
       @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
     }else{
       @ <td class="timelineTableCell">
     }
     if( pGraph && zType[0]!='c' ){
-      @ &bull;
+      @ •
     }
     if( zType[0]=='c' ){
       hyperlink_to_uuid(zUuid);
       if( isLeaf ){
         if( db_exists("SELECT 1 FROM tagxref"
@@ -436,16 +436,16 @@
           @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew))
           @ [view]</a></li>
         }else if( isDel ){
           @ <li> %h(zFilename) (deleted)</li>
         }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){
-          @ <li> %h(zOldName) &rarr; %h(zFilename)
+          @ <li> %h(zOldName) → %h(zFilename)
           @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew))
           @ [view]</a></li>
         }else{
           if( zOldName!=0 ){
-            @ <li> %h(zOldName) &rarr; %h(zFilename)
+            @ <li> %h(zOldName) → %h(zFilename)
           }else{
             @ <li> %h(zFilename) &nbsp;
           }
           @ %z(xhref("target='diffwindow'","%R/fdiff?v1=%S&v2=%S",zOld,zNew))
           @ [diff]</a></li>

Index: src/translate.c
==================================================================
--- src/translate.c
+++ src/translate.c
@@ -1,7 +1,7 @@
 /*
-** Copyright (c) 2002 D. Richard Hipp
+** Copyright © 2002 D. Richard Hipp
 **
 ** This program is free software; you can redistribute it and/or
 ** modify it under the terms of the Simplified BSD License (also
 ** known as the "2-Clause License" or "FreeBSD License".)
 
@@ -76,17 +76,34 @@
   char c1, c2;          /* Characters used to start a comment */
   int lastWasEq = 0;    /* True if last non-whitespace character was "=" */
   int lastWasComma = 0; /* True if last non-whitespace character was "," */
   char zLine[2000];     /* A single line of input */
   char zOut[4000];      /* The input line translated into appropriate output */
+  int isFirstline = 1;  /* True if this is the first line */
 
   c1 = c2 = '-';
   while( fgets(zLine, sizeof(zLine), in) ){
+    if (isFirstline) {
+      static const char bom[] = { 0xEF, 0xBB, 0xBF };
+      if( memcmp(zLine, bom, 3)==0 ) {
+    	  memmove(zLine, zLine+3, sizeof(zLine)-3);
+      }
+      isFirstline = 0;
+    }
     for(i=0; zLine[i] && isspace(zLine[i]); i++){}
     if( zLine[i]!='@' ){
       if( inPrint || inStr ) end_block(out);
-      fprintf(out,"%s",zLine);
+      for(i=0,j=0; zLine[i]; i++){
+        if (128 <= (unsigned char)zLine[i]) {
+          sprintf(&zOut[j], "\\0x%.2X", zLine[i] & 0xFF);
+          j += 5;
+        } else {
+          zOut[j++] = zLine[i];
+        }
+      }
+      zOut[j] = 0;
+      fprintf(out,"%s",zOut);
                        /* 0123456789 12345 */
       if( strncmp(zLine, "/* @-comment: ", 14)==0 ){
         c1 = zLine[14];
         c2 = zLine[15];
       }
@@ -110,11 +127,16 @@
       for(j=0; zLine[i] && zLine[i]!='\r' && zLine[i]!='\n'; i++){
         if( zLine[i]==c1 && (c2==' ' || zLine[i+1]==c2) ){
            omitline = 1; break; 
         }
         if( zLine[i]=='"' || zLine[i]=='\\' ){ zOut[j++] = '\\'; }
-        zOut[j++] = zLine[i];
+        if (128 <= (unsigned char)zLine[i]) {
+          sprintf(&zOut[j], "\\0x%.2X", zLine[i] & 0xFF);
+          j += 5;
+        } else {
+          zOut[j++] = zLine[i];
+        }
       }
       while( j>0 && isspace(zOut[j-1]) ){ j--; }
       zOut[j] = 0;
       if( j<=0 && omitline ){
         fprintf(out,"\n");
@@ -134,11 +156,16 @@
       i++;
       if( isspace(zLine[i]) ){ i++; }
       indent = i;
       for(j=0; zLine[i] && zLine[i]!='\r' && zLine[i]!='\n'; i++){
         if( zLine[i]=='"' || zLine[i]=='\\' ){ zOut[j++] = '\\'; }
-        zOut[j++] = zLine[i];
+        if (128 <= (unsigned char)zLine[i]) {
+          sprintf(&zOut[j], "\\0x%.2X", zLine[i] & 0xFF);
+          j += 5;
+        } else {
+          zOut[j++] = zLine[i];
+        }
         if( zLine[i]!='%' || zLine[i+1]=='%' || zLine[i+1]==0 ) continue;
         for(nC=1; zLine[i+nC] && zLine[i+nC]!='('; nC++){}
         if( zLine[i+nC]!='(' || !isalpha(zLine[i+nC-1]) ) continue;
         while( --nC ) zOut[j++] = zLine[++i];
         zArg[nArg++] = ',';

Index: src/vfile.c
==================================================================
--- src/vfile.c
+++ src/vfile.c
@@ -25,10 +25,19 @@
 #include "dirent.h"
 #else
 #include <dirent.h>
 #endif
 
+#ifndef _WIN32
+#define _WDIR DIR
+#define _wdirent dirent
+#define _wopendir opendir
+#define _wreaddir readdir
+#define _wclosedir closedir
+#define wchar_t char
+#endif
+
 /*
 ** The input is guaranteed to be a 40-character well-formed UUID.
 ** Find its rid.
 */
 int fast_uuid_to_rid(const char *zUuid){
@@ -381,18 +390,18 @@
 ** Any files or directories that match the glob pattern pIgnore are 
 ** excluded from the scan.  Name matching occurs after the first
 ** nPrefix characters are elided from the filename.
 */
 void vfile_scan(Blob *pPath, int nPrefix, int allFlag, Glob *pIgnore){
-  DIR *d;
+  _WDIR *d;
   int origSize;
   const char *zDir;
-  struct dirent *pEntry;
+  struct _wdirent *pEntry;
   int skipAll = 0;
   static Stmt ins;
   static int depth = 0;
-  char *zMbcs;
+  wchar_t *zMbcs;
 
   origSize = blob_size(pPath);
   if( pIgnore ){
     blob_appendf(pPath, "/");
     if( glob_match(pIgnore, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
@@ -407,22 +416,22 @@
     );
   }
   depth++;
 
   zDir = blob_str(pPath);
-  zMbcs = fossil_utf8_to_mbcs(zDir);
-  d = opendir(zMbcs);
+  zMbcs = fossil_utf8_to_unicode(zDir);
+  d = _wopendir(zMbcs);
   if( d ){
-    while( (pEntry=readdir(d))!=0 ){
+    while( (pEntry=_wreaddir(d))!=0 ){
       char *zPath;
       char *zUtf8;
       if( pEntry->d_name[0]=='.' ){
         if( !allFlag ) continue;
         if( pEntry->d_name[1]==0 ) continue;
         if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
       }
-      zUtf8 = fossil_mbcs_to_utf8(pEntry->d_name);
+      zUtf8 = fossil_unicode_to_utf8(pEntry->d_name);
       blob_appendf(pPath, "/%s", zUtf8);
       fossil_mbcs_free(zUtf8);
       zPath = blob_str(pPath);
       if( glob_match(pIgnore, &zPath[nPrefix+1]) ){
         /* do nothing */
@@ -435,11 +444,11 @@
         db_step(&ins);
         db_reset(&ins);
       }
       blob_resize(pPath, origSize);
     }
-    closedir(d);
+    _wclosedir(d);
   }
   fossil_mbcs_free(zMbcs);
 
   depth--;
   if( depth==0 ){

Index: src/wikiformat.c
==================================================================
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1,7 +1,7 @@
 /*
-** Copyright (c) 2007 D. Richard Hipp
+** Copyright © 2007 D. Richard Hipp
 **
 ** This program is free software; you can redistribute it and/or
 ** modify it under the terms of the Simplified BSD License (also
 ** known as the "2-Clause License" or "FreeBSD License".)
 
@@ -1190,11 +1190,11 @@
         p->state |= AT_NEWLINE;
         break;
       }
       case TOKEN_BUL_LI: {
         if( inlineOnly ){
-          blob_append(p->pOut, " &bull; ", -1);
+          blob_append(p->pOut, " • ", -1);
         }else{
           if( p->wikiList!=MARKUP_UL ){
             if( p->wikiList ){
               popStackToTag(p, p->wikiList);
             }
@@ -1410,18 +1410,18 @@
           p->state &= ~ALLOW_WIKI;
           for (vAttrIdx = 0; vAttrIdx < markup.nAttr; vAttrIdx++){
             if( markup.aAttr[vAttrIdx].iACode == ATTR_ID ){
               p->zVerbatimId = markup.aAttr[0].zValue;
             }else if( markup.aAttr[vAttrIdx].iACode == ATTR_TYPE ){
-              blob_appendf(p->pOut, "<pre name='code' class='%s'>",
+              blob_appendf(p->pOut, "<pre name=\"code\" class=\"%s\">",
                 markup.aAttr[vAttrIdx].zValue);
               vAttrDidAppend=1;
             }
           }
           if( !vAttrDidAppend ) {
             endAutoParagraph(p);
-            blob_append(p->pOut, "<pre class='verbatim'>",-1);
+            blob_append(p->pOut, "<pre class=\"verbatim\">",-1);
           }
           p->wantAutoParagraph = 0;
         }else
         if( markup.iType==MUTYPE_LI ){
           if( backupToType(p, MUTYPE_LIST)==0 ){