Code

partial fix sent by jfb for bug #188814
[inkscape.git] / src / dialogs / filedialog-win32.cpp
2 #ifdef HAVE_CONFIG_H
3 # include <config.h>
4 #endif
5 #include "filedialog.h"
7 //#include "extension/internal/win32.h"
9 #include <windows.h>
11 #include <glib.h>
13 #include <extension/extension.h>
14 #include <extension/db.h>
16 #define UNSAFE_SCRATCH_BUFFER_SIZE 4096
18 namespace Inkscape
19 {
20 namespace UI
21 {
22 namespace Dialogs
23 {
25 /*#################################
26 # U T I L I T Y
27 #################################*/
28 static gboolean
29 win32_is_os_wide()
30 {
31         static gboolean initialized = FALSE;
32         static gboolean is_wide = FALSE;
33         static OSVERSIONINFOA osver;
35         if ( !initialized )
36         {
37                 BOOL result;
39                 initialized = TRUE;
41                 memset (&osver, 0, sizeof(OSVERSIONINFOA));
42                 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
43                 result = GetVersionExA (&osver);
44                 if (result)
45                 {
46                         if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
47                                 is_wide = TRUE;
48                 }
49                 // If we can't even call to get the version, fall back to ANSI API
50         }
52         return is_wide;
53 }
55 /*#################################
56 # F I L E    O P E N
57 #################################*/
59 struct FileOpenNativeData_def {
60     char           *dir;
61     FileDialogType fileTypes;
62     char           *title;
63 };
65 FileOpenDialog::FileOpenDialog(
66     const char *dir, FileDialogType fileTypes, const char *title) {
68     nativeData = (FileOpenNativeData *)
69             g_malloc(sizeof (FileOpenNativeData));
70     if ( !nativeData ) {
71         // do we want exceptions?
72         return;
73         }
75     if ( !dir )
76         dir = "";
77     nativeData->dir       = g_strdup(dir);
78     nativeData->fileTypes = fileTypes;
79     nativeData->title     = g_strdup(title);
81         extension = NULL;
82         filename = NULL;
83 }
87 FileOpenDialog::~FileOpenDialog() {
89     //do any cleanup here
90     if ( nativeData ) {
91         g_free(nativeData->dir);
92         g_free(nativeData->title);
93         g_free(nativeData);
94     }
96     if (filename) g_free(filename);
97     extension = NULL;
98 }
102 bool
103 FileOpenDialog::show() {
105     if ( !nativeData ) {
106         //error
107         return FALSE;
108     }
110     gint  retval  = FALSE;
113     //Jon's UNICODE patch
114     if ( win32_is_os_wide() ) {
115         gunichar2 fnbufW[UNSAFE_SCRATCH_BUFFER_SIZE * sizeof(gunichar2)] = {0};
116         gunichar2* dirW    =
117             g_utf8_to_utf16( nativeData->dir,    -1, NULL, NULL, NULL );
118         gunichar2 *filterW = (gunichar2 *) L"";
119                 if ( nativeData->fileTypes == SVG_TYPES )
120                    filterW = (gunichar2 *) L"SVG files\0*.svg;*.svgz\0All files\0*\0";
121                 else if ( nativeData->fileTypes == IMPORT_TYPES )
122                    filterW = (gunichar2 *) L"Image files\0*.svg;*.png;*.jpg;*.jpeg;*.bmp;*.gif;*.tiff;*.xpm\0"
123                             L"SVG files\0*.svg\0"
124                             L"All files\0*\0";
125         gunichar2* titleW  =
126             g_utf8_to_utf16( nativeData->title,  -1, NULL, NULL, NULL );
127         OPENFILENAMEW ofn = {
128             sizeof (OPENFILENAMEW),
129             NULL,                   // hwndOwner
130             NULL,                   // hInstance
131             (const WCHAR *)filterW, // lpstrFilter
132             NULL,                   // lpstrCustomFilter
133             0,                      // nMaxCustFilter
134             1,                      // nFilterIndex
135             (WCHAR *)fnbufW,        // lpstrFile
136             sizeof (fnbufW) / sizeof(WCHAR), // nMaxFile
137             NULL,                   // lpstrFileTitle
138             0,                      // nMaxFileTitle
139             (const WCHAR *)dirW,    // lpstrInitialDir
140             (const WCHAR *)titleW,  // lpstrTitle
141             OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, // Flags
142             0,                      // nFileOffset
143             0,                      // nFileExtension
144             NULL,                   // lpstrDefExt
145             0,                      // lCustData
146             NULL,                   // lpfnHook
147             NULL                    // lpTemplateName
148         };
150         retval = GetOpenFileNameW (&ofn);
151         if (retval)
152             filename = g_utf16_to_utf8( fnbufW, -1, NULL, NULL, NULL );
154         g_free( dirW );
155         g_free( titleW );
157     } else {
158         gchar *dir    = nativeData->dir;
159         gchar *title  = nativeData->title;
160         gchar fnbuf[UNSAFE_SCRATCH_BUFFER_SIZE] = {0};
162         gchar *filter = "";
163                 if ( nativeData->fileTypes == SVG_TYPES )
164                    filter = "SVG files\0*.svg;*.svgz\0All files\0*\0";
165                 else if ( nativeData->fileTypes == IMPORT_TYPES )
166                    filter = "Image files\0*.svg;*.png;*.jpg;*.jpeg;*.bmp;*.gif;*.tiff;*.xpm\0"
167                             "SVG files\0*.svg\0"
168                             "All files\0*\0";
170         OPENFILENAMEA ofn = {
171             sizeof (OPENFILENAMEA),
172             NULL,                  // hwndOwner
173             NULL,                  // hInstance
174             (const CHAR *)filter,  // lpstrFilter
175             NULL,                  // lpstrCustomFilter
176             0,                     // nMaxCustFilter
177             1,                     // nFilterIndex
178             fnbuf,                 // lpstrFile
179             sizeof (fnbuf),        // nMaxFile
180             NULL,                  // lpstrFileTitle
181             0,                     // nMaxFileTitle
182             (const CHAR *)dir,     // lpstrInitialDir
183             (const CHAR *)title,   // lpstrTitle
184             OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, // Flags
185             0,                     // nFileOffset
186             0,                     // nFileExtension
187             NULL,                  // lpstrDefExt
188             0,                     // lCustData
189             NULL,                  // lpfnHook
190             NULL                   // lpTemplateName
191         };
193         retval = GetOpenFileNameA (&ofn);
194         if ( retval ) {
195             filename = g_strdup( fnbuf );
196             /* ### We need to try something like this instead:
197             GError *err = NULL;
198             filename = g_filename_to_utf8(fnbuf, -1, NULL, NULL, &err);
199             if ( !filename && err ) {
200                 g_warning("Charset conversion in show()[%d]%s\n",
201                            err->code, err->message);
202             }
203             */
204         }
205     }
207     if ( !retval ) {
208         //int errcode = CommDlgExtendedError();
209         return FALSE;
210     }
212     return TRUE;
218 /*#################################
219 # F I L E    S A V E
220 #################################*/
222 struct FileSaveNativeData_def {
223     OPENFILENAME ofn;
224     gchar filter[UNSAFE_SCRATCH_BUFFER_SIZE];
225     gchar fnbuf[4096];
226 };
230 FileSaveDialog::FileSaveDialog(
231    const char *dir, FileDialogType fileTypes, const char *title, const char * default_key) {
233     nativeData = (FileSaveNativeData *)
234             g_malloc(sizeof (FileSaveNativeData));
235     if ( !nativeData ) {
236         //do we want exceptions?
237         return;
238         }
240     extension = NULL;
241     filename = NULL;
243     int default_item = 0;
245     GSList* extension_list = Inkscape::Extension::db.get_output_list();
246     g_assert (extension_list != NULL);
248     /* Make up the filter string for the save dialogue using the list
249     ** of available output types.
250     */
251     
252     gchar *p = nativeData->filter;
253     int N = UNSAFE_SCRATCH_BUFFER_SIZE;
255     int n = 1;
256     for (GSList* i = g_slist_next (extension_list); i != NULL; i = g_slist_next(i)) {
258       Inkscape::Extension::DB::IOExtensionDescription* d =
259         reinterpret_cast<Inkscape::Extension::DB::IOExtensionDescription*>(i->data);
261           if (!d->sensitive)
262                   continue;
264       int w = snprintf (p, N, "%s", d->name);
265       N -= w + 1;
266       p += w + 1;
268       w = snprintf (p, N, "*");
269       N -= w + 1;
270       p += w + 1;
272       g_assert (N >= 0);
274       /* Look to see if this extension is the default */
275       if (default_key &&
276           d->extension->get_id() &&
277           strcmp (default_key, d->extension->get_id()) == 0) {
278         default_item = n;
279         extension = d->extension;
280       }
281       
282       n++;
283     }
285     *p = '\0';
286     
287     nativeData->fnbuf[0] = '\0';
288     
289     if (dir) {
290       /* We must check that dir is not something like
291       ** c:\foo\ (ie with a trailing \).  If it is,
292       ** GetSaveFileName will give an error.
293       */
294       int n = strlen(dir);
295       if (n > 0 && dir[n - 1] != '\\') {
296         strncpy(nativeData->fnbuf, dir, sizeof(nativeData->fnbuf));
297       }
298     }
300     OPENFILENAME ofn = {
301         sizeof (OPENFILENAME),
302         NULL,                       // hwndOwner
303         NULL,                       // hInstance
304         nativeData->filter,         // lpstrFilter
305         NULL,                       // lpstrCustomFilter
306         0,                          // nMaxCustFilter
307         default_item,               // nFilterIndex
308         nativeData->fnbuf,          // lpstrFile
309         sizeof (nativeData->fnbuf), // nMaxFile
310         NULL,                       // lpstrFileTitle
311         0,                          // nMaxFileTitle
312         (const CHAR *)dir,          // lpstrInitialDir
313         (const CHAR *)title,        // lpstrTitle
314         OFN_HIDEREADONLY | OFN_NOCHANGEDIR,           // Flags
315         0,                          // nFileOffset
316         0,                          // nFileExtension
317         NULL,                       // lpstrDefExt
318         0,                          // lCustData
319         NULL,                       // lpfnHook
320         NULL                        // lpTemplateName
321         };
322     
323     nativeData->ofn = ofn;
326 FileSaveDialog::~FileSaveDialog() {
328   //do any cleanup here
329   g_free(nativeData);
330   if (filename) g_free(filename);
331   extension = NULL;
334 bool
335 FileSaveDialog::show() {
337     if (!nativeData)
338         return FALSE;
339     int retval = GetSaveFileName (&(nativeData->ofn));
340     if (!retval) {
341         //int errcode = CommDlgExtendedError();
342         return FALSE;
343         }
345     GSList* extension_list = Inkscape::Extension::db.get_output_list();
346     g_assert (extension_list != NULL);
348     /* Work out which extension corresponds to the user's choice of
349     ** file type.
350     */
351     int n = nativeData->ofn.nFilterIndex - 1;
352     GSList* i = g_slist_next (extension_list);
354     while (n > 0 && i) {
355       n--;
356       i = g_slist_next(i);
357     }
359     Inkscape::Extension::DB::IOExtensionDescription* d =
360       reinterpret_cast<Inkscape::Extension::DB::IOExtensionDescription*>(i->data);
361     
362     extension = d->extension;
364     filename = g_strdup (nativeData->fnbuf);
365         return TRUE;
375 } //namespace Dialogs
376 } //namespace UI
377 } //namespace Inkscape