From dede76e56ac0b35a65b27bb93a1a7110ef6f0e8a Mon Sep 17 00:00:00 2001 From: "berkeviktor@aol.com" Date: Tue, 5 Oct 2010 05:30:22 +0200 Subject: [PATCH] native file open/save dialogs --- src/common/thread.c | 33 +++++ src/common/thread.h | 10 ++ src/makeinc.skel | 3 +- xchat-wdk.patch | 292 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 335 insertions(+), 3 deletions(-) create mode 100644 src/common/thread.c create mode 100644 src/common/thread.h diff --git a/src/common/thread.c b/src/common/thread.c new file mode 100644 index 00000000..02b17cfb --- /dev/null +++ b/src/common/thread.c @@ -0,0 +1,33 @@ +#include +#include "thread.h" + +thread * +thread_new (void) +{ + thread *th; + + th = calloc (1, sizeof (*th)); + if (!th) + { + return NULL; + } + + if (_pipe (th->pipe_fd, 4096, _O_BINARY) == -1) + { + free (th); + return NULL; + } + + return th; +} + +int +thread_start (thread *th, void *(*start_routine)(void *), void *arg) +{ + DWORD id; + + CloseHandle (CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, arg, 0, (DWORD *)&id)); + th->threadid = id; + + return 1; +} diff --git a/src/common/thread.h b/src/common/thread.h new file mode 100644 index 00000000..7ca0f937 --- /dev/null +++ b/src/common/thread.h @@ -0,0 +1,10 @@ +#include + +typedef struct +{ + DWORD threadid; + int pipe_fd[2]; +} thread; + +thread *thread_new (void); +int thread_start (thread *th, void *(*start_routine)(void *), void *arg); diff --git a/src/makeinc.skel b/src/makeinc.skel index 8961928b..5612d85f 100644 --- a/src/makeinc.skel +++ b/src/makeinc.skel @@ -5,7 +5,7 @@ CFLAGS = $(CFLAGS) /DWIN32 /DG_DISABLE_CAST_CHECKS /DG_DISABLE_DEPRECATED /DGDK_ CFLAGS = $(CFLAGS) -Ic:\mozilla-build\build\xchat-wdk\plugins CPPFLAGS = /c /MD /W0 /nologo /DWIN32 LDFLAGS = /subsystem:windows /nologo -LIBS = $(LIBS) gdi32.lib shell32.lib user32.lib advapi32.lib imm32.lib ole32.lib winmm.lib ws2_32.lib wininet.lib +LIBS = $(LIBS) gdi32.lib shell32.lib user32.lib advapi32.lib imm32.lib ole32.lib winmm.lib ws2_32.lib wininet.lib comdlg32.lib !ifdef X64 ############################################################# @@ -77,6 +77,7 @@ server.obj \ servlist.obj \ ssl.obj \ text.obj \ +thread.obj \ tree.obj \ url.obj \ userlist.obj \ diff --git a/xchat-wdk.patch b/xchat-wdk.patch index 5666685e..2420d0b3 100644 --- a/xchat-wdk.patch +++ b/xchat-wdk.patch @@ -882,7 +882,7 @@ diff -ruN --strip-trailing-cr xchat-wdk.orig/src/fe-gtk/fkeys.c xchat-wdk/src/fe #include diff -ruN --strip-trailing-cr xchat-wdk.orig/src/fe-gtk/gtkutil.c xchat-wdk/src/fe-gtk/gtkutil.c --- xchat-wdk.orig/src/fe-gtk/gtkutil.c 2009-07-18 14:38:10 +0200 -+++ xchat-wdk/src/fe-gtk/gtkutil.c 2010-10-05 03:55:27 +0200 ++++ xchat-wdk/src/fe-gtk/gtkutil.c 2010-10-05 05:22:28 +0200 @@ -22,7 +22,6 @@ #include #include @@ -891,6 +891,283 @@ diff -ruN --strip-trailing-cr xchat-wdk.orig/src/fe-gtk/gtkutil.c xchat-wdk/src/ #include #include "fe-gtk.h" +@@ -51,6 +50,10 @@ + #include "../common/util.h" + #include "gtkutil.h" + #include "pixmaps.h" ++#ifdef WIN32 ++#include "../common/fe.h" ++#include "../common/thread.h" ++#endif + + /* gtkutil.c, just some gtk wrappers */ + +@@ -63,6 +66,13 @@ + void *userdata; + filereqcallback callback; + int flags; /* FRF_* flags */ ++ ++#ifdef WIN32 ++ int multiple; ++ thread *th; ++ char *title; /* native locale */ ++ char *filter; ++#endif + }; + + static char last_dir[256] = ""; +@@ -164,6 +174,196 @@ + } + } + ++#ifdef WIN32 ++static int ++win32_openfile (char *file_buf, int file_buf_len, char *title_text, char *filter, ++ int multiple) ++{ ++ OPENFILENAME o; ++ ++ memset (&o, 0, sizeof (o)); ++ ++ o.lStructSize = sizeof (o); ++ o.lpstrFilter = filter; ++ o.lpstrFile = file_buf; ++ o.nMaxFile = file_buf_len; ++ o.lpstrTitle = title_text; ++ o.Flags = 0x02000000 | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | ++ OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_LONGNAMES | OFN_NONETWORKBUTTON; ++ if (multiple) ++ o.Flags |= OFN_ALLOWMULTISELECT; ++ ++ return GetOpenFileName (&o); ++} ++ ++static int ++win32_savefile (char *file_buf, int file_buf_len, char *title_text, char *filter, ++ int multiple) ++{ ++ OPENFILENAME o; ++ ++ memset (&o, 0, sizeof (o)); ++ ++ o.lStructSize = sizeof (o); ++ o.lpstrFilter = filter; ++ o.lpstrFile = file_buf; ++ o.nMaxFile = file_buf_len; ++ o.lpstrTitle = title_text; ++ o.Flags = 0x02000000 | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | ++ OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_LONGNAMES | OFN_NONETWORKBUTTON; ++ if (multiple) ++ o.Flags |= OFN_ALLOWMULTISELECT; ++ ++ return GetSaveFileName (&o); ++} ++ ++static void * ++win32_thread (struct file_req *freq) ++{ ++ char buf[1024 + 32]; ++ char file[1024]; ++ ++ memset (file, 0, sizeof (file)); ++ safe_strcpy (file, last_dir, sizeof (file)); ++ ++ if (win32_openfile (file, sizeof (file), freq->title, freq->filter, freq->multiple)) ++ { ++ if (freq->multiple) ++ { ++ char *f = file; ++ ++ if (f[strlen (f) + 1] == 0) /* only selected one file */ ++ { ++ snprintf (buf, sizeof (buf), "1\n%s\n", file); ++ write (freq->th->pipe_fd[1], buf, strlen (buf)); ++ } else ++ { ++ f += strlen (f) + 1; /* skip first, it's only the dir */ ++ while (f[0]) ++ { ++ snprintf (buf, sizeof (buf), "1\n%s\\%s\n", /*dir!*/file, f); ++ write (freq->th->pipe_fd[1], buf, strlen (buf)); ++ f += strlen (f) + 1; ++ } ++ } ++ ++ } else ++ { ++ snprintf (buf, sizeof (buf), "1\n%s\n", file); ++ write (freq->th->pipe_fd[1], buf, strlen (buf)); ++ } ++ } ++ ++ write (freq->th->pipe_fd[1], "0\n", 2); ++ Sleep (2000); ++ ++ return NULL; ++} ++ ++static void * ++win32_thread2 (struct file_req *freq) ++{ ++ char buf[1024 + 32]; ++ char file[1024]; ++ ++ memset (file, 0, sizeof (file)); ++ safe_strcpy (file, last_dir, sizeof (file)); ++ ++ if (win32_savefile (file, sizeof (file), freq->title, freq->filter, freq->multiple)) ++ { ++ if (freq->multiple) ++ { ++ char *f = file; ++ ++ if (f[strlen (f) + 1] == 0) /* only selected one file */ ++ { ++ snprintf (buf, sizeof (buf), "1\n%s\n", file); ++ write (freq->th->pipe_fd[1], buf, strlen (buf)); ++ } else ++ { ++ f += strlen (f) + 1; /* skip first, it's only the dir */ ++ while (f[0]) ++ { ++ snprintf (buf, sizeof (buf), "1\n%s\\%s\n", /*dir!*/file, f); ++ write (freq->th->pipe_fd[1], buf, strlen (buf)); ++ f += strlen (f) + 1; ++ } ++ } ++ ++ } else ++ { ++ snprintf (buf, sizeof (buf), "1\n%s\n", file); ++ write (freq->th->pipe_fd[1], buf, strlen (buf)); ++ } ++ } ++ ++ write (freq->th->pipe_fd[1], "0\n", 2); ++ Sleep (2000); ++ ++ return NULL; ++} ++ ++static int ++waitline2 (GIOChannel *source, char *buf, int bufsize) ++{ ++ int i = 0; ++ int len; ++ ++ while (1) ++ { ++ if (g_io_channel_read (source, &buf[i], 1, &len) != G_IO_ERROR_NONE) ++ return -1; ++ if (buf[i] == '\n' || bufsize == i + 1) ++ { ++ buf[i] = 0; ++ return i; ++ } ++ i++; ++ } ++} ++ ++static gboolean ++win32_close_pipe (int fd) ++{ ++ close (fd); ++ return 0; ++} ++ ++static gboolean ++win32_read_thread (GIOChannel *source, GIOCondition cond, struct file_req *freq) ++{ ++ char buf[512]; ++ char *file; ++ ++ waitline2 (source, buf, sizeof buf); ++ ++ switch (buf[0]) ++ { ++ case '0': /* filedialog has closed */ ++ freq->callback (freq->userdata, NULL); ++ break; ++ ++ case '1': /* got a filename! */ ++ waitline2 (source, buf, sizeof buf); ++ file = g_filename_to_utf8 (buf, -1, 0, 0, 0); ++ freq->callback (freq->userdata, file); ++ g_free (file); ++ return TRUE; ++ } ++ ++ /* it doesn't work to close them here, because of the weird ++ way giowin32 works. We must _return_ before closing them */ ++ g_timeout_add(3000, (GSourceFunc)win32_close_pipe, freq->th->pipe_fd[0]); ++ g_timeout_add(2000, (GSourceFunc)win32_close_pipe, freq->th->pipe_fd[1]); ++ ++ g_free (freq->title); ++ free (freq->th); ++ free (freq); ++ ++ return FALSE; ++} ++#endif ++ + void + gtkutil_file_req (const char *title, void *callback, void *userdata, char *filter, + int flags) +@@ -172,6 +372,54 @@ + GtkWidget *dialog; + extern char *get_xdir_fs (void); + ++#ifdef WIN32 ++ if (!(flags & FRF_WRITE)) ++ { ++ freq = malloc (sizeof (struct file_req)); ++ freq->th = thread_new (); ++ freq->flags = 0; ++ freq->multiple = (flags & FRF_MULTIPLE); ++ freq->callback = callback; ++ freq->userdata = userdata; ++ freq->title = g_locale_from_utf8 (title, -1, 0, 0, 0); ++ if (!filter) ++ freq->filter = "All files\000*.*\000" ++ "EXE files\000*.EXE\000" ++ "MP3 files\000*.MP3\000" ++ "MPEG files\000*.MPG;*.MPEG\000" ++ "RAR files\000*.RAR\000" ++ "ZIP files\000*.ZIP\000"; ++ else ++ freq->filter = filter; ++ ++ thread_start (freq->th, win32_thread, freq); ++ fe_input_add (freq->th->pipe_fd[0], FIA_FD|FIA_READ, win32_read_thread, freq); ++ ++ return; ++ ++ } ++ ++ else { ++ freq = malloc (sizeof (struct file_req)); ++ freq->th = thread_new (); ++ freq->flags = 0; ++ freq->multiple = (flags & FRF_MULTIPLE); ++ freq->callback = callback; ++ freq->userdata = userdata; ++ freq->title = g_locale_from_utf8 (title, -1, 0, 0, 0); ++ if (!filter) ++ freq->filter = "Text files\000*.TXT\000" ++ "All files\000*.*\000"; ++ else ++ freq->filter = filter; ++ ++ thread_start (freq->th, win32_thread2, freq); ++ fe_input_add (freq->th->pipe_fd[0], FIA_FD|FIA_READ, win32_read_thread, freq); ++ ++ return; ++ } ++#endif ++ + if (flags & FRF_WRITE) + { + dialog = gtk_file_chooser_dialog_new (title, NULL, diff -ruN --strip-trailing-cr xchat-wdk.orig/src/fe-gtk/joind.c xchat-wdk/src/fe-gtk/joind.c --- xchat-wdk.orig/src/fe-gtk/joind.c 2006-12-26 05:56:55 +0100 +++ xchat-wdk/src/fe-gtk/joind.c 2010-10-05 03:55:27 +0200 @@ -1195,7 +1472,7 @@ diff -ruN --strip-trailing-cr xchat-wdk.orig/src/fe-gtk/plugin-tray.c xchat-wdk/ return 1; /* return 1 for success */ diff -ruN --strip-trailing-cr xchat-wdk.orig/src/fe-gtk/plugingui.c xchat-wdk/src/fe-gtk/plugingui.c --- xchat-wdk.orig/src/fe-gtk/plugingui.c 2010-05-16 05:20:22 +0200 -+++ xchat-wdk/src/fe-gtk/plugingui.c 2010-10-05 03:55:28 +0200 ++++ xchat-wdk/src/fe-gtk/plugingui.c 2010-10-05 02:53:43 +0200 @@ -35,7 +35,7 @@ #include "../common/xchat.h" #define PLUGIN_C @@ -1205,6 +1482,17 @@ diff -ruN --strip-trailing-cr xchat-wdk.orig/src/fe-gtk/plugingui.c xchat-wdk/sr #include "../common/plugin.h" #include "../common/util.h" #include "../common/outbound.h" +@@ -147,7 +147,9 @@ + plugingui_load (void) + { + gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, +- current_sess, NULL, FRF_ADDFOLDER); ++ current_sess, ++ "Plugins and Scripts\000" "*.dll;*.pl;*.tcl;*.py;*.lua\000" ++ "All files\000" "*.*\000", 0); + } + + static void diff -ruN --strip-trailing-cr xchat-wdk.orig/src/fe-gtk/rawlog.c xchat-wdk/src/fe-gtk/rawlog.c --- xchat-wdk.orig/src/fe-gtk/rawlog.c 2010-05-16 05:20:22 +0200 +++ xchat-wdk/src/fe-gtk/rawlog.c 2010-10-05 03:55:28 +0200