Copyright (c) 2001, Loki software, inc.
All rights reserved.
-Redistribution and use in source and binary forms, with or without modification,
+Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
-Redistributions of source code must retain the above copyright notice, this list
+Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
-Neither the name of Loki software nor the names of its contributors may be used
-to endorse or promote products derived from this software without specific prior
-written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+Neither the name of Loki software nor the names of its contributors may be used
+to endorse or promote products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//
//
#include <gdk/gdkkeysyms.h>
+#include <glib/gi18n.h>
#if defined (__linux__) || defined (__APPLE__)
#include <unistd.h>
#include <gtk/gtk.h>
-
#ifdef _WIN32
#include <gdk/gdkwin32.h>
#define WIN32_LEAN_AND_MEAN
#ifdef _WIN32
void win32_get_window_pos(GtkWidget *widget, gint *x, gint *y)
{
- // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=913
if ( g_PrefsDlg.m_bStartOnPrimMon ) {
RECT rc;
POINT point;
}
#ifdef DBG_WINDOWPOS
Sys_Printf("win32_get_window_pos %p %d,%d\n",widget,*x,*y);
-#endif
+#endif
}
#endif
return NULL;
}
- rc = fread(&g, 1, 1, fp);
+ rc = fread(&g, 1, 1, fp);
m_bytesRead++;
if (rc!=1)
{
return NULL;
}
- rc = fread(&r, 1, 1, fp);
+ rc = fread(&r, 1, 1, fp);
m_bytesRead++;
if (rc != 1)
{
return NULL;
}
- rc = fread(&dummy, 1, 1, fp);
+ rc = fread(&dummy, 1, 1, fp);
m_bytesRead++;
if (rc != 1)
{
imagebits = (unsigned char *)malloc(w * h * 3);
long row_size = w * 3;
- if (imagebits != NULL)
+ if (imagebits != NULL)
{
*width = w;
*height = h;
for (row = bmHeight - 1; row >= 0; row--)
{
// which row are we working on?
- rowOffset = (long unsigned)row * row_size;
+ rowOffset = (long unsigned)row * row_size;
if (bmBitsPixel == 24)
{
unsigned char c, c1 = 0, *pp;
row = 0;
pp = outbuf + (bmHeight - 1) * bmWidth * 3;
-
+
if (bmBitsPixel == 8)
{
while (row < bmHeight)
{
c = getc(fp);
-
+
if (c)
{
// encoded mode
*pp = colormap[c1].rgbGreen; pp++;
*pp = colormap[c1].rgbBlue; pp++;
}
-
+
if (c & 1)
getc(fp); // odd length run: read an extra pad byte
}
while (row < bmHeight)
{
c = getc(fp);
-
+
if (c)
{
// encoded mode
{
// c==0x00, escape codes
c = getc(fp);
-
+
if (c == 0x00) // end of line
{
row++;
*pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbGreen; pp++;
*pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbBlue; pp++;
}
-
+
if (((c & 3) == 1) || ((c & 3) == 2))
getc(fp); // odd length run: read an extra pad byte
}
}
if (colormap)
delete [] colormap;
-
+
fclose(fp);
}
return imagebits;
if (*gdkpixmap == NULL)
{
printf("gdkpixmap was null\n");
- char *dummy[] = { "1 1 1 1", " c None", " " };
+ gchar *dummy[] = { "1 1 1 1", " c None", " " };
printf("calling gdk_pixmap_create_from_xpm_d\n");
*gdkpixmap = gdk_pixmap_create_from_xpm_d (gdk_get_default_root_window(), mask, NULL, dummy);
}
if (*gdkpixmap == NULL)
{
-
+
// look in core modules
str = g_strAppPath;
str += g_strModulesDir;
str += "bitmaps/";
str += filename;
bmp_to_pixmap (str.GetBuffer (), (GdkPixmap **)gdkpixmap, (GdkBitmap **)mask);
-
+
if (*gdkpixmap == NULL)
{
- char *dummy[] = { "1 1 1 1", " c None", " " };
+ gchar *dummy[] = { "1 1 1 1", " c None", " " };
*gdkpixmap = gdk_pixmap_create_from_xpm_d (gdk_get_default_root_window(), (GdkBitmap **)mask, NULL, dummy);
return false;
}
}
// Load a xpm file and return a pixmap widget.
-GtkWidget* new_pixmap (GtkWidget* widget, char* filename)
+GtkWidget* new_pixmap (GtkWidget* widget, const char* filename)
{
GdkPixmap *gdkpixmap;
GdkBitmap *mask;
gdk_drawable_unref (mask);
return pixmap;
-}
+}
// =============================================================================
// Menu stuff
gtk_widget_show (menu_item);
return menu_item;
}
-
-GtkWidget* create_sub_menu_with_mnemonic (GtkWidget *bar, gchar *mnemonic)
+
+GtkWidget* create_sub_menu_with_mnemonic (GtkWidget *bar, const gchar *mnemonic)
{
GtkWidget *item, *sub_menu;
extern void AddMenuItem (GtkWidget* menu, unsigned int id);
-GtkWidget* create_menu_item_with_mnemonic (GtkWidget *menu, gchar *mnemonic, GtkSignalFunc func, int id)
+GtkWidget* create_menu_item_with_mnemonic (GtkWidget *menu, const gchar *mnemonic, GtkSignalFunc func, int id)
{
GtkWidget *item;
return item;
}
-GtkWidget* create_check_menu_item_with_mnemonic (GtkWidget *menu, gchar *mnemonic, GtkSignalFunc func, int id, gboolean active)
+GtkWidget* create_check_menu_item_with_mnemonic (GtkWidget *menu, const gchar *mnemonic, GtkSignalFunc func, int id, gboolean active)
{
GtkWidget *item;
return item;
}
-GtkWidget* create_radio_menu_item_with_mnemonic (GtkWidget *menu, GtkWidget *last, gchar *mnemonic, GtkSignalFunc func, int id, gboolean state)
+GtkWidget* create_radio_menu_item_with_mnemonic (GtkWidget *menu, GtkWidget *last, const gchar *mnemonic, GtkSignalFunc func, int id, gboolean state)
{
GtkWidget *item;
GSList *group = (GSList*)NULL;
ret = (int*)g_object_get_data( G_OBJECT( parent ), "ret" );
*loop = 0;
- *ret = (int)data;
+ *ret = GPOINTER_TO_INT (data);
}
gint dialog_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data)
hbox = gtk_hbox_new (FALSE, 10);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2);
gtk_widget_show (hbox);
-
+
if (mode == MB_OK)
{
- w = gtk_button_new_with_label ("Ok");
+ w = gtk_button_new_with_label (_("Ok"));
gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (w), "clicked",
GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
}
else if (mode == MB_OKCANCEL)
{
- w = gtk_button_new_with_label ("Ok");
+ w = gtk_button_new_with_label (_("Ok"));
gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (w), "clicked",
GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
gtk_widget_grab_default (w);
gtk_widget_show (w);
- w = gtk_button_new_with_label ("Cancel");
+ w = gtk_button_new_with_label (_("Cancel"));
gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (w), "clicked",
GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
}
else if (mode == MB_YESNOCANCEL)
{
- w = gtk_button_new_with_label ("Yes");
+ w = gtk_button_new_with_label (_("Yes"));
gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (w), "clicked",
GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDYES));
GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
gtk_widget_grab_default (w);
gtk_widget_show (w);
-
- w = gtk_button_new_with_label ("No");
+
+ w = gtk_button_new_with_label (_("No"));
gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (w), "clicked",
GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDNO));
gtk_widget_show (w);
-
- w = gtk_button_new_with_label ("Cancel");
+
+ w = gtk_button_new_with_label (_("Cancel"));
gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (w), "clicked",
GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
}
else /* if (mode == MB_YESNO) */
{
- w = gtk_button_new_with_label ("Yes");
+ w = gtk_button_new_with_label (_("Yes"));
gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (w), "clicked",
GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDYES));
GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
gtk_widget_grab_default (w);
gtk_widget_show (w);
-
- w = gtk_button_new_with_label ("No");
+
+ w = gtk_button_new_with_label (_("No"));
gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (w), "clicked",
GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDNO));
if (URL)
{
- w = gtk_button_new_with_label ("Go to URL");
+ w = gtk_button_new_with_label (_("Go to URL"));
gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (w), "clicked",
GTK_SIGNAL_FUNC (dialog_url_callback), NULL);
parent = gtk_widget_get_toplevel (widget);
loop = (int*)g_object_get_data (G_OBJECT (parent), "loop");
success = (bool*)g_object_get_data (G_OBJECT (parent), "success");
-
- if ((int)data == IDOK)
+
+ if (GPOINTER_TO_INT (data) == IDOK)
*success = true;
#ifdef FILEDLG_DBG
else
Sys_Printf("file_sel_callback != IDOK\n");
#endif
-
+
*loop = 0;
}
#ifdef _WIN32
#include <commdlg.h>
-static OPENFILENAME ofn; /* common dialog box structure */
-static char szDirName[MAX_PATH]; /* directory string */
-static char szFile[MAX_PATH]; /* filename string */
-static char szFileTitle[MAX_PATH]; /* file title string */
-static int i, cbString; /* integer count variables */
-static HANDLE hf; /* file handle */
+static OPENFILENAME ofn; /* common dialog box structure */
+static char szDirName[MAX_PATH]; /* directory string */
+static char szFile[MAX_PATH]; /* filename string */
+static char szFileTitle[MAX_PATH]; /* file title string */
+static int i, cbString; /* integer count variables */
+static HANDLE hf; /* file handle */
#else
static char szFile[QER_MAX_NAMELEN];
#endif
ConstructGTKMasks();
ConstructWin32Filters();
}
-
+
filetype_t GetTypeForWin32Filter(const char *filter) const
{
for(int i=0; i<m_nTypes; i++)
return filetype_t();
}
+ int GetNumTypes()
+ {
+ return m_nTypes;
+ }
+
+ filetype_t GetTypeForIndex(int index) const // Zero-based index.
+ {
+ if (index >= 0 && index < m_nTypes)
+ return filetype_t(m_pTypes[index].m_name.c_str(), m_pTypes[index].m_pattern.c_str());
+ return filetype_t();
+ }
+
char *m_strWin32Filters;
char **m_pstrGTKMasks;
private:
delete[] *p;
delete[] m_pstrGTKMasks;
}
-
+
void ConstructGTKMasks()
{
const char *r;
};
-const char* file_dialog (void *parent, gboolean open, const char* title, const char* path, const char* pattern)
+#ifdef _WIN32
+
+static int in_file_dialog = 0;
+
+typedef struct {
+ gboolean open;
+ OPENFILENAME *ofn;
+ BOOL dlgRtnVal;
+ int done;
+} win32_native_file_dialog_comms_t;
+
+DWORD WINAPI win32_native_file_dialog_thread_func(LPVOID lpParam)
{
+ win32_native_file_dialog_comms_t *fileDialogComms;
+ fileDialogComms = (win32_native_file_dialog_comms_t *) lpParam;
+ if (fileDialogComms->open) {
+ fileDialogComms->dlgRtnVal = GetOpenFileName(fileDialogComms->ofn);
+ }
+ else {
+ fileDialogComms->dlgRtnVal = GetSaveFileName(fileDialogComms->ofn);
+ }
+ fileDialogComms->done = -1; // No need to synchronize around lock.
+ return 0;
+}
+
+#endif
+
+/**
+ * @param[in] baseSubDir should have a trailing slash if not @c NULL
+ */
+const char* file_dialog (void *parent, gboolean open, const char* title, const char* path, const char* pattern, const char *baseSubDir)
+{
+
+#ifdef _WIN32
+ HANDLE fileDialogThreadHandle;
+ win32_native_file_dialog_comms_t fileDialogComms;
+ int dialogDone;
+#endif
+
// Gtk dialog
GtkWidget* file_sel;
int loop = 1;
#endif
#ifdef _WIN32
- // win32 dialog stores the selected "save as type" extension in the second null-terminated string
- char customfilter[FILEDLG_CUSTOM_FILTER_LENGTH];
-
if (g_PrefsDlg.m_bNativeGUI)
{
#ifdef FILEDLG_DBG
Sys_Printf("Doing win32 file dialog...");
#endif
// do that the native way
- /* Place the terminating null character in the szFile. */
- szFile[0] = '\0';
- customfilter[0] = customfilter[1] = customfilter[2] = '\0';
-
- /* Set the members of the OPENFILENAME structure. */
- ofn.lStructSize = sizeof(OPENFILENAME);
+
+ if (in_file_dialog) return NULL; // Avoid recursive entry.
+ in_file_dialog = 1;
+ /* Set the members of the OPENFILENAME structure. */
+ // See http://msdn.microsoft.com/en-us/library/ms646839%28v=vs.85%29.aspx .
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = (HWND)GDK_WINDOW_HWND (g_pParentWnd->m_pWidget->window);
+ ofn.nFilterIndex = 1; // The index is 1-based, not 0-based. This basically says,
+ // "select the first filter as default".
if (pattern)
{
- ofn.nFilterIndex = 0;
ofn.lpstrFilter = typelist.m_strWin32Filters;
}
- else ofn.nFilterIndex = 1;
- ofn.lpstrCustomFilter = customfilter;
- ofn.nMaxCustFilter = sizeof(customfilter);
+ else
+ {
+ // TODO: Would be a bit cleaner if we could extract this string from
+ // GetFileTypeRegistry() instead of hardcoding it here.
+ ofn.lpstrFilter = "all files\0*.*\0"; // Second '\0' will be added to end of string.
+ }
+ szFile[0] = '\0';
ofn.lpstrFile = szFile;
- ofn.nMaxFile = sizeof(szFile);
- ofn.lpstrFileTitle = NULL; // we don't need to get the name of the file
+ ofn.nMaxFile = sizeof(szFile);
if(path)
{
// szDirName: Radiant uses unix convention for paths internally
*w = '\0';
ofn.lpstrInitialDir = szDirName;
}
- else ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = title;
- ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
-
- /* Display the Open dialog box. */
- // it's open or close depending on 'open' parameter
- if (open)
- {
- if (!GetOpenFileName(&ofn))
- return NULL; // canceled
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+
+ memset(&fileDialogComms, 0, sizeof(fileDialogComms));
+ fileDialogComms.open = open;
+ fileDialogComms.ofn = &ofn;
+
+ fileDialogThreadHandle =
+ CreateThread(NULL, // lpThreadAttributes
+ 0, // dwStackSize, default stack size
+ win32_native_file_dialog_thread_func, // lpStartAddress, funcion to call
+ &fileDialogComms, // lpParameter, argument to pass to function
+ 0, // dwCreationFlags
+ NULL); // lpThreadId
+
+ dialogDone = 0;
+ while (1) {
+ // Avoid blocking indefinitely. Another thread will set fileDialogComms->done to nonzero;
+ // we don't want to be in an indefinite blocked state when this happens. We want to break
+ // out of here eventually.
+ while (gtk_events_pending()) {
+ gtk_main_iteration();
+ }
+ if (dialogDone) break;
+ if (fileDialogComms.done) dialogDone = 1; // One more loop of gtk_main_iteration() to get things in sync.
+ // Avoid tight infinte loop, add a small amount of sleep.
+ Sleep(10);
}
- else
- {
- if (!GetSaveFileName(&ofn))
- return NULL; // canceled
+ // Make absolutely sure that the thread is finished before we call CloseHandle().
+ WaitForSingleObject(fileDialogThreadHandle, INFINITE);
+ CloseHandle(fileDialogThreadHandle);
+
+ in_file_dialog = 0;
+
+ if (!fileDialogComms.dlgRtnVal) {
+ return NULL; // Cancelled.
}
if(pattern != NULL)
- type = typelist.GetTypeForWin32Filter(customfilter+1);
-
+ type = typelist.GetTypeForIndex(ofn.nFilterIndex - 1);
+
#ifdef FILEDLG_DBG
Sys_Printf("Done.\n");
#endif
else
{
#endif
+ char buf[PATH_MAX];
// do that the Gtk way
if (title == NULL)
- title = open ? "Open File" : "Save File";
-
+ title = open ? _("Open File") : _("Save File");
+
#ifdef FILEDLG_DBG
Sys_Printf("Doing Gtk file dialog:\nBuilding new_path..");
#endif
// we expect an actual path below, if the path is NULL we might crash
if (!path || path[0] == '\0')
{
-#ifdef _WIN32
- path = "C:\\";
-#elif defined (__linux__) || defined (__APPLE__)
- path = "/";
-#else
- path = "/";
-#endif
- }
+ strcpy(buf, g_pGameDescription->mEnginePath.GetBuffer());
+ strcat(buf, g_pGameDescription->mBaseGame.GetBuffer());
+ strcat(buf, "/");
+ if (baseSubDir)
+ strcat(buf, baseSubDir);
+ path = buf;
+ }
// alloc new path with extra char for dir separator
new_path = new char[strlen(path)+1+1];
*w = '\0';
#ifdef FILEDLG_DBG
- Sys_Printf("Done.\n");
- Sys_Printf("Calling gtk_file_selection_new with title: %s...", title);
+ Sys_Printf("Done.\n");
+ Sys_Printf("Calling gtk_file_selection_new with title: %s...", title);
#endif
-
file_sel = gtk_file_selection_new (title);
-
#ifdef FILEDLG_DBG
- Sys_Printf("Done.\n");
- Sys_Printf("Set the masks...");
+ Sys_Printf("Done.\n");
+ Sys_Printf("Set the masks...");
#endif
#if 0 //!\todo Add masks to GtkFileSelection in gtk-2.0
gtk_signal_connect (GTK_OBJECT (file_sel), "delete_event",
GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (file_sel));
-
+
if (parent != NULL)
gtk_window_set_transient_for (GTK_WINDOW (file_sel), GTK_WINDOW (parent));
-
+
#ifdef FILEDLG_DBG
Sys_Printf("set_data...");
#endif
#ifdef FILEDLG_DBG
Sys_Printf("Done.\n");
#endif
-
+
if (!open)
{
#ifdef FILEDLG_DBG
Sys_Printf("Done.\n");
#endif
}
-
+
if (new_path != NULL)
{
#ifdef FILEDLG_DBG
- Sys_Printf("gtk_file_selection_set_filename... %p", file_sel);
+ Sys_Printf("gtk_file_selection_set_filename... %p (%s)", file_sel, new_path);
#endif
gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_sel), new_path);
delete[] new_path;
gtk_grab_add (file_sel);
#ifdef FILEDLG_DBG
- Sys_Printf("gtk_widget_show... %p", file_sel);
+ Sys_Printf("gtk_widget_show... %p", file_sel);
#endif
gtk_widget_show (file_sel);
#ifdef FILEDLG_DBG
- Sys_Printf("Done.\n");
+ Sys_Printf("Done.\n");
#endif
#ifdef FILEDLG_DBG
- Sys_Printf("gtk_main_iteration...");
+ Sys_Printf("gtk_main_iteration...");
#endif
while (loop)
gtk_main_iteration ();
#ifdef FILEDLG_DBG
Sys_Printf("Done.\n");
#endif
-
+
gtk_grab_remove (file_sel);
gtk_widget_destroy (file_sel);
#ifdef _WIN32
*w = '/';
#if defined(WIN32)
- if (g_PrefsDlg.m_bNativeGUI) // filetype mask not supported in gtk dialog yet
+ if (g_PrefsDlg.m_bNativeGUI)
{
- // when saving, force an extension depending on filetype
/* \todo SPoG - file_dialog should return filetype information separately.. not force file extension.. */
if(!open && pattern != NULL)
{
// last ext separator
w = strrchr(szFile, '.');
- // no extension
- w = (w!=NULL) ? w : szFile+strlen(szFile);
- strcpy(w, type.pattern+1);
+ if (w == NULL) { // No extension.
+ w = szFile + strlen(szFile);
+ strcpy(w, type.pattern + 1); // Add extension of selected filter type.
+ }
+ else { // An extension was explicitly in the filename.
+ int knownExtension = 0;
+ for (int i = typelist.GetNumTypes() - 1; i >= 0; i--) {
+ type = typelist.GetTypeForIndex(i);
+ if (stricmp(w, type.pattern + 1) == 0) {
+ knownExtension = 1;
+ break;
+ }
+ }
+ if (!knownExtension) {
+ if (gtk_MessageBox(parent, "Unknown file extension for this save operation.\nAttempt to save anyways?",
+ "GtkRadiant", MB_YESNO) == IDNO) {
+ return NULL;
+ }
+ }
+ }
}
}
#endif
GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (file_sel));
- if (parent != NULL)
- gtk_window_set_transient_for (GTK_WINDOW (file_sel), GTK_WINDOW (parent));
+ if ( parent != NULL ) {
+ gtk_window_set_transient_for( GTK_WINDOW( file_sel ), GTK_WINDOW( parent ) );
+ }
gtk_widget_hide (GTK_FILE_SELECTION (file_sel)->file_list->parent);
g_object_set_data (G_OBJECT (file_sel), "loop", &loop);
- g_object_set_data (G_OBJECT (file_sel), "filename", &filename);
g_object_set_data (G_OBJECT (file_sel), "success", &success);
if (path != NULL)
while (loop)
gtk_main_iteration ();
- filename = g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_sel)));
+ filename = g_strdup( gtk_file_selection_get_filename( GTK_FILE_SELECTION( file_sel ) ) );
- gtk_grab_remove (file_sel);
- gtk_widget_destroy (file_sel);
+ gtk_grab_remove( file_sel );
+ gtk_widget_destroy( file_sel );
return filename;
}