From: TTimo Date: Sun, 26 Dec 2010 04:13:09 +0000 (+0000) Subject: move old gtk runtime code back to trunk X-Git-Tag: xonotic-v0.7.0~16^2~12^2~43 X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=commitdiff_plain;h=82ef81821f9f2721f338cb12074e7ee8a508decb;hp=2be17e386a471f0c7ca0a99391db02cb538639dd move old gtk runtime code back to trunk git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/trunk@361 8a3a26a2-13c4-0310-b231-cf6edde360e5 --- diff --git a/config.py b/config.py index 314b2d0d..e0f20a01 100644 --- 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 ) ) diff --git a/plugins/imagepng/plugin.cpp b/plugins/imagepng/plugin.cpp index fda3e6f0..5d8bba70 100644 --- a/plugins/imagepng/plugin.cpp +++ b/plugins/imagepng/plugin.cpp @@ -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); diff --git a/radiant/glwidget.cpp b/radiant/glwidget.cpp index 7a408f9e..57699b37 100644 --- a/radiant/glwidget.cpp +++ b/radiant/glwidget.cpp @@ -33,7 +33,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "stdafx.h" #include + +#ifndef _WIN32 #include +#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 } diff --git a/radiant/gtkmisc.cpp b/radiant/gtkmisc.cpp index 6b549180..93fed4a0 100644 --- a/radiant/gtkmisc.cpp +++ b/radiant/gtkmisc.cpp @@ -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; - char* w; + 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(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; } diff --git a/radiant/preferences.cpp b/radiant/preferences.cpp index f44aca8a..03486fd8 100644 --- a/radiant/preferences.cpp +++ b/radiant/preferences.cpp @@ -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); diff --git a/radiant/radiant_VC9.vcproj b/radiant/radiant_VC9.vcproj index 13e0cad3..9f8c8cfb 100755 --- a/radiant/radiant_VC9.vcproj +++ b/radiant/radiant_VC9.vcproj @@ -40,7 +40,7 @@