Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ A small C library for opening a file dialog on Windows and Linux.
## Usage
**[sfd.c](src/sfd.c?raw=1)** and **[sfd.h](src/sfd.h?raw=1)** should be dropped
into an existing project and compiled along with it — on Windows `comdlg32`
should be linked.
should be linked. On Linux, sfd opens a pipe to `zenity` by default. You can
use a GTK dialog instead by defining `SFD_GTK` and linking to gtk3.

The library provides a function for *open* dialogs and one for *save* dialogs:

Expand Down
79 changes: 77 additions & 2 deletions src/sfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,88 @@ const char* sfd_save_dialog(sfd_Options *opt) {

#endif

#ifndef _WIN32

#ifdef SFD_GTK
/******************************************************************************
** Zenity
** GTK
*******************************************************************************/
#include <gtk/gtk.h>
#include <stdbool.h>

static const char* file_dialog(sfd_Options *opt, int save) {
static char result_buf[2048];
static bool gtk_inited = false;
if (!gtk_inited) {
gtk_init(NULL, NULL);
gtk_inited = true;
}

GtkWidget *dialog = gtk_file_chooser_dialog_new(
opt->title, NULL,
save ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN,
"Cancel", GTK_RESPONSE_CANCEL,
save ? "Save" : "Open", GTK_RESPONSE_ACCEPT,
NULL
);

if (opt->path && opt->path[0] != '\0') {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), opt->path);
}

if (opt->filter) {
GtkFileFilter *filter = gtk_file_filter_new();
gtk_file_filter_set_name(filter, opt->filter_name);

char filter_buf[256];
strncpy(filter_buf, opt->filter, sizeof(filter_buf) - 1);
filter_buf[sizeof(filter_buf) - 1] = '\0';
char *s = strtok(filter_buf, "|");
while (s != NULL) {
gtk_file_filter_add_pattern(filter, s);
s = strtok(NULL, "|");
}

gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
}

GtkFileFilter *filter = gtk_file_filter_new();
gtk_file_filter_set_name(filter, "All files");
gtk_file_filter_add_pattern(filter, "*");
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);

gint resp = gtk_dialog_run(GTK_DIALOG(dialog));
char *out = NULL;
if (resp == GTK_RESPONSE_ACCEPT) {
char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
strncpy(result_buf, filename, sizeof(result_buf) - 1);
result_buf[sizeof(result_buf) - 1] = 0;
g_free(filename);

if (save && opt->extension && !strstr(result_buf, opt->extension)) {
strncat(result_buf, opt->extension, sizeof(result_buf) - strlen(opt->extension) - 1);
}
}

gtk_widget_destroy(dialog);

return result_buf;
}


const char* sfd_open_dialog(sfd_Options *opt) {
return file_dialog(opt, 0);
}

#ifndef _WIN32

const char* sfd_save_dialog(sfd_Options *opt) {
return file_dialog(opt, 1);
}

#else
/******************************************************************************
** Zenity
*******************************************************************************/
static const char* file_dialog(sfd_Options *opt, int save) {
static char result_buf[2048];
char buf[2048];
Expand Down Expand Up @@ -257,5 +331,6 @@ const char* sfd_save_dialog(sfd_Options *opt) {
return file_dialog(opt, 1);
}

#endif

#endif