Index: Plugins/Qt/qt_chooser_widget.cpp
===================================================================
--- Plugins/Qt/qt_chooser_widget.cpp	(revision 7973)
+++ Plugins/Qt/qt_chooser_widget.cpp	(working copy)
@@ -210,8 +210,7 @@
 void
 qt_chooser_widget_rep::perform_dialog () {
   QString caption = to_qstring (win_title);
-  c_string tmp (directory * "/" * file);
-  QString path = QString::fromLocal8Bit (tmp);
+  QString    path = to_qstring (directory * "/" * file);
   
 #if (defined(Q_WS_MAC) || defined(Q_WS_WIN))
   QFileDialog* dialog = new QFileDialog (NULL, caption, path);
@@ -263,14 +262,9 @@
   if (dialog->exec ()) {
     fileNames = dialog->selectedFiles();
     if (fileNames.count() > 0) {
-      url u = url_system (scm_unquote (from_qstring (fileNames.first())));
-        // FIXME: charset detection in to_qstring() (if that hack is still there)
-        // fails sometimes, so we bypass it to force the proper (?) conversions here.
-      //QByteArray arr   = to_qstring (as_string (u)).toLocal8Bit ();
-      QByteArray arr   = utf8_to_qstring (cork_to_utf8 (as_string (u))).toLocal8Bit ();
-      const char* cstr = arr.constData ();
-      string localname = string ((char*) cstr);
-      file = "(system->url " * scm_quote (localname) * ")";
+        // FIXME: not all filesystems / operating systems use UTF8 to encode filenames
+      url u = url_system (from_qstring (fileNames.first()));
+      file = "(system->url " * scm_quote (as_string (u)) * ")";
       if (type == "image") {
 #if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
         file = "(list " * file * imgdialog->getParamsAsString () * ")";
Index: Plugins/Qt/qt_sys_utils.cpp
===================================================================
--- Plugins/Qt/qt_sys_utils.cpp	(revision 7973)
+++ Plugins/Qt/qt_sys_utils.cpp	(working copy)
@@ -10,6 +10,7 @@
 ******************************************************************************/
 
 #include "qt_sys_utils.hpp"
+#include "qt_utilities.hpp"
 #include "basic.hpp"
 #include "string.hpp"
 
@@ -27,14 +28,7 @@
   QProcess proc;
 
   proc.setProcessChannelMode (QProcess::MergedChannels);
-  c_string _cmd (cmd);
-#if defined (__MINGW__) || defined (__MINGW32__)
-  QString qcmd = QString::fromLocal8Bit (_cmd);
-#else
-  QString qcmd = "sh -c \"";
-  qcmd += _cmd;
-  qcmd += "\"";
-#endif
+  QString qcmd = to_qstring ("sh -c \"" * cmd * "\"");
   proc.start (qcmd);
   if (! proc.waitForStarted ()) {
     if (DEBUG_STD) debug_shell << "System: failed to launch command\n";
Index: Plugins/Qt/qt_utilities.cpp
===================================================================
--- Plugins/Qt/qt_utilities.cpp	(revision 7973)
+++ Plugins/Qt/qt_utilities.cpp	(working copy)
@@ -289,21 +289,9 @@
   return ql;
 }
 
-/* HACK!!! Something has to be done wrt. to internal encoding: most of the times
- it's cork, but often it's utf8. For instance when the title is built in a tmfs
- title handler in scheme, it is sent to us as an utf8 string. Should we convert
- before? Another example are items in the go-menu: file names are internally
- stored as utf8, but we assume that strings are sent to us for display in
- widgets as cork and thus display the wrong encoding.
- 
- It gets tricky soon, so for the time being we use this hack.
- */
 QString
 to_qstring (const string& s) {
-  if (looks_utf8 (s) && !(looks_ascii (s) || looks_universal (s)))
-    return utf8_to_qstring (s);
-  else
-    return utf8_to_qstring (cork_to_utf8 (s));
+  return utf8_to_qstring (cork_to_utf8 (s));
 }
 
 QString
Index: Plugins/X11/x_window.cpp
===================================================================
--- Plugins/X11/x_window.cpp	(revision 7971)
+++ Plugins/X11/x_window.cpp	(working copy)
@@ -13,6 +13,8 @@
 #include "message.hpp"
 #include "boot.hpp"
 #include "x_picture.hpp"
+#include "converter.hpp"
+#include "language.hpp"
 
 extern int nr_windows;
 
@@ -305,7 +307,7 @@
 
 void
 x_window_rep::set_name (string name) {
-  c_string s (name);
+  c_string s (cork_to_utf8 (name)); // FIXME: use correct encoding (which one?)
   XStoreName (dpy, win, s);
   XSetIconName (dpy, win, s);
   the_name= name;
Index: System/Classes/url.cpp
===================================================================
--- System/Classes/url.cpp	(revision 7971)
+++ System/Classes/url.cpp	(working copy)
@@ -67,7 +67,7 @@
 
 #include <ctype.h>
 
-#if defined(OS_WIN32)  || defined(__MINGW32__)
+#if defined(OS_WIN32) || defined(__MINGW32__)
 #define WINPATHS
 #endif
 
@@ -84,8 +84,8 @@
 ******************************************************************************/
 
 static url
-url_get_atom (string s, int type) {
-  if (type < URL_STANDARD) {
+url_get_atom (string s, url_types type) {
+  if (type != URL_STANDARD) {
     if (s == "~") return url_system (get_env ("HOME"));
     if (starts (s, "$")) {
       string val= get_env (s (1, N(s)));
@@ -98,7 +98,7 @@
 }
 
 static url
-url_get_name (string s, int type= URL_STANDARD, int i=0) {
+url_get_name (string s, url_types type= URL_STANDARD, int i=0) {
   char sep= (type == URL_SYSTEM)? URL_CONCATER: '/';
   int start= i, n= N(s);
   while ((i<n) && (s[i] != sep) && (s[i] != '/')) i++;
@@ -110,7 +110,7 @@
 }
 
 static url
-url_get_path (string s, int type= URL_STANDARD, int i=0) {
+url_get_path (string s, url_types type= URL_STANDARD, int i=0) {
   char sep= (type == URL_SYSTEM)? URL_SEPARATOR: ':';
   int start= i, n= N(s);
   if (i == n) return url_none ();
@@ -136,7 +136,7 @@
 }
 
 static url
-url_default (string name, int type= URL_SYSTEM) {
+url_default (string name, url_types type= URL_SYSTEM) {
   url u= url_get_name (name, type);
 #ifdef WINPATHS
   // FIXME: this hack seems a bit too simple
@@ -150,13 +150,13 @@
 }
 
 static url
-url_mingw_default (string name, int type) {
+url_mingw_default (string name, url_types type) {
   string s= name (0, 2) * ":" * name (2, N(name));
   return url_root ("default") * url_get_name (s, type);  
 }
 
 static url
-url_path (string s, int type= URL_SYSTEM) {
+url_path (string s, url_types type= URL_SYSTEM) {
   url u= url_get_path (s, type);
   return u;
 }
@@ -208,8 +208,8 @@
 ******************************************************************************/
 
 static bool
-heuristic_is_path (string name, int type) {
-  char sep= (type==0)? URL_SEPARATOR: ':';
+heuristic_is_path (string name, url_types type) {
+  char sep= (type==URL_SYSTEM)? URL_SEPARATOR: ':';
   int i, n= N(name);
   for (i=0; i<n; i++)
     if (name[i] == sep)
@@ -218,7 +218,7 @@
 }
 
 static bool
-heuristic_is_default (string name, int type) {
+heuristic_is_default (string name, url_types type) {
 #ifdef WINPATHS
   // FIXME: we probably should take into account 'type' too
   if (N(name) < 2) return false;
@@ -227,7 +227,7 @@
     isalpha (name[0]) && (name[1] == ':') &&
     ((N(name)==2) || (name[2] == '\\') || (name[2] == '/'));
 #else
-  char sep= (type==0)? URL_CONCATER: '/';
+  char sep= (type==URL_SYSTEM)? URL_CONCATER: '/';
   return (name != "") && (name[0] == sep);
 #endif
 }
@@ -244,7 +244,7 @@
 }
 
 static bool
-heuristic_is_mingw_default (string name, int type) {
+heuristic_is_mingw_default (string name, url_types type) {
 #ifdef WINPATHS
   return type != URL_SYSTEM && N(name) >= 2 &&
          name[0] == '/' && is_alpha (name[1]) &&
@@ -255,7 +255,7 @@
 }
 
 url
-url_general (string name, int type= URL_SYSTEM) {
+url_general (string name, url_types type= URL_SYSTEM) {
   if (starts (name, "local:")) return url_local (name (6, N (name)));
   if (starts (name, "file://")) return url_file (name (7, N (name)));
   if (starts (name, "http://")) return url_http (name (7, N (name)));
@@ -273,7 +273,7 @@
 
 url
 url_unix (string name) {
-  return url_general (name, URL_UNIX);
+  return url_general (convert_to_filesystem_encoding (name), URL_UNIX);
 }
 
 url
@@ -283,7 +283,7 @@
 
 url
 url_system (string name) {
-  return url_general (name, URL_SYSTEM);
+  return url_general (convert_to_filesystem_encoding (name), URL_SYSTEM);
 }
 
 url
@@ -293,6 +293,8 @@
 
 url
 url_standard (string name) {
+    //TODO: escape colons, spaces, etc, as per web standards.
+    //return url_general (convert_to_web_encoding (name), URL_STANDARD);
   return url_general (name, URL_STANDARD);
 }
 
@@ -477,14 +479,54 @@
 ******************************************************************************/
 
 string
-as_string (url u, int type) {
-  // This routine pritty prints an url as a string.
+convert_from_filesystem_encoding (string s) {
+#if defined (OS_MACOS) || defined (OS_GNU_LINUX)
+//  if (s != utf8_to_cork(s))
+//    cout << "FROM: " << s << " --> " << utf8_to_cork(s) << LF;
+  return utf8_to_cork (s);
+#elif defined OS_WIN32 || defined (__MINGW__) || defined (__MINGW32__)
+  /* FIXME: NTFS/FATxx use different encodings. See:
+http://msdn.microsoft.com/en-us/library/windows/desktop/dd317748%28v=vs.85%29.aspx
+   */
+  return s;
+#else
+  return s;
+#endif
+}
+
+string
+convert_to_filesystem_encoding (string s) {
+#if defined (OS_MACOS) || defined (OS_GNU_LINUX)
+//  if (s != cork_to_utf8(s))
+//    cout << "TO: " << s << " --> " << cork_to_utf8 (s) << LF;
+  return cork_to_utf8 (s);
+#elif defined OS_WIN32 || defined (__MINGW__) || defined (__MINGW32__)
+  /* FIXME: NTFS/FATxx use different encodings. See:
+http://msdn.microsoft.com/en-us/library/windows/desktop/dd317748%28v=vs.85%29.aspx
+   */
+  return s;
+#else
+  return s;
+#endif
+}
+
+string
+as_string (url u, url_types type) {
+  // This routine pretty prints a url as a string.
   // FIXME: the current algorithm is quadratic in time.
   if (is_none (u)) return "{}";
-  if (is_atomic (u)) return u->t->label;
+  if (is_atomic (u)) {
+    if (type == URL_SYSTEM || type == URL_UNIX)
+      return convert_from_filesystem_encoding (u->t->label);
+//  else if (type == URL_STANDARD)
+//    return convert_from_web_encoding (u->t->label); // TODO
+    else // type == URL_INTERNAL
+      return u->t->label;
+  }
+  
   if (is_concat (u)) {
-    int stype= type;
-    if (is_root (u[1]) && (!is_root (u[1], "default"))) stype= URL_STANDARD;
+    url_types stype= type;
+    if (is_root_web (u[1])) stype= URL_STANDARD;
     string sep= (stype==URL_SYSTEM? string (URL_CONCATER): string ("/"));
     string s1 = as_string (u[1], type);
     string s2 = as_string (u[2], stype);
@@ -524,7 +566,7 @@
   }
 #ifdef WINPATHS
   if (is_root (u, "default")) {
-    int stype= type;
+    url_types stype= type;
     if (is_root (u[1]) && (!is_root (u[1], "default"))) stype= URL_STANDARD;
 	if (stype == URL_SYSTEM) return ""; else return "/";
   }
@@ -804,7 +846,7 @@
 
 url
 complete (url base, url u, string filter, bool flag) {
-  // cout << "complete " << base << " |||| " << u << LF;
+    // cout << "complete " << base << " |||| " << u << LF;
   if (is_none (base)) return base;
   if (is_none (u)) return u;
   if ((!is_root (base)) && (!is_rooted_name (base))) {
@@ -827,11 +869,11 @@
     FAILED ("bad protocol in url");
   }
   if (is_root (u)) {
-    // FIXME: test filter flags here
+      // FIXME: test filter flags here
     return u;
   }
   if (is_concat (u) && is_wildcard (u[1], 0) && is_wildcard (u[2], 1)) {
-    // FIXME: ret= ret | ... is unefficient (quadratic) in main loop
+      // FIXME: ret= ret | ... is unefficient (quadratic) in main loop
     if (!(is_rooted (base, "default") || is_rooted (base, "file"))) {
       failed_error << "base= " << base << LF;
       FAILED ("wildcards only implemented for files");
@@ -847,13 +889,13 @@
         if (is_directory (base * dir[i])) continue;
       ret= ret | (dir[i] * complete (base * dir[i], u, filter, flag));
       if (match_wildcard (dir[i], u[2][1]->t->label))
-	ret= ret | complete (base, dir[i], filter, flag);
+        ret= ret | complete (base, dir[i], filter, flag);
     }
     return ret;
   }
   if (is_concat (u)) {
     url sub= complete (base, u[1], "", false);
-    // "" should often be faster than the more correct "d" here
+      // "" should often be faster than the more correct "d" here
     return complete (base, sub, u[2], filter, flag);
   }
   if (is_or (u)) {
@@ -862,7 +904,7 @@
     return res1 | complete (base, u[2], filter, flag);
   }
   if (is_wildcard (u)) {
-    // FIXME: ret= ret | ... is unefficient (quadratic) in main loop
+      // FIXME: ret= ret | ... is unefficient (quadratic) in main loop
     if (!(is_rooted (base, "default") || is_rooted (base, "file"))) {
       failed_error << "base= " << base << LF;
       FAILED ("wildcards only implemented for files");
@@ -878,9 +920,9 @@
       if (starts (dir[i], "http://") || starts (dir[i], "ftp://"))
         if (is_directory (base * dir[i])) continue;
       if (is_wildcard (u, 0))
-	ret= ret | (dir[i] * complete (base * dir[i], u, filter, flag));
+        ret= ret | (dir[i] * complete (base * dir[i], u, filter, flag));
       else if (match_wildcard (dir[i], u[1]->t->label))
-	ret= ret | complete (base, dir[i], filter, flag);
+        ret= ret | complete (base, dir[i], filter, flag);
     }
     return ret;
   }
@@ -982,19 +1024,20 @@
   string s = as_string (u);
   if (starts (s, "file:///")) s= s (8, N(s));
   if (heuristic_is_default (s, 0)) return s;
-  if (is_rooted (u, "blank")) return as_string (reroot (u, "default"));
+  if (is_rooted (u, "blank"))
+    return as_string (reroot (u, "default"), URL_INTERNAL);
 #else
   if (is_rooted (u, "default") ||
       is_rooted (u, "file") ||
       is_rooted (u, "blank"))
-    return as_string (reroot (u, "default"));
+    return as_string (reroot (u, "default"), URL_INTERNAL);
 #endif
   if (is_rooted_web (u)) return concretize (get_from_web (u));
   if (is_rooted_tmfs (u)) return concretize (get_from_server (u));
   if (is_ramdisc (u)) return concretize (get_from_ramdisc (u));
-  if (is_here (u)) return as_string (url_pwd ());
-  if (is_parent (u)) return as_string (url_pwd () * url_parent ());
-  if (is_wildcard (u, 1)) return u->t[1]->label;
+  if (is_here (u)) return as_string (url_pwd (), URL_INTERNAL);
+  if (is_parent (u)) return as_string (url_pwd ()*url_parent (), URL_INTERNAL);
+  if (is_wildcard (u, 1)) return u->t[1]->label; // FIXME? convert encoding?
   std_warning << "Couldn't concretize " << u->t << LF;
   // failed_error << "u= " << u << LF;
   // FAILED ("url has no root");
Index: System/Classes/url.hpp
===================================================================
--- System/Classes/url.hpp	(revision 7971)
+++ System/Classes/url.hpp	(working copy)
@@ -13,9 +13,8 @@
 #define URL_H
 #include "tree.hpp"
 
-#define URL_SYSTEM 0
-#define URL_UNIX 1
-#define URL_STANDARD 2
+  // URL_INTERNAL is used to bypass encoding conversions in url<->string
+enum url_types { URL_SYSTEM = 0, URL_UNIX, URL_INTERNAL, URL_STANDARD };
 
 /******************************************************************************
 * The url data type
@@ -44,17 +43,19 @@
 
 tm_ostream& operator << (tm_ostream& out, url u);
 inline url as_url (tree t) { return url(t); }
-string as_string (url u, int type= URL_SYSTEM);
+string as_string (url u, url_types type= URL_SYSTEM);
 inline tree as_tree (url u) { return tree (u->t); }
 inline string as_system_string (url u) { return as_string (u, URL_SYSTEM); }
 inline string as_unix_string (url u) { return as_string (u, URL_UNIX); }
-inline string as_standard_string (url u) { return as_string (u,URL_STANDARD); }
+inline string as_standard_string (url u) { return as_string (u, URL_STANDARD); }
+string convert_from_filesystem_encoding (string s);
+string convert_to_filesystem_encoding (string s);
 
 /******************************************************************************
 * url constructors
 ******************************************************************************/
 
-url url_general (string name, int type);
+url url_general (string name, url_types type);
 url url_unix (string name);
 url url_unix (string dir, string name);
 url url_system (string name);
Index: System/Files/file.cpp
===================================================================
--- System/Files/file.cpp	(revision 7971)
+++ System/Files/file.cpp	(working copy)
@@ -455,7 +455,7 @@
   while (true) {
     ep= readdir (dp);
     if (ep==NULL) break;
-    dir << string (ep->d_name);
+    dir << convert_from_filesystem_encoding (string (ep->d_name));
   }
   (void) closedir (dp);
   merge_sort (dir);
