tCanonicalize filename in file chooser - vaccinewars - be a doctor and try to vaccinate the world
 (HTM) git clone git://src.adamsgaard.dk/vaccinewars
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit c3e33fb411e179566d42741cef23625b95d1d7cb
 (DIR) parent 7c578e5ec4943f58d5b3b24a28a3093ced89faf0
 (HTM) Author: Ben Webb <ben@salilab.org>
       Date:   Sun,  6 Dec 2020 23:33:23 -0800
       
       Canonicalize filename in file chooser
       
       The Windows file chooser dialog doesn't seem to be
       able to find the initial file if it is a relative path,
       so make it absolute. Also use the Unicode version of the
       API so we don't fall over when given non-ASCII paths.
       Closes #55.
       
       Diffstat:
         M src/gtkport/gtkport.c               |      42 +++++++++++++++++++++++--------
         M src/gtkport/unicodewrap.c           |       4 ++--
         M src/gtkport/unicodewrap.h           |       2 ++
       
       3 files changed, 35 insertions(+), 13 deletions(-)
       ---
 (DIR) diff --git a/src/gtkport/gtkport.c b/src/gtkport/gtkport.c
       t@@ -5179,35 +5179,55 @@ void gtk_window_set_position(GtkWindow *window, GtkWindowPosition position)
        {
        }
        
       +#define GTK_GET_FILE_LEN 800
        gchar *GtkGetFile(const GtkWidget *parent, const gchar *oldname,
                          const gchar *title)
        {
       -  OPENFILENAME ofn;
       -  char file[800];
       +  OPENFILENAMEW ofn;
       +  gunichar2 *title2, file[GTK_GET_FILE_LEN];
        
       +  file[0] = 0;
       +  title2 = strtow32(title, -1);
       +  /* Convert from our (UTF-8) representation to Windows Unicode */
          if (oldname) {
       -    strncpy(file, oldname, sizeof(file));
       -    file[sizeof(file) - 1] = '\0';
       -  } else {
       -    file[0] = '\0';
       +    glong nwritten;
       +    char *abspath = NULL;
       +    gunichar2 *oldname2;
       +    /* Make absolute if necessary; OpenFileName does not work with
       +       relative paths */
       +    if (!g_path_is_absolute(oldname)) {
       +      abspath = g_canonicalize_filename(oldname, NULL);
       +    }
       +    oldname2 = g_utf8_to_utf16(abspath ? abspath : oldname, -1, NULL,
       +                               &nwritten, NULL);
       +    if (oldname2) {
       +      memcpy(file, oldname2,
       +             MIN(GTK_GET_FILE_LEN, nwritten) * sizeof(gunichar2));
       +      /* Ensure null terminated */
       +      file[GTK_GET_FILE_LEN - 1] = 0;
       +      g_free(oldname2);
       +    }
       +    g_free(abspath);
          }
       -  ofn.lStructSize = sizeof(OPENFILENAME);
       +  ofn.lStructSize = sizeof(OPENFILENAMEW);
          ofn.hwndOwner = parent ? parent->hWnd : NULL;
          ofn.hInstance = NULL;
          ofn.lpstrFilter = NULL;
          ofn.lpstrCustomFilter = NULL;
          ofn.nFilterIndex = 1;
          ofn.lpstrFile = file;
       -  ofn.nMaxFile = sizeof(file);
       +  ofn.nMaxFile = GTK_GET_FILE_LEN;
          ofn.lpstrFileTitle = NULL;
          ofn.nMaxFileTitle = 0;
          ofn.lpstrInitialDir = NULL;
       -  ofn.lpstrTitle = title;
       +  ofn.lpstrTitle = title2;
          ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
          ofn.lpstrDefExt = NULL;
       -  if (GetOpenFileName(&ofn)) {
       -    return g_strdup(file);
       +  if (GetOpenFileNameW(&ofn)) {
       +    g_free(title2);
       +    return w32tostr(file, -1);
          } else {
       +    g_free(title2);
            return NULL;
          }
        }
 (DIR) diff --git a/src/gtkport/unicodewrap.c b/src/gtkport/unicodewrap.c
       t@@ -60,7 +60,7 @@ gboolean HaveUnicodeSupport(void)
         * suitable for Windows Unicode-aware functions (i.e. UTF-16). This
         * returned string must be g_free'd when no longer needed.
         */
       -static gunichar2 *strtow32(const char *instr, int len)
       +gunichar2 *strtow32(const char *instr, int len)
        {
          gunichar2 *outstr;
          if (!instr) {
       t@@ -73,7 +73,7 @@ static gunichar2 *strtow32(const char *instr, int len)
          return outstr;
        }
        
       -static gchar *w32tostr(const gunichar2 *instr, int len)
       +gchar *w32tostr(const gunichar2 *instr, int len)
        {
          gchar *outstr;
          if (!instr) {
 (DIR) diff --git a/src/gtkport/unicodewrap.h b/src/gtkport/unicodewrap.h
       t@@ -68,6 +68,8 @@ LONG myDispatchMessage(CONST MSG *lpmsg);
        BOOL myIsDialogMessage(HWND hDlg, LPMSG lpMsg);
        size_t myw32strlen(const char *str);
        LRESULT myComboBox_AddString(HWND hWnd, LPCTSTR text);
       +gchar *w32tostr(const gunichar2 *instr, int len);
       +gunichar2 *strtow32(const char *instr, int len);
        
        #endif /* CYGWIN */