move old gtk runtime code back to trunk
authorTTimo <ttimo@ttimo.net>
Sun, 26 Dec 2010 04:13:09 +0000 (04:13 +0000)
committerTTimo <ttimo@ttimo.net>
Sun, 26 Dec 2010 04:13:09 +0000 (04:13 +0000)
git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/trunk@361 8a3a26a2-13c4-0310-b231-cf6edde360e5

config.py
plugins/imagepng/plugin.cpp
radiant/glwidget.cpp
radiant/gtkmisc.cpp
radiant/preferences.cpp
radiant/radiant_VC9.vcproj

index 314b2d0d62b5442a4e2a07b07642efcab9b20a0b..e0f20a01e52271274abd64a2aa3d6b8284f29836 100644 (file)
--- a/config.py
+++ b/config.py
@@ -273,7 +273,7 @@ class Config:
                        self.FetchGamePaks( self.install_directory )
                # NOTE: unrelated to self.setup_platforms - grab support files and binaries and install them
                if ( self.platform == 'Windows' ):
-                       depsfile = 'GtkR-deps-1.6-6.zip'
+                       depsfile = 'GtkR-deps-1.6-3.zip'
                        if ( not os.path.exists( depsfile ) ):
                                cmd = [ 'wget', '-N', 'http://zerowing.idsoftware.com/files/radiant/developer/1.6.1/%s' % depsfile ]
                                print( repr( cmd ) )
@@ -291,37 +291,28 @@ class Config:
                                # copy all the dependent runtime data to the install directory
                                srcdir = os.path.dirname( backup_cwd )
                                for f in [
-                                       # USE THE DEPENDENCY WALKER
-                                        # tier 1: radiant.exe direct deps
-                                        # tier 2: deps of tier 1 DLLs
-                                        # etc.
-                                        # tier 1
                                        'libxml2/bin/libxml2.dll',
-                                        'libxml2/bin/iconv.dll',
                                        'gtk2/bin/libglib-2.0-0.dll',
                                        'gtk2/bin/libgobject-2.0-0.dll',
                                        'gtk2/bin/libgdk-win32-2.0-0.dll',
                                        'gtk2/bin/libgtk-win32-2.0-0.dll',
                                        'gtk2/bin/intl.dll',
-                                       'gtk2/bin/libpango-1.0-0.dll',
-                                        'gtk2/bin/libpangoft2-1.0-0.dll',
-                                       'gtk2/lib/gtkglext-1.2.0/lib/libgtkglext-win32-1.0-0.dll',
-                                       'gtk2/lib/gtkglext-1.2.0/lib/libgdkglext-win32-1.0-0.dll',
-                                        # tier 2
-                                        'gtk2/bin/libgthread-2.0-0.dll',
+                                       'gtk2/bin/libatk-1.0-0.dll',
                                        'gtk2/bin/libcairo-2.dll',
                                        'gtk2/bin/libgdk_pixbuf-2.0-0.dll',
+                                       'gtk2/bin/libgmodule-2.0-0.dll',
+                                       'gtk2/bin/libpng13.dll',
+                                       'gtk2/bin/libpango-1.0-0.dll',
+                                        'gtk2/bin/libpangoft2-1.0-0.dll',
                                        'gtk2/bin/libpangocairo-1.0-0.dll',
                                        'gtk2/bin/libpangowin32-1.0-0.dll',
-                                       'gtk2/bin/libatk-1.0-0.dll',
-                                       'gtk2/bin/libgmodule-2.0-0.dll',
-                                        'gtk2/bin/libfontconfig-1.dll',
-                                        'gtk2/bin/freetype6.dll',
-                                        # tier 3
-                                        'gtk2/bin/libexpat-1.dll',
-                                        'gtk2/bin/libpng14-14.dll',
-                                        'gtk2/bin/zlib1.dll',
-                                        'gtk2/bin/libgio-2.0-0.dll',                                        
+                                       'gtk2/lib/libgtkglext-win32-1.0-0.dll',
+                                       'gtk2/lib/libgdkglext-win32-1.0-0.dll',
+                                       'gtk2/lib/iconv.dll',
+                                        'gtk2/zlib1.dll',
+#                                       'freetype-dev_2.4.2-1_win32/bin/freetype6.dll',
+#                                       'fontconfig-dev_2.8.0-2_win32/bin/libfontconfig-1.dll',
+#                                       'expat_2.0.1-1_win32/bin/libexpat-1.dll',
                                         ]:
                                         cmd = [ 'cp', '-v', os.path.join( srcdir, f ), 'install' ]
                                         print( repr( cmd ) )
@@ -329,6 +320,9 @@ class Config:
                                for d in [
                                        'gtk2/etc',
                                        'gtk2/share',
+#                                       'fontconfig-dev_2.8.0-2_win32/etc',
+#                                       'fontconfig-dev_2.8.0-2_win32/share',
+#                                       'freetype-dev_2.4.2-1_win32/share',
                                        ]:
                                         cmd = [ 'cp', '-r', '-v', os.path.join( srcdir, d ), 'install' ]
                                        print( repr( cmd ) )
index fda3e6f0572f58c7b453e3304308f87609ae66d5..5d8bba70fe998258b249c5f1e71a6c6fc7297392 100644 (file)
@@ -137,7 +137,7 @@ void LoadImage (const char *filename, unsigned char **pic, int *width, int *heig
   // http://www.libpng.org/pub/png/libpng-manual.html
 
   png_structp png_ptr = png_create_read_struct
-    (PNG_LIBPNG_VER_STRING, NULL,
+    (PNG_LIBPNG_VER_STRING, png_voidp_NULL,
     user_error_fn, user_warning_fn);
   if (!png_ptr)
   {
@@ -148,7 +148,7 @@ void LoadImage (const char *filename, unsigned char **pic, int *width, int *heig
   png_infop info_ptr = png_create_info_struct(png_ptr);
   if (!info_ptr) {
     png_destroy_read_struct(&png_ptr,
-      NULL, NULL);
+      png_infopp_NULL, png_infopp_NULL);
     g_FuncTable.m_pfnSysPrintf ("libpng error: png_create_info_struct (info_ptr)\n");
     return;
   }
@@ -156,7 +156,7 @@ void LoadImage (const char *filename, unsigned char **pic, int *width, int *heig
   png_infop end_info = png_create_info_struct(png_ptr);
   if (!end_info) {
     png_destroy_read_struct(&png_ptr, &info_ptr,
-      NULL);
+      png_infopp_NULL);
     g_FuncTable.m_pfnSysPrintf ("libpng error: png_create_info_struct (end_info)\n");
     return;
   }
@@ -187,10 +187,8 @@ void LoadImage (const char *filename, unsigned char **pic, int *width, int *heig
   if (color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_palette_to_rgb(png_ptr);
 
-  if ( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 ) {
-         // png_set_gray_1_2_4_to_8 was renamed to png_set_expand_gray_1_2_4_to_8
-    png_set_expand_gray_1_2_4_to_8(png_ptr);
-  }
+  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+    png_set_gray_1_2_4_to_8(png_ptr);
 
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
     png_set_tRNS_to_alpha(png_ptr);
@@ -236,7 +234,7 @@ void LoadImage (const char *filename, unsigned char **pic, int *width, int *heig
   png_read_end(png_ptr, info_ptr);
 
   /* free up the memory structure */
-  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+  png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
 
   free(row_pointers);
   g_FileSystemTable.m_pfnFreeFile (fbuffer);
index 7a408f9e51cebec59999e9945eddf09d46fcfd95..57699b379ee1b9ff137ec8ff4c0b76acf755e606 100644 (file)
@@ -33,7 +33,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "stdafx.h"
 
 #include <gtk/gtkgl.h>
+
+#ifndef _WIN32
 #include <pango/pangoft2.h>
+#endif
+
 #include "glwidget.h"
 #include "qgl.h"
 
@@ -208,6 +212,15 @@ gboolean WINAPI gtk_glwidget_make_current (GtkWidget *widget)
 }
 
 
+#ifdef _WIN32
+
+GLuint font_list_base;
+static gchar font_string[] = "courier 8";
+static gint font_height;
+static int font_created = 0;
+
+#else
+
 // Think about rewriting this font stuff to use OpenGL display lists and glBitmap().
 // Bit maps together with display lists may offer a performance increase, but
 // they would not allow antialiased fonts.
@@ -219,31 +232,88 @@ static int y_offset_bitmap_render_pango_units = -1;
 static PangoContext *ft2_context = NULL;
 static int _debug_font_created = 0;
 
+#endif
+
 
 // Units are pixels.  Returns a positive value [most likely].
 int gtk_glwidget_font_ascent()
 {
+#ifdef _WIN32
+
+  return 6; // Approximation.
+
+#else
+
   if (!_debug_font_created) {
     Error("Programming error: gtk_glwidget_font_ascent() called but font does not exist; "
           "you should have called gtk_glwidget_create_font() first");
   }
 
   return font_ascent;
+
+#endif
 }
 
 // Units are pixels.  Returns a positive value [most likely].
 int gtk_glwidget_font_descent()
 {
+#ifdef _WIN32
+
+  return 0; // Approximation.
+
+#else
+
   if (!_debug_font_created) {
     Error("Programming error: gtk_glwidget_font_descent() called but font does not exist; "
           "you should have called gtk_glwidget_create_font() first");
   }
 
   return font_descent;
+
+#endif
+}
+
+#ifdef _WIN32
+
+void gtk_glwidget_create_font_win_internal()
+{
+  if (font_created) return;
+  font_created = 1;
+
+  PangoFontDescription *font_desc;
+  PangoFont *font;
+  PangoFontMetrics *font_metrics;
+
+  font_list_base = qglGenLists (256);
+
+  font_desc = pango_font_description_from_string (font_string);
+
+  font = gdk_gl_font_use_pango_font (font_desc, 0, 256, font_list_base);
+
+  if(font != NULL)
+  {
+    font_metrics = pango_font_get_metrics (font, NULL);
+
+    font_height = pango_font_metrics_get_ascent (font_metrics) +
+                  pango_font_metrics_get_descent (font_metrics);
+    font_height = PANGO_PIXELS (font_height);
+
+    pango_font_metrics_unref (font_metrics);
+  }
+
+  pango_font_description_free (font_desc);
 }
 
+#endif
+
 void gtk_glwidget_create_font()
 {
+#ifdef _WIN32
+
+  // Do nothing.
+
+#else
+
   PangoFontDescription *font_desc;
   PangoLayout *layout;
   PangoRectangle log_rect;
@@ -294,10 +364,18 @@ void gtk_glwidget_create_font()
   font_ascent = PANGO_PIXELS_CEIL(font_ascent_pango_units);
   font_descent = PANGO_PIXELS_CEIL(font_descent_pango_units);
   y_offset_bitmap_render_pango_units = (font_ascent * PANGO_SCALE) - font_ascent_pango_units;
+
+#endif
 }
 
 void gtk_glwidget_destroy_font()
 {
+#ifdef _WIN32
+
+  // Do nothing.
+
+#else
+
   if (!_debug_font_created) {
     Error("Programming error: gtk_glwidget_destroy_font() called when font "
           "does not exist");
@@ -308,6 +386,8 @@ void gtk_glwidget_destroy_font()
   y_offset_bitmap_render_pango_units = -1;
   g_object_unref(G_OBJECT(ft2_context));
   _debug_font_created = 0;
+
+#endif
 }
 
 
@@ -323,6 +403,14 @@ void gtk_glwidget_destroy_font()
 // Google for "glDrawPixels clipping".
 void gtk_glwidget_print_string(const char *s)
 {
+#ifdef _WIN32
+
+  gtk_glwidget_create_font_win_internal();
+  qglListBase(font_list_base);
+  qglCallLists(strlen(s), GL_UNSIGNED_BYTE, (unsigned char *)s);
+
+#else
+
   // The idea for this code initially came from the font-pangoft2.c example that comes with GtkGLExt.
 
   PangoLayout *layout;
@@ -396,12 +484,24 @@ void gtk_glwidget_print_string(const char *s)
   }
 
   g_object_unref(G_OBJECT(layout));
+
+#endif
 }
 
 void gtk_glwidget_print_char(char s)
 {
+#ifdef _WIN32
+
+  gtk_glwidget_create_font_win_internal();
+  qglListBase(font_list_base);
+  qglCallLists(1, GL_UNSIGNED_BYTE, (unsigned char *) &s);
+
+#else
+
   char str[2];
   str[0] = s;
   str[1] = '\0';
   gtk_glwidget_print_string(str);
+
+#endif
 }
index 6b54918018de2cdd0b2c8f6743426e6dda325b05..93fed4a010eea754d356efa81684dfccd6ffb891 100644 (file)
@@ -1025,8 +1025,6 @@ int WINAPI gtk_MessageBox (void *parent, const char* lpText, const char* lpCapti
 
 // fenris #3078 WHENHELLISFROZENOVER
 
-//#define FILEDLG_DBG
-
 static void file_sel_callback (GtkWidget *widget, gpointer data)
 {
   GtkWidget *parent;
@@ -1040,11 +1038,6 @@ static void file_sel_callback (GtkWidget *widget, gpointer data)
   if (GPOINTER_TO_INT (data) == IDOK)
     *success = true;
 
-#ifdef FILEDLG_DBG
-  else
-    Sys_Printf("file_sel_callback != IDOK\n");
-#endif
-
   *loop = 0;
 }
 
@@ -1123,6 +1116,18 @@ public:
     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:
@@ -1185,10 +1190,10 @@ private:
       for(r = m_pTypes[i].m_name.c_str(); *r!='\0'; r++, w++)
         *w = *r;
       *w++ = ' ';
-      *w++ = '<';
+      *w++ = '(';
       for(r = m_pTypes[i].m_pattern.c_str(); *r!='\0'; r++, w++)
         *w = *r;
-      *w++ = '>';
+      *w++ = ')';
       *w++ = '\0';
     }
     m_pstrGTKMasks[m_nTypes] = NULL;
@@ -1196,64 +1201,82 @@ private:
 
 };
 
+#ifdef _WIN32
+
+typedef struct {
+  gboolean open;
+  OPENFILENAME *ofn;
+  BOOL dlgRtnVal;
+  bool 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 = true; // No need to synchronize around lock, one-way gate.
+  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
+  static bool in_file_dialog = false;
+  HANDLE fileDialogThreadHandle;
+  win32_native_file_dialog_comms_t fileDialogComms;
+  bool dialogDone;
+#endif
+
   // Gtk dialog
   GtkWidget* file_sel;
-  int loop = 1;
   char *new_path = NULL;
 
   const char* r;
-  charw;
+  char *v, *w;
   filetype_t type;
   CFileType typelist;
   if(pattern != NULL)
     GetFileTypeRegistry()->getTypeList(pattern, &typelist);
 
-#ifdef FILEDLG_DBG
-  Sys_Printf("file_dialog: open = %d title = %s path = %s\n", open, title, path);
-  if (pattern)
-  {
-    Sys_Printf("Patterns:\n");
-    char** p = typelist.m_pstrGTKMasks;
-    while(*p!=NULL)
-      Sys_Printf("%s\n", *p++);
-  }
-  else
-    Sys_Printf("no patterns\n");
-#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';
 
+    if (in_file_dialog) return NULL; // Avoid recursive entry.
+    in_file_dialog = true;
     /* Set the members of the OPENFILENAME structure. */
-    ofn.lStructSize = sizeof(OPENFILENAME);
+    // 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
     if(path)
     {
       // szDirName: Radiant uses unix convention for paths internally
@@ -1265,29 +1288,47 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
       *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
+    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 = false;
+    while (1) {
+      // Avoid blocking indefinitely.  Another thread will set fileDialogComms->done to true;
+      // 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 = true; // 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 = false;
+    
+    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
   {
@@ -1297,9 +1338,6 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
     if (title == NULL)
       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')
     {
@@ -1321,101 +1359,51 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
     // terminate string
     *w = '\0';
 
-#ifdef FILEDLG_DBG
-       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...");
-#endif
-
-#if 0 //!\todo Add masks to GtkFileSelection in gtk-2.0
-    // set the masks
-    if (pattern)
-    {
-      gtk_file_selection_clear_masks (GTK_FILE_SELECTION (file_sel));
-      gtk_file_selection_set_masks (GTK_FILE_SELECTION (file_sel), const_cast<const char**>(typelist.m_pstrGTKMasks));
+    file_sel = gtk_file_chooser_dialog_new(title,
+                                           GTK_WINDOW(parent),
+                                           open ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE,
+                                           GTK_STOCK_CANCEL,
+                                           GTK_RESPONSE_CANCEL,
+                                           open ? GTK_STOCK_OPEN : GTK_STOCK_SAVE,
+                                           GTK_RESPONSE_ACCEPT,
+                                           NULL);
+    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_sel), new_path);
+    delete[] new_path;
+
+    // Setting the file chooser dialog to modal and centering it on the parent is done automatically.
+
+    if (pattern != NULL) {
+      for (int i = 0; i < typelist.GetNumTypes(); i++) {
+        GtkFileFilter *filter = gtk_file_filter_new();
+        type = typelist.GetTypeForIndex(i);
+        // We can use type.name here, or m_pstrGTKMasks[i], which includes the actual pattern.
+        gtk_file_filter_set_name(filter, typelist.m_pstrGTKMasks[i]);
+        gtk_file_filter_add_pattern(filter, type.pattern);
+        // "Note that the chooser takes ownership of the filter, so
+        // you have to ref and sink it if you want to keep a reference."
+        // So I guess we won't need to garbage collect this.
+        gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_sel), filter);
+      }
     }
-#endif
-
-#ifdef FILEDLG_DBG
-    Sys_Printf("Done.\n");
-#endif
-
-    gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button), "clicked",
-      GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDOK));
-    gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->cancel_button), "clicked",
-      GTK_SIGNAL_FUNC (file_sel_callback), GINT_TO_POINTER (IDCANCEL));
-    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
-    bool success = false;
-    g_object_set_data (G_OBJECT (file_sel), "loop", &loop);
-    g_object_set_data (G_OBJECT (file_sel), "success", &success);
-#ifdef FILEDLG_DBG
-    Sys_Printf("Done.\n");
-#endif
-
-    if (!open)
-    {
-#ifdef FILEDLG_DBG
-      Sys_Printf("set_data \"overwrite\" ...");
-#endif
-      g_object_set_data (G_OBJECT (file_sel), "overwrite", GINT_TO_POINTER (1));
-#ifdef FILEDLG_DBG
-      Sys_Printf("Done.\n");
-#endif
+    if (gtk_dialog_run(GTK_DIALOG(file_sel)) == GTK_RESPONSE_ACCEPT) {
+      strcpy(szFile, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_sel)));
     }
-
-    if (new_path != NULL)
-    {
-#ifdef FILEDLG_DBG
-      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;
-#ifdef FILEDLG_DBG
-      Sys_Printf("Done.\n");
-#endif
+    else {
+      szFile[0] = '\0';
     }
 
-    gtk_grab_add (file_sel);
-#ifdef FILEDLG_DBG
-    Sys_Printf("gtk_widget_show... %p", file_sel);
-#endif
-    gtk_widget_show (file_sel);
-#ifdef FILEDLG_DBG
-    Sys_Printf("Done.\n");
-#endif
-
-#ifdef FILEDLG_DBG
-    Sys_Printf("gtk_main_iteration...");
-#endif
-    while (loop)
-      gtk_main_iteration ();
-    if(success)
-    {
-#if 0 //!\todo Add masks to GtkFileSelection in gtk2
-      if(pattern!=NULL)
-        type = typelist.GetTypeForGTKMask(GTK_FILE_SELECTION (file_sel)->mask);
-#endif
-      strcpy(szFile, gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_sel)));
+    if (pattern != NULL) {
+      GtkFileFilter *filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(file_sel));
+      if (filter == NULL) {
+        type = filetype_t();
+      }
+      else {
+        type = typelist.GetTypeForGTKMask(gtk_file_filter_get_name(filter));
+      }
     }
-#ifdef FILEDLG_DBG
-    Sys_Printf("Done.\n");
-#endif
+    gtk_widget_destroy(file_sel);
 
-    gtk_grab_remove (file_sel);
-    gtk_widget_destroy (file_sel);
 #ifdef _WIN32
   }
 #endif
@@ -1428,21 +1416,42 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
     if(*w=='\\')
       *w = '/';
 
-#if defined(WIN32)
-  if (g_PrefsDlg.m_bNativeGUI) // filetype mask not supported in gtk dialog yet
-  {
-    // 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);
+  /* \todo SPoG - file_dialog should return filetype information separately.. not force file extension.. */
+  if(!open && pattern != NULL) {
+    v = strrchr(szFile, '/');
+    w = strrchr(szFile, '.');
+    if ((v && w && w < v) || // Last '.' is before the file.
+        w == NULL) { // Extension missing.
+      if (type.pattern[0]) {
+        w = szFile + strlen(szFile);
+        strcpy(w, type.pattern + 1); // Add extension of selected filter type.
+      }
+      else {
+        // type will be empty if for example there were no filters for pattern,
+        // or if some other UI inconsistencies happen.
+        if (gtk_MessageBox(parent, "No file extension specified in file to be saved.\nAttempt to save anyways?",
+                           "GtkRadiant", MB_YESNO) == IDNO) {
+          return NULL;
+        }
+      }
+    }
+    else { // An extension was explicitly in the filename.
+      bool knownExtension = false;
+      for (int i = typelist.GetNumTypes() - 1; i >= 0; i--) {
+        type = typelist.GetTypeForIndex(i);
+        if (type.pattern[0] && strcmp(w, type.pattern + 1) == 0) {
+          knownExtension = true;
+          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
 
   // prompt to overwrite existing files
   if (!open)
@@ -1450,11 +1459,6 @@ const char* file_dialog (void *parent, gboolean open, const char* title, const c
       if (gtk_MessageBox (parent, "File already exists.\nOverwrite?", "GtkRadiant", MB_YESNO) == IDNO)
         return NULL;
 
-#ifdef FILEDLG_DBG
-  // ... let's use a static filename
-  Sys_Printf("filename: %p\n", szFile);
-#endif
-
   return szFile;
 }
 
index f44aca8a16e33ec3ad179de0536c676d00cfbabd..03486fd861b4abc81997dd36b48f88f59e3e7613 100644 (file)
@@ -40,7 +40,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include "gtkmisc.h"
 
 #ifdef _WIN32
-#undef fprintf
+       // sanity check - some gtk2 win32 runtimes replace sprintf
+       #if defined( sprintf )
+               #error sprintf is a macro. are you sure?
+       #endif
 #endif
 
 #ifdef _WIN32
@@ -2222,7 +2225,7 @@ void PrefsDlg::BuildDialog ()
 
 #ifdef _WIN32
   // win32 file dialog
-  check = gtk_check_button_new_with_label (_("Use win32 file load dialog"));
+  check = gtk_check_button_new_with_label (_("Use win32 file dialog (hacky)"));
   gtk_widget_show (check);
   // gtk_container_add (GTK_CONTAINER (vbox), check);
   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
index 13e0cad38156b913e4eddd0c92a539c547010257..9f8c8cfbf21e73d9e35a17afaff8222e45d601c6 100755 (executable)
@@ -40,7 +40,7 @@
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="&quot;$(SolutionDir)\include&quot;;&quot;$(SolutionDir)\libs&quot;;&quot;$(SolutionDir)\..\STLPort\stlport&quot;;&quot;$(SolutionDir)\..\gtk2\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\glib-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\lib\glib-2.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\lib\gtk-2.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\lib\gtkglext-1.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\gtk-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\cairo&quot;;&quot;$(SolutionDir)\..\gtk2\include\pango-1.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\atk-1.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\gdk-pixbuf-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\freetype2&quot;;&quot;$(SolutionDir)\..\libxml2\include&quot;"\r
+                               AdditionalIncludeDirectories="&quot;$(SolutionDir)\include&quot;;&quot;$(SolutionDir)\libs&quot;;&quot;$(SolutionDir)\..\STLPort\stlport&quot;;&quot;$(SolutionDir)\..\gtk2\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\glib-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\lib\glib-2.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\lib\gtk-2.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\gtkglext-1.0&quot;;&quot;$(SolutionDir)\..\gtk2\lib\gtkglext-1.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\gtk-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\cairo&quot;;&quot;$(SolutionDir)\..\gtk2\include\pango-1.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\atk-1.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\gdk-pixbuf-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\freetype2&quot;;&quot;$(SolutionDir)\..\libxml2\include&quot;"\r
                                PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS"\r
                                MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
@@ -62,7 +62,7 @@
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="intl.lib user32.lib shell32.lib gdi32.lib comdlg32.lib l_net.lib cmdlib.lib mathlib.lib Wsock32.lib libxml2.lib glib-2.0.lib gobject-2.0.lib gdk-win32-2.0.lib gtk-win32-2.0.lib pango-1.0.lib pangoft2-1.0.lib gtkglext-win32-1.0.lib gdkglext-win32-1.0.lib"\r
-                               AdditionalLibraryDirectories="&quot;$(SolutionDir)\..\libxml2\lib&quot;;&quot;$(SolutionDir)\..\gtk2\lib&quot;;&quot;$(SolutionDir)\build\$(ConfigurationName)\libs&quot;;&quot;$(SolutionDir)..\gtk2\lib\gtkglext-1.0\lib&quot;"\r
+                               AdditionalLibraryDirectories="&quot;$(SolutionDir)\..\libxml2\lib&quot;;&quot;$(SolutionDir)\..\gtk2\lib&quot;;&quot;$(SolutionDir)\build\$(ConfigurationName)\libs&quot;;&quot;$(SolutionDir)\..\gtk2\lib\gtkglext-1.2.0\lib&quot;"\r
                                GenerateDebugInformation="true"\r
                                RandomizedBaseAddress="1"\r
                                DataExecutionPrevention="0"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               AdditionalIncludeDirectories="&quot;$(SolutionDir)\include&quot;;&quot;$(SolutionDir)\libs&quot;;&quot;$(SolutionDir)\..\STLPort\stlport&quot;;&quot;$(SolutionDir)\..\gtk2\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\glib-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\lib\glib-2.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\lib\gtk-2.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\lib\gtkglext-1.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\gtk-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\cairo&quot;;&quot;$(SolutionDir)\..\gtk2\include\pango-1.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\atk-1.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\gdk-pixbuf-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\freetype2&quot;;&quot;$(SolutionDir)\..\libxml2\include&quot;"\r
+                               AdditionalIncludeDirectories="&quot;$(SolutionDir)\include&quot;;&quot;$(SolutionDir)\libs&quot;;&quot;$(SolutionDir)\..\STLPort\stlport&quot;;&quot;$(SolutionDir)\..\gtk2\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\glib-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\lib\glib-2.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\lib\gtk-2.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\gtkglext-1.0&quot;;&quot;$(SolutionDir)\..\gtk2\lib\gtkglext-1.0\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\gtk-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\cairo&quot;;&quot;$(SolutionDir)\..\gtk2\include\pango-1.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\atk-1.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\gdk-pixbuf-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\include\freetype2&quot;;&quot;$(SolutionDir)\..\libxml2\include&quot;"\r
                                PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS"\r
                                RuntimeLibrary="2"\r
                                WarningLevel="3"\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="intl.lib user32.lib shell32.lib gdi32.lib comdlg32.lib l_net.lib cmdlib.lib mathlib.lib Wsock32.lib libxml2.lib glib-2.0.lib gobject-2.0.lib gdk-win32-2.0.lib gtk-win32-2.0.lib pango-1.0.lib pangoft2-1.0.lib gtkglext-win32-1.0.lib gdkglext-win32-1.0.lib"\r
-                               AdditionalLibraryDirectories="&quot;$(SolutionDir)\..\libxml2\lib&quot;;&quot;$(SolutionDir)\..\gtk2\lib&quot;;&quot;$(SolutionDir)\build\$(ConfigurationName)\libs&quot;;&quot;$(SolutionDir)..\gtk2\lib\gtkglext-1.0\lib&quot;"\r
+                               AdditionalLibraryDirectories="&quot;$(SolutionDir)\..\libxml2\lib&quot;;&quot;$(SolutionDir)\..\gtk2\lib&quot;;&quot;$(SolutionDir)\build\$(ConfigurationName)\libs&quot;;&quot;$(SolutionDir)\..\gtk2\lib\gtkglext-1.2.0\lib&quot;"\r
                                GenerateDebugInformation="true"\r
                                OptimizeReferences="2"\r
                                EnableCOMDATFolding="2"\r
                                        >\r
                                </File>\r
                                <File\r
-                                       RelativePath="..\..\src\gtk+\gtk\gtkmisc.h"\r
+                                       RelativePath=".\gtkmisc.h"\r
                                        >\r
                                </File>\r
                                <File\r
-                                       RelativePath=".\gtkmisc.h"\r
+                                       RelativePath="..\..\src\gtk+\gtk\gtkmisc.h"\r
                                        >\r
                                </File>\r
                                <File\r
                        Name="Misc"\r
                        >\r
                        <File\r
-                               RelativePath="..\..\src\gtk+\gdk\makefile.msc"\r
+                               RelativePath="..\..\src\glib\makefile.msc"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\src\gtk+\gdk\win32\makefile.msc"\r
+                               RelativePath="..\..\src\gtk+\gdk\makefile.msc"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\src\gtk+\gtk\makefile.msc"\r
+                               RelativePath="..\..\src\gtk+\gdk\win32\makefile.msc"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\..\src\glib\makefile.msc"\r
+                               RelativePath="..\..\src\gtk+\gtk\makefile.msc"\r
                                >\r
                        </File>\r
                </Filter>\r