Added Windows dialogs for Project new and Project open actions.

Fixed some mem leaks in the Windows code.

git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@1307 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
Enrico Tröger 2007-02-19 18:58:32 +00:00
parent 1e34e879c3
commit 64f34f1f59
4 changed files with 225 additions and 38 deletions

View File

@ -1,6 +1,9 @@
2007-02-19 Enrico Tröger <enrico.troeger@uvena.de> 2007-02-19 Enrico Tröger <enrico.troeger@uvena.de>
* src/search.c: Fixed compiler warning. * src/search.c: Fixed compiler warning.
* src/project.c, src/win32.c, src/win32.h:
Added Windows dialogs for Project new and Project open actions.
Fixed some mem leaks in the Windows code.
2007-02-19 Nick Treleaven <nick.treleaven@btinternet.com> 2007-02-19 Nick Treleaven <nick.treleaven@btinternet.com>

View File

@ -55,7 +55,9 @@ static void on_properties_dialog_response(GtkDialog *dialog, gint response,
PropertyDialogElements *e); PropertyDialogElements *e);
static void on_file_open_button_clicked(GtkButton *button, GtkWidget *entry); static void on_file_open_button_clicked(GtkButton *button, GtkWidget *entry);
static void on_folder_open_button_clicked(GtkButton *button, GtkWidget *entry); static void on_folder_open_button_clicked(GtkButton *button, GtkWidget *entry);
#ifndef G_OS_WIN32
static void on_open_dialog_response(GtkDialog *dialog, gint response, gpointer user_data); static void on_open_dialog_response(GtkDialog *dialog, gint response, gpointer user_data);
#endif
static gboolean close_open_project(); static gboolean close_open_project();
static gboolean load_config(const gchar *filename); static gboolean load_config(const gchar *filename);
static gboolean write_config(); static gboolean write_config();
@ -80,15 +82,23 @@ void project_new()
void project_open() void project_open()
{ {
#ifndef G_OS_WIN32 gchar *dir = g_strconcat(GEANY_HOME_DIR, G_DIR_SEPARATOR_S, PROJECT_DIR, NULL);
#ifdef G_OS_WIN32
gchar *file;
#else
GtkWidget *dialog; GtkWidget *dialog;
GtkFileFilter *filter; GtkFileFilter *filter;
gchar *dir;
#endif #endif
if (! close_open_project()) return; if (! close_open_project()) return;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
win32_show_file_dialog(TRUE); file = win32_show_project_open_dialog(_("Open project"), dir, FALSE);
if (file != NULL)
{
load_config(file);
g_free(file);
g_free(dir);
}
#else #else
dialog = gtk_file_chooser_dialog_new(_("Open project"), GTK_WINDOW(app->window), dialog = gtk_file_chooser_dialog_new(_("Open project"), GTK_WINDOW(app->window),
@ -115,7 +125,6 @@ void project_open()
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
dir = g_strconcat(GEANY_HOME_DIR, G_DIR_SEPARATOR_S, PROJECT_DIR, NULL);
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir);
g_free(dir); g_free(dir);
@ -462,9 +471,10 @@ static void on_properties_dialog_response(GtkDialog *dialog, gint response,
} }
#ifndef G_OS_WIN32
static void run_dialog(GtkWidget *dialog, GtkWidget *entry) static void run_dialog(GtkWidget *dialog, GtkWidget *entry)
{ {
// set filename // set filename in the file chooser dialog
gchar *locale_filename = utils_get_locale_from_utf8(gtk_entry_get_text(GTK_ENTRY(entry))); gchar *locale_filename = utils_get_locale_from_utf8(gtk_entry_get_text(GTK_ENTRY(entry)));
if (g_path_is_absolute(locale_filename)) if (g_path_is_absolute(locale_filename))
@ -486,13 +496,19 @@ static void run_dialog(GtkWidget *dialog, GtkWidget *entry)
} }
gtk_widget_destroy(dialog); gtk_widget_destroy(dialog);
} }
#endif
static void on_file_open_button_clicked(GtkButton *button, GtkWidget *entry) static void on_file_open_button_clicked(GtkButton *button, GtkWidget *entry)
{ {
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
/// TODO write me gchar *path = win32_show_project_open_dialog(_("Choose project filename"),
//win32_show_project_file_dialog(item); gtk_entry_get_text(GTK_ENTRY(entry)), TRUE);
if (path != NULL)
{
gtk_entry_set_text(GTK_ENTRY(entry), path);
g_free(path);
}
#else #else
GtkWidget *dialog; GtkWidget *dialog;
@ -514,8 +530,13 @@ static void on_file_open_button_clicked(GtkButton *button, GtkWidget *entry)
static void on_folder_open_button_clicked(GtkButton *button, GtkWidget *entry) static void on_folder_open_button_clicked(GtkButton *button, GtkWidget *entry)
{ {
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
/// TODO write me gchar *path = win32_show_project_folder_dialog(_("Choose project base path"),
//win32_show_project_folder_dialog(item); gtk_entry_get_text(GTK_ENTRY(entry)));
if (path != NULL)
{
gtk_entry_set_text(GTK_ENTRY(entry), path);
g_free(path);
}
#else #else
GtkWidget *dialog; GtkWidget *dialog;
@ -579,6 +600,7 @@ static void on_entries_changed(GtkEditable *editable, PropertyDialogElements *e)
} }
#ifndef G_OS_WIN32
static void on_open_dialog_response(GtkDialog *dialog, gint response, gpointer user_data) static void on_open_dialog_response(GtkDialog *dialog, gint response, gpointer user_data)
{ {
if (response == GTK_RESPONSE_ACCEPT) if (response == GTK_RESPONSE_ACCEPT)
@ -601,6 +623,7 @@ static void on_open_dialog_response(GtkDialog *dialog, gint response, gpointer u
else else
gtk_widget_destroy(GTK_WIDGET(dialog)); gtk_widget_destroy(GTK_WIDGET(dialog));
} }
#endif
/* Reads the given filename and creates a new project with the data found in the file. /* Reads the given filename and creates a new project with the data found in the file.

View File

@ -30,12 +30,15 @@
#include <windows.h> #include <windows.h>
#include <commdlg.h> #include <commdlg.h>
#include <shlobj.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <gdk/gdkwin32.h>
#include "win32.h" #include "win32.h"
#include "document.h" #include "document.h"
@ -46,33 +49,27 @@
#include "dialogs.h" #include "dialogs.h"
static gchar *filters;
static gchar *exe_filters;
static gchar *win32_get_file_filters()
static gchar *win32_get_filters(gboolean exe)
{ {
gchar *string = ""; gchar *string;
gint i, len; gint i, len;
if (exe) GString *str = g_string_sized_new(100);
{ gchar *tmp;
string = g_strconcat(string,
_("Executables"), "\t", "*.exe;*.bat;*.cmd", "\t", for (i = 0; i < GEANY_MAX_FILE_TYPES; i++)
filetypes[GEANY_FILETYPES_ALL]->title, "\t",
g_strjoinv(";", filetypes[GEANY_FILETYPES_ALL]->pattern), "\t", NULL);
}
else
{
for(i = 0; i < GEANY_MAX_FILE_TYPES; i++)
{ {
if (filetypes[i]) if (filetypes[i])
{ {
string = g_strconcat(string, filetypes[i]->title, "\t", g_strjoinv(";", filetypes[i]->pattern), "\t", NULL); tmp = g_strjoinv(";", filetypes[i]->pattern);
g_string_append_printf(str, "%s\t%s\t", filetypes[i]->title, tmp);
g_free(tmp);
} }
} }
} g_string_append_c(str, '\t'); // the final \0 byte to mark the end of the string
string = g_strconcat(string, "\t", NULL); string = str->str;
g_string_free(str, FALSE);
// replace all "\t"s by \0 // replace all "\t"s by \0
len = strlen(string); len = strlen(string);
@ -84,6 +81,159 @@ static gchar *win32_get_filters(gboolean exe)
} }
static gchar *win32_get_filters(gboolean exe)
{
gchar *string;
gint i, len;
if (exe)
{
string = g_strconcat(_("Executables"), "\t", "*.exe;*.bat;*.cmd", "\t",
filetypes[GEANY_FILETYPES_ALL]->title, "\t",
filetypes[GEANY_FILETYPES_ALL]->pattern[0], "\t", NULL);
}
else
{
string = g_strconcat(_("Geany project files"), "\t", "*." GEANY_PROJECT_EXT, "\t",
filetypes[GEANY_FILETYPES_ALL]->title, "\t",
filetypes[GEANY_FILETYPES_ALL]->pattern[0], "\t", NULL);
}
// replace all "\t"s by \0
len = strlen(string);
for(i = 0; i < len; i++)
{
if (string[i] == '\t') string[i] = '\0';
}
return string;
}
/* Returns the directory part of the given filename. */
static gchar *get_dir(const gchar *filename)
{
if (! g_file_test(filename, G_FILE_TEST_IS_DIR))
return g_path_get_dirname(filename);
else
return g_strdup(filename);
}
/* Callback function for setting the initial directory of the folder open dialog. This could also
* be done with BROWSEINFO.pidlRoot and SHParseDisplayName but SHParseDisplayName is not available
* on systems below Windows XP. So, we go the hard way by creating a callback which will set up the
* folder when the dialog is initialised. Yeah, I like Windows. */
INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
{
switch(uMsg)
{
case BFFM_INITIALIZED:
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM) pData);
break;
case BFFM_SELCHANGED:
{
// set the status window to the currently selected path.
static TCHAR szDir[MAX_PATH];
if (SHGetPathFromIDList((LPITEMIDLIST) lp, szDir))
{
SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM) szDir);
}
break;
}
}
return 0;
}
/* Shows a folder selection dialog.
* The selected folder name is returned. */
gchar *win32_show_project_folder_dialog(const gchar *title, const gchar *initial_dir)
{
BROWSEINFO bi;
LPCITEMIDLIST pidl;
gchar *fname = g_malloc(MAX_PATH);
gchar *dir = get_dir(initial_dir);
memset(&bi, 0, sizeof bi);
bi.hwndOwner = GDK_WINDOW_HWND(app->window->window);
bi.pidlRoot = NULL;
bi.lpszTitle = title;
bi.lpfn = BrowseCallbackProc;
bi.lParam = (LPARAM) dir;
bi.ulFlags = BIF_DONTGOBELOWDOMAIN | BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
pidl = SHBrowseForFolder(&bi);
g_free(dir);
// convert the strange Windows folder list item something into an usual path string ;-)
if (pidl != NULL && SHGetPathFromIDList(pidl, fname))
return fname;
else
{
g_free(fname);
return NULL;
}
}
/* Shows a file open dialog.
* If allow_new_file is set, the file to be opened doesn't have to exist.
* The selected file name is returned. */
gchar *win32_show_project_open_dialog(const gchar *title, const gchar *initial_dir, gboolean allow_new_file)
{
OPENFILENAME of;
gint retval;
gchar *fname = g_malloc(2048);
gchar *filters = win32_get_filters(FALSE);
gchar *dir = get_dir(initial_dir);
fname[0] = '\0';
/* initialise file dialog info struct */
memset(&of, 0, sizeof of);
#ifdef OPENFILENAME_SIZE_VERSION_400
of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
#else
of.lStructSize = sizeof of;
#endif
of.hwndOwner = GDK_WINDOW_HWND(app->window->window);
of.lpstrFilter = filters;
of.lpstrCustomFilter = NULL;
of.nFilterIndex = 0;
of.lpstrFile = fname;
of.lpstrInitialDir = dir;
of.nMaxFile = 2048;
of.lpstrFileTitle = NULL;
of.lpstrTitle = title;
of.lpstrDefExt = "";
of.Flags = OFN_PATHMUSTEXIST | OFN_EXPLORER | OFN_HIDEREADONLY;
if (! allow_new_file)
of.Flags |= OFN_FILEMUSTEXIST;
retval = GetOpenFileName(&of);
g_free(dir);
g_free(filters);
if (! retval)
{
if (CommDlgExtendedError())
{
gchar *error;
error = g_strdup_printf("File dialog box error (%x)", (int)CommDlgExtendedError());
win32_message_dialog(GTK_MESSAGE_ERROR, error);
g_free(error);
}
g_free(fname);
return NULL;
}
return fname;
}
// return TRUE if the dialog was not cancelled. // return TRUE if the dialog was not cancelled.
gboolean win32_show_file_dialog(gboolean file_open) gboolean win32_show_file_dialog(gboolean file_open)
{ {
@ -91,11 +241,10 @@ gboolean win32_show_file_dialog(gboolean file_open)
gint retval; gint retval;
gchar *fname = g_malloc(2048); gchar *fname = g_malloc(2048);
gchar *current_dir = utils_get_current_file_dir(); gchar *current_dir = utils_get_current_file_dir();
gchar *filters = win32_get_file_filters();
fname[0] = '\0'; fname[0] = '\0';
if (! filters) filters = win32_get_filters(FALSE);
/* initialize file dialog info struct */ /* initialize file dialog info struct */
memset(&of, 0, sizeof of); memset(&of, 0, sizeof of);
#ifdef OPENFILENAME_SIZE_VERSION_400 #ifdef OPENFILENAME_SIZE_VERSION_400
@ -103,7 +252,7 @@ gboolean win32_show_file_dialog(gboolean file_open)
#else #else
of.lStructSize = sizeof of; of.lStructSize = sizeof of;
#endif #endif
of.hwndOwner = NULL; of.hwndOwner = GDK_WINDOW_HWND(app->window->window);
of.lpstrFilter = filters; of.lpstrFilter = filters;
of.lpstrCustomFilter = NULL; of.lpstrCustomFilter = NULL;
@ -126,6 +275,7 @@ gboolean win32_show_file_dialog(gboolean file_open)
} }
g_free(current_dir); g_free(current_dir);
g_free(filters);
if (!retval) if (!retval)
{ {
@ -183,7 +333,7 @@ void win32_show_font_dialog(void)
memset(&cf, 0, sizeof cf); memset(&cf, 0, sizeof cf);
cf.lStructSize = sizeof cf; cf.lStructSize = sizeof cf;
cf.hwndOwner = NULL; cf.hwndOwner = GDK_WINDOW_HWND(app->window->window);
cf.lpLogFont = &lf; cf.lpLogFont = &lf;
cf.Flags = CF_APPLY | CF_NOSCRIPTSEL | CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS; cf.Flags = CF_APPLY | CF_NOSCRIPTSEL | CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
@ -220,7 +370,7 @@ void win32_show_color_dialog(const gchar *colour)
// Initialize CHOOSECOLOR // Initialize CHOOSECOLOR
memset(&cc, 0, sizeof cc); memset(&cc, 0, sizeof cc);
cc.lStructSize = sizeof(cc); cc.lStructSize = sizeof(cc);
cc.hwndOwner = NULL; cc.hwndOwner = GDK_WINDOW_HWND(app->window->window);
cc.lpCustColors = (LPDWORD) acr_cust_clr; cc.lpCustColors = (LPDWORD) acr_cust_clr;
cc.rgbResult = (colour != NULL) ? utils_strtod(colour, NULL, colour[0] == '#') : 0; cc.rgbResult = (colour != NULL) ? utils_strtod(colour, NULL, colour[0] == '#') : 0;
cc.Flags = CC_FULLOPEN | CC_RGBINIT; cc.Flags = CC_FULLOPEN | CC_RGBINIT;
@ -245,9 +395,9 @@ void win32_show_pref_file_dialog(GtkEntry *item)
gint retval; gint retval;
gchar *fname = g_malloc(512); gchar *fname = g_malloc(512);
gchar **field, *filename, *tmp; gchar **field, *filename, *tmp;
gchar *filters = win32_get_filters(TRUE);
fname[0] = '\0'; fname[0] = '\0';
if (! exe_filters) exe_filters = win32_get_filters(TRUE);
// cut the options from the command line // cut the options from the command line
field = g_strsplit(gtk_entry_get_text(GTK_ENTRY(item)), " ", 2); field = g_strsplit(gtk_entry_get_text(GTK_ENTRY(item)), " ", 2);
@ -265,9 +415,9 @@ void win32_show_pref_file_dialog(GtkEntry *item)
#else #else
of.lStructSize = sizeof of; of.lStructSize = sizeof of;
#endif #endif
of.hwndOwner = NULL; of.hwndOwner = GDK_WINDOW_HWND(app->window->window);
of.lpstrFilter = exe_filters; of.lpstrFilter = filters;
of.lpstrCustomFilter = NULL; of.lpstrCustomFilter = NULL;
of.nFilterIndex = 1; of.nFilterIndex = 1;
@ -281,6 +431,8 @@ void win32_show_pref_file_dialog(GtkEntry *item)
of.Flags = OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_EXPLORER; of.Flags = OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_EXPLORER;
retval = GetOpenFileName(&of); retval = GetOpenFileName(&of);
g_free(filters);
if (!retval) if (!retval)
{ {
if (CommDlgExtendedError()) if (CommDlgExtendedError())
@ -360,7 +512,7 @@ gboolean win32_message_dialog(GtkMessageType type, const gchar *msg)
MultiByteToWideChar(CP_UTF8, 0, title, -1, w_title, sizeof(w_title)/sizeof(w_title[0])); MultiByteToWideChar(CP_UTF8, 0, title, -1, w_title, sizeof(w_title)/sizeof(w_title[0]));
// display the message box // display the message box
rc = MessageBoxW(NULL, w_msg, w_title, t); rc = MessageBoxW(GDK_WINDOW_HWND(app->window->window), w_msg, w_title, t);
if (type == GTK_MESSAGE_QUESTION && rc != IDYES) if (type == GTK_MESSAGE_QUESTION && rc != IDYES)
ret = FALSE; ret = FALSE;
@ -380,7 +532,7 @@ gint win32_message_dialog_unsaved(const gchar *msg)
MultiByteToWideChar(CP_UTF8, 0, msg, -1, w_msg, sizeof(w_msg)/sizeof(w_msg[0])); MultiByteToWideChar(CP_UTF8, 0, msg, -1, w_msg, sizeof(w_msg)/sizeof(w_msg[0]));
MultiByteToWideChar(CP_UTF8, 0, _("Question"), -1, w_title, sizeof(w_title)/sizeof(w_title[0])); MultiByteToWideChar(CP_UTF8, 0, _("Question"), -1, w_title, sizeof(w_title)/sizeof(w_title[0]));
ret = MessageBoxW(NULL, w_msg, w_title, MB_YESNOCANCEL | MB_ICONQUESTION); ret = MessageBoxW(GDK_WINDOW_HWND(app->window->window), w_msg, w_title, MB_YESNOCANCEL | MB_ICONQUESTION);
switch(ret) switch(ret)
{ {
case IDYES: ret = GTK_RESPONSE_YES; break; case IDYES: ret = GTK_RESPONSE_YES; break;

View File

@ -44,4 +44,13 @@ gint win32_message_dialog_unsaved(const gchar *msg);
/* Just a simple wrapper function to open a browser window */ /* Just a simple wrapper function to open a browser window */
void win32_open_browser(const gchar *uri); void win32_open_browser(const gchar *uri);
/* Shows a file open dialog.
* If allow_new_file is set, the file to be opened doesn't have to exist.
* The selected file name is returned. */
gchar *win32_show_project_open_dialog(const gchar *title, const gchar *initial_dir, gboolean allow_new_file);
/* Shows a folder selection dialog.
* The selected folder name is returned. */
gchar *win32_show_project_folder_dialog(const gchar *title, const gchar *initial_dir);
#endif #endif