Merge in current Win32 version. Almost no Unix code touched.
authorTor Lillqvist <tml@src.gnome.org>
Sat, 16 Jan 1999 23:46:42 +0000 (23:46 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Sat, 16 Jan 1999 23:46:42 +0000 (23:46 +0000)
* README.win32: More text.

* config.h.win32 glibconfig.h.win32: Update to match the
corresponding generated files on Unix.

* makefile.msc: Update with new source files, and gthread
  library. Use the compiler flag -MD instead of using -D_DLL and
"/nodefaultlib:libc msvcrt.lib" in the link phase.

* glib.def: Include new functions, drop removed ones.

* glib.h: Add comments about main loop and polling on Win32. (In
general, it's only for the GIMP's use.) Add Win32 IO Channel
functions. Remove the obsoleted old IO Channel stuff (which was
in #if 0 already).

* giowin32.c: New file.

* gmain.c: Include config.h, conditionalize <sys/time.h>
  inclusion.  Add g_poll implementation for Win32 (only for the
  GIMP's needs for now, it's hard or even impossible to be as clean
  and generic as on Unix). Implement g_get_current_time on Win32. If
  threads aren't supported, don't try to wake up main thread's
  loop. On Win32, use a semaphore and not a pipe to wake up the main
  loop.

* gmessages.c: On Win32, allocate a console window if the standard
output handle is invalid before writing to stdout, and reopen stdout
to that console window.

* giochannel.c: Conditionalize unistd.h inclusion. Some indentation
cleanup.

* gstrfuncs.c: Include <signal.h>.

* gutils.c: On Win32, also check the HOMEDRIVE and HOMEPATH
environment variables.

* gmodule-dl.c gmodule-dld.c: In
  _g_module_build_path, don't add the "lib" prefix and
  ".so" or ".sl" suffix if already there.

* gmodule-win32.c: Likewise for the ".dll" suffix.

* gthread-posix.c: Conditionalize <sys/time.h> inclusion.

34 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
README.win32
config.h.win32
giochannel.c
giowin32.c [new file with mode: 0644]
glib.def
glib.h
glib/giochannel.c
glib/giowin32.c [new file with mode: 0644]
glib/glib.def
glib/glib.h
glib/gmain.c
glib/gmessages.c
glib/gstrfuncs.c
glib/gutils.c
glibconfig.h.win32
gmain.c
gmessages.c
gmodule/ChangeLog
gmodule/gmodule-dl.c
gmodule/gmodule-dld.c
gmodule/gmodule-win32.c
gstrfuncs.c
gthread/ChangeLog
gthread/gthread-posix.c
gutils.c
makefile.msc

index df7dc128f3fb2d4e10ceb5a3ef73660b4275ca8a..88295e56cee7b704d32a87da9a64b8514dd76fcf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+1999-01-16  Tor Lillqvist  <tml@iki.fi>
+
+       * Merge in current Win32 version:
+
+       * README.win32: More text.
+
+       * config.h.win32 glibconfig.h.win32: Update to match the
+       corresponding generated files on Unix.
+
+       * makefile.msc: Update with new source files, and gthread
+       library. Use the compiler flag -MD instead of using -D_DLL and
+       /nodefaultlib:libc msvcrt.lib in the link phase.
+
+       * glib.def: Update to include new functions, drop removed ones.
+
+       * glib.h: Add comments about main loop and polling on Win32. (In
+       general, it's only for the GIMP's use.) Add Win32 IO Channel
+       functions. Remove the obsoleted old IO Channel stuff (which was
+       in #if 0 already).
+
+       * giowin32.c: New file.
+
+       * gmain.c: Include config.h, conditionalize <sys/time.h>
+       inclusion.  Add g_poll implementation for Win32 (only for the
+       GIMP's needs for now, it's hard or even impossible to be as clean
+       and generic as on Unix). Implement g_get_current_time on Win32. If
+       threads aren't supported, don't try to wake up main thread's
+       loop. On Win32, use a semaphore and not a pipe to wake up the main
+       loop.
+
+       * gmessages.c: On Win32, allocate a console window if the standard
+       output handle is invalid before writing to stdout, and reopen stdout
+       to that console window.
+
+       * giochannel.c: Conditionalize unistd.h inclusion. Some indentation
+       cleanup.
+
+       * gstrfuncs.c: Include <signal.h>.
+
+       * gutils.c: On Win32, also check the HOMEDRIVE and HOMEPATH
+       environment variables.
+
 Sun Jan 17 01:06:38 1999 Timur Bakeyev <mc@bat.ru>
 
        * configure.in: Add support for FreeBSD 2.2.x macro _THREAD_SAFE.
index df7dc128f3fb2d4e10ceb5a3ef73660b4275ca8a..88295e56cee7b704d32a87da9a64b8514dd76fcf 100644 (file)
@@ -1,3 +1,45 @@
+1999-01-16  Tor Lillqvist  <tml@iki.fi>
+
+       * Merge in current Win32 version:
+
+       * README.win32: More text.
+
+       * config.h.win32 glibconfig.h.win32: Update to match the
+       corresponding generated files on Unix.
+
+       * makefile.msc: Update with new source files, and gthread
+       library. Use the compiler flag -MD instead of using -D_DLL and
+       /nodefaultlib:libc msvcrt.lib in the link phase.
+
+       * glib.def: Update to include new functions, drop removed ones.
+
+       * glib.h: Add comments about main loop and polling on Win32. (In
+       general, it's only for the GIMP's use.) Add Win32 IO Channel
+       functions. Remove the obsoleted old IO Channel stuff (which was
+       in #if 0 already).
+
+       * giowin32.c: New file.
+
+       * gmain.c: Include config.h, conditionalize <sys/time.h>
+       inclusion.  Add g_poll implementation for Win32 (only for the
+       GIMP's needs for now, it's hard or even impossible to be as clean
+       and generic as on Unix). Implement g_get_current_time on Win32. If
+       threads aren't supported, don't try to wake up main thread's
+       loop. On Win32, use a semaphore and not a pipe to wake up the main
+       loop.
+
+       * gmessages.c: On Win32, allocate a console window if the standard
+       output handle is invalid before writing to stdout, and reopen stdout
+       to that console window.
+
+       * giochannel.c: Conditionalize unistd.h inclusion. Some indentation
+       cleanup.
+
+       * gstrfuncs.c: Include <signal.h>.
+
+       * gutils.c: On Win32, also check the HOMEDRIVE and HOMEPATH
+       environment variables.
+
 Sun Jan 17 01:06:38 1999 Timur Bakeyev <mc@bat.ru>
 
        * configure.in: Add support for FreeBSD 2.2.x macro _THREAD_SAFE.
index df7dc128f3fb2d4e10ceb5a3ef73660b4275ca8a..88295e56cee7b704d32a87da9a64b8514dd76fcf 100644 (file)
@@ -1,3 +1,45 @@
+1999-01-16  Tor Lillqvist  <tml@iki.fi>
+
+       * Merge in current Win32 version:
+
+       * README.win32: More text.
+
+       * config.h.win32 glibconfig.h.win32: Update to match the
+       corresponding generated files on Unix.
+
+       * makefile.msc: Update with new source files, and gthread
+       library. Use the compiler flag -MD instead of using -D_DLL and
+       /nodefaultlib:libc msvcrt.lib in the link phase.
+
+       * glib.def: Update to include new functions, drop removed ones.
+
+       * glib.h: Add comments about main loop and polling on Win32. (In
+       general, it's only for the GIMP's use.) Add Win32 IO Channel
+       functions. Remove the obsoleted old IO Channel stuff (which was
+       in #if 0 already).
+
+       * giowin32.c: New file.
+
+       * gmain.c: Include config.h, conditionalize <sys/time.h>
+       inclusion.  Add g_poll implementation for Win32 (only for the
+       GIMP's needs for now, it's hard or even impossible to be as clean
+       and generic as on Unix). Implement g_get_current_time on Win32. If
+       threads aren't supported, don't try to wake up main thread's
+       loop. On Win32, use a semaphore and not a pipe to wake up the main
+       loop.
+
+       * gmessages.c: On Win32, allocate a console window if the standard
+       output handle is invalid before writing to stdout, and reopen stdout
+       to that console window.
+
+       * giochannel.c: Conditionalize unistd.h inclusion. Some indentation
+       cleanup.
+
+       * gstrfuncs.c: Include <signal.h>.
+
+       * gutils.c: On Win32, also check the HOMEDRIVE and HOMEPATH
+       environment variables.
+
 Sun Jan 17 01:06:38 1999 Timur Bakeyev <mc@bat.ru>
 
        * configure.in: Add support for FreeBSD 2.2.x macro _THREAD_SAFE.
index df7dc128f3fb2d4e10ceb5a3ef73660b4275ca8a..88295e56cee7b704d32a87da9a64b8514dd76fcf 100644 (file)
@@ -1,3 +1,45 @@
+1999-01-16  Tor Lillqvist  <tml@iki.fi>
+
+       * Merge in current Win32 version:
+
+       * README.win32: More text.
+
+       * config.h.win32 glibconfig.h.win32: Update to match the
+       corresponding generated files on Unix.
+
+       * makefile.msc: Update with new source files, and gthread
+       library. Use the compiler flag -MD instead of using -D_DLL and
+       /nodefaultlib:libc msvcrt.lib in the link phase.
+
+       * glib.def: Update to include new functions, drop removed ones.
+
+       * glib.h: Add comments about main loop and polling on Win32. (In
+       general, it's only for the GIMP's use.) Add Win32 IO Channel
+       functions. Remove the obsoleted old IO Channel stuff (which was
+       in #if 0 already).
+
+       * giowin32.c: New file.
+
+       * gmain.c: Include config.h, conditionalize <sys/time.h>
+       inclusion.  Add g_poll implementation for Win32 (only for the
+       GIMP's needs for now, it's hard or even impossible to be as clean
+       and generic as on Unix). Implement g_get_current_time on Win32. If
+       threads aren't supported, don't try to wake up main thread's
+       loop. On Win32, use a semaphore and not a pipe to wake up the main
+       loop.
+
+       * gmessages.c: On Win32, allocate a console window if the standard
+       output handle is invalid before writing to stdout, and reopen stdout
+       to that console window.
+
+       * giochannel.c: Conditionalize unistd.h inclusion. Some indentation
+       cleanup.
+
+       * gstrfuncs.c: Include <signal.h>.
+
+       * gutils.c: On Win32, also check the HOMEDRIVE and HOMEPATH
+       environment variables.
+
 Sun Jan 17 01:06:38 1999 Timur Bakeyev <mc@bat.ru>
 
        * configure.in: Add support for FreeBSD 2.2.x macro _THREAD_SAFE.
index df7dc128f3fb2d4e10ceb5a3ef73660b4275ca8a..88295e56cee7b704d32a87da9a64b8514dd76fcf 100644 (file)
@@ -1,3 +1,45 @@
+1999-01-16  Tor Lillqvist  <tml@iki.fi>
+
+       * Merge in current Win32 version:
+
+       * README.win32: More text.
+
+       * config.h.win32 glibconfig.h.win32: Update to match the
+       corresponding generated files on Unix.
+
+       * makefile.msc: Update with new source files, and gthread
+       library. Use the compiler flag -MD instead of using -D_DLL and
+       /nodefaultlib:libc msvcrt.lib in the link phase.
+
+       * glib.def: Update to include new functions, drop removed ones.
+
+       * glib.h: Add comments about main loop and polling on Win32. (In
+       general, it's only for the GIMP's use.) Add Win32 IO Channel
+       functions. Remove the obsoleted old IO Channel stuff (which was
+       in #if 0 already).
+
+       * giowin32.c: New file.
+
+       * gmain.c: Include config.h, conditionalize <sys/time.h>
+       inclusion.  Add g_poll implementation for Win32 (only for the
+       GIMP's needs for now, it's hard or even impossible to be as clean
+       and generic as on Unix). Implement g_get_current_time on Win32. If
+       threads aren't supported, don't try to wake up main thread's
+       loop. On Win32, use a semaphore and not a pipe to wake up the main
+       loop.
+
+       * gmessages.c: On Win32, allocate a console window if the standard
+       output handle is invalid before writing to stdout, and reopen stdout
+       to that console window.
+
+       * giochannel.c: Conditionalize unistd.h inclusion. Some indentation
+       cleanup.
+
+       * gstrfuncs.c: Include <signal.h>.
+
+       * gutils.c: On Win32, also check the HOMEDRIVE and HOMEPATH
+       environment variables.
+
 Sun Jan 17 01:06:38 1999 Timur Bakeyev <mc@bat.ru>
 
        * configure.in: Add support for FreeBSD 2.2.x macro _THREAD_SAFE.
index df7dc128f3fb2d4e10ceb5a3ef73660b4275ca8a..88295e56cee7b704d32a87da9a64b8514dd76fcf 100644 (file)
@@ -1,3 +1,45 @@
+1999-01-16  Tor Lillqvist  <tml@iki.fi>
+
+       * Merge in current Win32 version:
+
+       * README.win32: More text.
+
+       * config.h.win32 glibconfig.h.win32: Update to match the
+       corresponding generated files on Unix.
+
+       * makefile.msc: Update with new source files, and gthread
+       library. Use the compiler flag -MD instead of using -D_DLL and
+       /nodefaultlib:libc msvcrt.lib in the link phase.
+
+       * glib.def: Update to include new functions, drop removed ones.
+
+       * glib.h: Add comments about main loop and polling on Win32. (In
+       general, it's only for the GIMP's use.) Add Win32 IO Channel
+       functions. Remove the obsoleted old IO Channel stuff (which was
+       in #if 0 already).
+
+       * giowin32.c: New file.
+
+       * gmain.c: Include config.h, conditionalize <sys/time.h>
+       inclusion.  Add g_poll implementation for Win32 (only for the
+       GIMP's needs for now, it's hard or even impossible to be as clean
+       and generic as on Unix). Implement g_get_current_time on Win32. If
+       threads aren't supported, don't try to wake up main thread's
+       loop. On Win32, use a semaphore and not a pipe to wake up the main
+       loop.
+
+       * gmessages.c: On Win32, allocate a console window if the standard
+       output handle is invalid before writing to stdout, and reopen stdout
+       to that console window.
+
+       * giochannel.c: Conditionalize unistd.h inclusion. Some indentation
+       cleanup.
+
+       * gstrfuncs.c: Include <signal.h>.
+
+       * gutils.c: On Win32, also check the HOMEDRIVE and HOMEPATH
+       environment variables.
+
 Sun Jan 17 01:06:38 1999 Timur Bakeyev <mc@bat.ru>
 
        * configure.in: Add support for FreeBSD 2.2.x macro _THREAD_SAFE.
index df7dc128f3fb2d4e10ceb5a3ef73660b4275ca8a..88295e56cee7b704d32a87da9a64b8514dd76fcf 100644 (file)
@@ -1,3 +1,45 @@
+1999-01-16  Tor Lillqvist  <tml@iki.fi>
+
+       * Merge in current Win32 version:
+
+       * README.win32: More text.
+
+       * config.h.win32 glibconfig.h.win32: Update to match the
+       corresponding generated files on Unix.
+
+       * makefile.msc: Update with new source files, and gthread
+       library. Use the compiler flag -MD instead of using -D_DLL and
+       /nodefaultlib:libc msvcrt.lib in the link phase.
+
+       * glib.def: Update to include new functions, drop removed ones.
+
+       * glib.h: Add comments about main loop and polling on Win32. (In
+       general, it's only for the GIMP's use.) Add Win32 IO Channel
+       functions. Remove the obsoleted old IO Channel stuff (which was
+       in #if 0 already).
+
+       * giowin32.c: New file.
+
+       * gmain.c: Include config.h, conditionalize <sys/time.h>
+       inclusion.  Add g_poll implementation for Win32 (only for the
+       GIMP's needs for now, it's hard or even impossible to be as clean
+       and generic as on Unix). Implement g_get_current_time on Win32. If
+       threads aren't supported, don't try to wake up main thread's
+       loop. On Win32, use a semaphore and not a pipe to wake up the main
+       loop.
+
+       * gmessages.c: On Win32, allocate a console window if the standard
+       output handle is invalid before writing to stdout, and reopen stdout
+       to that console window.
+
+       * giochannel.c: Conditionalize unistd.h inclusion. Some indentation
+       cleanup.
+
+       * gstrfuncs.c: Include <signal.h>.
+
+       * gutils.c: On Win32, also check the HOMEDRIVE and HOMEPATH
+       environment variables.
+
 Sun Jan 17 01:06:38 1999 Timur Bakeyev <mc@bat.ru>
 
        * configure.in: Add support for FreeBSD 2.2.x macro _THREAD_SAFE.
index df7dc128f3fb2d4e10ceb5a3ef73660b4275ca8a..88295e56cee7b704d32a87da9a64b8514dd76fcf 100644 (file)
@@ -1,3 +1,45 @@
+1999-01-16  Tor Lillqvist  <tml@iki.fi>
+
+       * Merge in current Win32 version:
+
+       * README.win32: More text.
+
+       * config.h.win32 glibconfig.h.win32: Update to match the
+       corresponding generated files on Unix.
+
+       * makefile.msc: Update with new source files, and gthread
+       library. Use the compiler flag -MD instead of using -D_DLL and
+       /nodefaultlib:libc msvcrt.lib in the link phase.
+
+       * glib.def: Update to include new functions, drop removed ones.
+
+       * glib.h: Add comments about main loop and polling on Win32. (In
+       general, it's only for the GIMP's use.) Add Win32 IO Channel
+       functions. Remove the obsoleted old IO Channel stuff (which was
+       in #if 0 already).
+
+       * giowin32.c: New file.
+
+       * gmain.c: Include config.h, conditionalize <sys/time.h>
+       inclusion.  Add g_poll implementation for Win32 (only for the
+       GIMP's needs for now, it's hard or even impossible to be as clean
+       and generic as on Unix). Implement g_get_current_time on Win32. If
+       threads aren't supported, don't try to wake up main thread's
+       loop. On Win32, use a semaphore and not a pipe to wake up the main
+       loop.
+
+       * gmessages.c: On Win32, allocate a console window if the standard
+       output handle is invalid before writing to stdout, and reopen stdout
+       to that console window.
+
+       * giochannel.c: Conditionalize unistd.h inclusion. Some indentation
+       cleanup.
+
+       * gstrfuncs.c: Include <signal.h>.
+
+       * gutils.c: On Win32, also check the HOMEDRIVE and HOMEPATH
+       environment variables.
+
 Sun Jan 17 01:06:38 1999 Timur Bakeyev <mc@bat.ru>
 
        * configure.in: Add support for FreeBSD 2.2.x macro _THREAD_SAFE.
index e819d9364c121e4512133c5d3a09de855a9e2e99..e2f179a529164eb55b88bc1b643f3b09c471dd9a 100644 (file)
@@ -1,7 +1,16 @@
-For more information about the Windows port, see
-http://www.iki.fi/tml/gimp/win32/ .
+For more information about the port or GLib, GTk+ and the GIMP to
+native Windows, see http://www.iki.fi/tml/gimp/win32/ . ("Native"
+means that we use the Win32 API only, and not any POSIX emulation
+layer except that provided by the Microsoft runtime C library, and the
+pthreads emulation library from Cygnus.)
 
-As for now, only Microsoft C is really supported. Before compiling,
-check the BIN definition in makefile.msc. Compile with `nmake -f
-makefile.msc`. Install with `nmake -f makefile.msc install`. Gnu-Win32
-with egcs and maybe LCC-Win32 support will be added later.
+As for now, only the Microsoft compiler and tools are really
+supported. Before compiling, check the BIN definition in
+makefile.msc. Compile with `nmake -f makefile.msc`. Install with
+`nmake -f makefile.msc install`. Cygwin (without cygwin runtime,
+i.e. "mingw32") and maybe LCC-Win32 support will be added later.  Note
+that when using the cygwin compiler and other tools *with* the cygwin
+runtime the normal Unix configuration method should work.
+
+The thread support uses the pthreads package from Cygnus, which isn't
+ready yet, and thus really should not be relied upon.
index 159a2d195ab3749ea5248b33f2d21e57eee15341..6fc30a5e37daa2eae2ff18d6be464242fcf5c36d 100644 (file)
 /* #undef ENABLE_MEM_PROFILE */
 
 #define G_COMPILED_WITH_DEBUGGING "minimum"
+
 /* #undef HAVE_BROKEN_WCTYPE */
 /* #undef HAVE_DOPRNT */
 #define HAVE_FLOAT_H 1
 #define HAVE_LIMITS_H 1
+/* #undef HAVE_LOCALTIME_R */
 /* #undef HAVE_LONG_DOUBLE */
+/* #undef HAVE_POLL */
 /* #undef HAVE_PWD_H */
 /* #undef HAVE_SYS_PARAM_H */
+/* #undef HAVE_SYS_POLL_H */
 /* #undef HAVE_SYS_SELECT_H */
 /* #undef HAVE_SYS_TIME_H */
 /* #undef HAVE_SYS_TIMES_H */
 
 #define GLIB_MAJOR_VERSION 1
 #define GLIB_MINOR_VERSION 1
-#define GLIB_MICRO_VERSION 4
+#define GLIB_MICRO_VERSION 12
 #define GLIB_INTERFACE_AGE 0
 #define GLIB_BINARY_AGE 0
 
+#define G_THREAD_SOURCE "gthread-posix.c"
+#define G_THREADS_IMPL_POSIX
+
 /* The number of bytes in a char.  */
 #define SIZEOF_CHAR 1
 
index a9bf10a8aa1ea7258559c17261373c135b667e2c..7c05e3c8162966691133a8d75f3ff20a401ae5d0 100644 (file)
  * MT safe
  */
 
+#include "config.h"
+
 #include "glib.h"
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 
 void
 g_io_channel_init (GIOChannel *channel)
@@ -94,7 +98,7 @@ g_io_channel_close (GIOChannel *channel)
 }
 
 guint 
-g_io_add_watch_full (GIOChannel      *channel,
+g_io_add_watch_full (GIOChannel    *channel,
                     gint           priority,
                     GIOCondition   condition,
                     GIOFunc        func,
@@ -108,7 +112,7 @@ g_io_add_watch_full (GIOChannel      *channel,
 }
 
 guint 
-g_io_add_watch (GIOChannel      *channel,
+g_io_add_watch (GIOChannel    *channel,
                GIOCondition   condition,
                GIOFunc        func,
                gpointer       user_data)
diff --git a/giowin32.c b/giowin32.c
new file mode 100644 (file)
index 0000000..16387d4
--- /dev/null
@@ -0,0 +1,1027 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * giowin32.c: IO Channels for Win32.
+ * Copyright 1998 Owen Taylor and Tor Lillqvist
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "glib.h"
+#include <windows.h>
+#include <winsock.h>           /* Not everybody has winsock2 */
+#include <fcntl.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <stdio.h>
+
+typedef struct _GIOWin32Channel GIOWin32Channel;
+typedef struct _GIOWin32Watch GIOWin32Watch;
+
+guint g_pipe_readable_msg;
+
+typedef enum {
+  G_IO_WINDOWS_MESSAGES,       /* Windows messages */
+  G_IO_FILE_DESC,              /* Unix-like file descriptors from _open*/
+  G_IO_PIPE,                   /* pipe, with windows messages for signalling */
+  G_IO_STREAM_SOCKET           /* Stream sockets */
+} GIOWin32ChannelType;
+
+struct _GIOWin32Channel {
+  GIOChannel channel;
+  gint fd;                     /* Either a Unix-like file handle as provided
+                                * by the Microsoft C runtime, or a SOCKET
+                                * as provided by WinSock.
+                                */
+  GIOWin32ChannelType type;
+
+  /* This is used by G_IO_WINDOWS_MESSAGES channels */
+  HWND hwnd;                   /* handle of window, or NULL */
+
+  /* This is used by G_IO_PIPE channels */
+  guint peer;                  /* thread id of reader */
+  guint peer_fd;               /* fd in the reader */
+  guint offset;                        /* counter of accumulated bytes */
+  guint need_wakeups;          /* in output channels whether the
+                                * reader needs wakeups
+                                */
+};
+
+struct _GIOWin32Watch {
+  GPollFD       pollfd;
+  GIOChannel   *channel;
+  GIOCondition  condition;
+  GIOFunc       callback;
+};
+
+static gboolean g_io_win32_msg_prepare  (gpointer  source_data, 
+                                        GTimeVal *current_time,
+                                        gint     *timeout);
+static gboolean g_io_win32_msg_check    (gpointer  source_data,
+                                        GTimeVal *current_time);
+static gboolean g_io_win32_msg_dispatch (gpointer  source_data,
+                                        GTimeVal *current_time,
+                                        gpointer  user_data);
+
+static gboolean g_io_win32_fd_prepare  (gpointer  source_data, 
+                                       GTimeVal *current_time,
+                                       gint     *timeout);
+static gboolean g_io_win32_fd_check    (gpointer  source_data,
+                                       GTimeVal *current_time);
+static gboolean g_io_win32_fd_dispatch (gpointer  source_data,
+                                       GTimeVal *current_time,
+                                       gpointer  user_data);
+
+static gboolean g_io_win32_pipe_prepare  (gpointer  source_data, 
+                                         GTimeVal *current_time,
+                                         gint     *timeout);
+static gboolean g_io_win32_pipe_check    (gpointer  source_data,
+                                         GTimeVal *current_time);
+static gboolean g_io_win32_pipe_dispatch (gpointer  source_data,
+                                         GTimeVal *current_time,
+                                         gpointer  user_data);
+static void g_io_win32_pipe_destroy     (gpointer source_data);
+
+static gboolean g_io_win32_sock_prepare  (gpointer  source_data, 
+                                         GTimeVal *current_time,
+                                         gint     *timeout);
+static gboolean g_io_win32_sock_check    (gpointer  source_data,
+                                         GTimeVal *current_time);
+static gboolean g_io_win32_sock_dispatch (gpointer  source_data,
+                                         GTimeVal *current_time,
+                                         gpointer  user_data);
+
+static void g_io_win32_destroy (gpointer source_data);
+
+static GIOError g_io_win32_msg_read (GIOChannel *channel, 
+                                    gchar      *buf, 
+                                    guint       count,
+                                    guint      *bytes_written);
+
+static GIOError g_io_win32_msg_write(GIOChannel *channel, 
+                                    gchar      *buf, 
+                                    guint       count,
+                                    guint      *bytes_written);
+static GIOError g_io_win32_msg_seek (GIOChannel *channel,
+                                    gint        offset, 
+                                    GSeekType   type);
+static void g_io_win32_msg_close    (GIOChannel *channel);
+static guint g_io_win32_msg_add_watch (GIOChannel      *channel,
+                                      gint             priority,
+                                      GIOCondition     condition,
+                                      GIOFunc          func,
+                                      gpointer         user_data,
+                                      GDestroyNotify   notify);
+
+static GIOError g_io_win32_fd_read (GIOChannel *channel, 
+                                   gchar      *buf, 
+                                   guint       count,
+                                   guint      *bytes_written);
+static GIOError g_io_win32_fd_write(GIOChannel *channel, 
+                                   gchar      *buf, 
+                                   guint       count,
+                                   guint      *bytes_written);
+static GIOError g_io_win32_fd_seek (GIOChannel *channel,
+                                   gint        offset, 
+                                   GSeekType   type);
+static void g_io_win32_fd_close (GIOChannel *channel);
+
+static void g_io_win32_free (GIOChannel *channel);
+
+static guint g_io_win32_fd_add_watch (GIOChannel      *channel,
+                                     gint             priority,
+                                     GIOCondition     condition,
+                                     GIOFunc          func,
+                                     gpointer         user_data,
+                                     GDestroyNotify   notify);
+
+static GIOError g_io_win32_no_seek (GIOChannel *channel,
+                                   gint        offset, 
+                                   GSeekType   type);
+
+static GIOError g_io_win32_pipe_read (GIOChannel *channel, 
+                                     gchar      *buf, 
+                                     guint       count,
+                                     guint      *bytes_written);
+static GIOError g_io_win32_pipe_write (GIOChannel *channel, 
+                                      gchar      *buf, 
+                                      guint       count,
+                                      guint      *bytes_written);
+static void g_io_win32_pipe_close    (GIOChannel *channel);
+static guint g_io_win32_pipe_add_watch (GIOChannel      *channel,
+                                       gint             priority,
+                                       GIOCondition     condition,
+                                       GIOFunc          func,
+                                       gpointer         user_data,
+                                       GDestroyNotify   notify);
+static void g_io_win32_pipe_free (GIOChannel *channel);
+
+static GIOError g_io_win32_sock_read (GIOChannel *channel, 
+                                     gchar      *buf, 
+                                     guint       count,
+                                     guint      *bytes_written);
+static GIOError g_io_win32_sock_write(GIOChannel *channel, 
+                                     gchar      *buf, 
+                                     guint       count,
+                                     guint      *bytes_written);
+static void g_io_win32_sock_close    (GIOChannel *channel);
+static guint g_io_win32_sock_add_watch (GIOChannel      *channel,
+                                       gint             priority,
+                                       GIOCondition     condition,
+                                       GIOFunc          func,
+                                       gpointer         user_data,
+                                       GDestroyNotify   notify);
+
+GSourceFuncs win32_watch_msg_funcs = {
+  g_io_win32_msg_prepare,
+  g_io_win32_msg_check,
+  g_io_win32_msg_dispatch,
+  g_io_win32_destroy
+};
+
+GSourceFuncs win32_watch_fd_funcs = {
+  g_io_win32_fd_prepare,
+  g_io_win32_fd_check,
+  g_io_win32_fd_dispatch,
+  g_io_win32_destroy
+};
+
+GSourceFuncs win32_watch_pipe_funcs = {
+  g_io_win32_pipe_prepare,
+  g_io_win32_pipe_check,
+  g_io_win32_pipe_dispatch,
+  g_io_win32_pipe_destroy
+};
+
+GSourceFuncs win32_watch_sock_funcs = {
+  g_io_win32_sock_prepare,
+  g_io_win32_sock_check,
+  g_io_win32_sock_dispatch,
+  g_io_win32_destroy
+};
+
+GIOFuncs win32_channel_msg_funcs = {
+  g_io_win32_msg_read,
+  g_io_win32_msg_write,
+  g_io_win32_no_seek,
+  g_io_win32_msg_close,
+  g_io_win32_msg_add_watch,
+  g_io_win32_free
+};
+
+GIOFuncs win32_channel_fd_funcs = {
+  g_io_win32_fd_read,
+  g_io_win32_fd_write,
+  g_io_win32_fd_seek,
+  g_io_win32_fd_close,
+  g_io_win32_fd_add_watch,
+  g_io_win32_free
+};
+
+GIOFuncs win32_channel_pipe_funcs = {
+  g_io_win32_pipe_read,
+  g_io_win32_pipe_write,
+  g_io_win32_no_seek,
+  g_io_win32_pipe_close,
+  g_io_win32_pipe_add_watch,
+  g_io_win32_pipe_free
+};
+
+GIOFuncs win32_channel_sock_funcs = {
+  g_io_win32_sock_read,
+  g_io_win32_sock_write,
+  g_io_win32_no_seek,
+  g_io_win32_sock_close,
+  g_io_win32_sock_add_watch,
+  g_io_win32_free
+};
+
+#define N_WATCHED_PIPES 4
+
+static struct {
+  gint fd;
+  GIOWin32Watch *watch;
+  GIOWin32Channel *channel;
+  gpointer user_data;
+} watched_pipes[N_WATCHED_PIPES];
+
+static gint n_watched_pipes = 0;
+
+static gboolean
+g_io_win32_msg_prepare  (gpointer source_data, 
+                        GTimeVal *current_time,
+                        gint    *timeout)
+{
+  GIOWin32Watch *data = source_data;
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
+  MSG msg;
+
+  *timeout = -1;
+
+  return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
+}
+
+static gboolean 
+g_io_win32_msg_check    (gpointer source_data,
+                        GTimeVal *current_time)
+{
+  GIOWin32Watch *data = source_data;
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
+  MSG msg;
+
+  return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
+}
+
+static gboolean
+g_io_win32_msg_dispatch (gpointer source_data, 
+                        GTimeVal *current_time,
+                        gpointer user_data)
+
+{
+  GIOWin32Watch *data = source_data;
+
+  return (*data->callback)(data->channel,
+                          data->pollfd.revents & data->condition,
+                          user_data);
+}
+
+static void
+g_io_win32_destroy (gpointer source_data)
+{
+  GIOWin32Watch *data = source_data;
+
+  g_main_remove_poll (&data->pollfd);
+  g_io_channel_unref (data->channel);
+  g_free (data);
+}
+
+static gboolean
+g_io_win32_fd_prepare  (gpointer source_data, 
+                       GTimeVal *current_time,
+                       gint    *timeout)
+{
+  *timeout = -1;
+
+  return FALSE;
+}
+
+static gboolean 
+g_io_win32_fd_check    (gpointer source_data,
+                       GTimeVal *current_time)
+{
+  GIOWin32Watch *data = source_data;
+
+  return (data->pollfd.revents & data->condition);
+}
+
+static gboolean
+g_io_win32_fd_dispatch (gpointer source_data, 
+                       GTimeVal *current_time,
+                       gpointer user_data)
+
+{
+  GIOWin32Watch *data = source_data;
+
+  return (*data->callback)(data->channel,
+                          data->pollfd.revents & data->condition,
+                          user_data);
+}
+
+static GIOError
+g_io_win32_msg_read (GIOChannel *channel, 
+                    gchar     *buf, 
+                    guint      count,
+                    guint     *bytes_read)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  MSG msg;                     /* In case of alignment problems */
+
+  if (count < sizeof (MSG))
+    return G_IO_ERROR_INVAL;
+  
+  if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
+    return G_IO_ERROR_AGAIN;
+
+  memmove (buf, &msg, sizeof (MSG));
+  *bytes_read = sizeof (MSG);
+  return G_IO_ERROR_NONE;
+}
+                      
+static GIOError 
+g_io_win32_msg_write(GIOChannel *channel, 
+                    gchar     *buf, 
+                    guint      count,
+                    guint     *bytes_written)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  MSG msg;
+  gint result;
+
+  if (count != sizeof (MSG))
+    return G_IO_ERROR_INVAL;
+
+  /* In case of alignment problems */
+  memmove (&msg, buf, sizeof (MSG));
+  if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
+    return G_IO_ERROR_UNKNOWN;
+
+  *bytes_written = sizeof (MSG);
+  return G_IO_ERROR_NONE; 
+}
+
+static GIOError 
+g_io_win32_no_seek (GIOChannel *channel,
+                   gint      offset, 
+                   GSeekType type)
+{
+  g_warning ("g_io_win32_no_seek: unseekable IO channel type");
+  return G_IO_ERROR_UNKNOWN;
+}
+
+
+static void 
+g_io_win32_msg_close (GIOChannel *channel)
+{
+  /* Nothing to be done. Or should we set hwnd to some invalid value? */
+}
+
+static void 
+g_io_win32_free (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  g_free (win32_channel);
+}
+
+static guint 
+g_io_win32_msg_add_watch (GIOChannel    *channel,
+                         gint           priority,
+                         GIOCondition   condition,
+                         GIOFunc        func,
+                         gpointer       user_data,
+                         GDestroyNotify notify)
+{
+  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  
+  watch->channel = channel;
+  g_io_channel_ref (channel);
+
+  watch->callback = func;
+  watch->condition = condition;
+
+  watch->pollfd.fd = G_WIN32_MSG_HANDLE;
+  watch->pollfd.events = condition;
+
+  g_main_add_poll (&watch->pollfd, priority);
+
+  return g_source_add (priority, TRUE, &win32_watch_msg_funcs,
+                      watch, user_data, notify);
+}
+
+static gboolean
+g_io_win32_pipe_prepare  (gpointer source_data, 
+                         GTimeVal *current_time,
+                         gint    *timeout)
+{
+  *timeout = -1;
+
+  return FALSE;
+}
+
+static gboolean 
+g_io_win32_pipe_check    (gpointer source_data,
+                         GTimeVal *current_time)
+{
+  GIOWin32Watch *data = source_data;
+  return FALSE;
+}
+
+static gboolean
+g_io_win32_pipe_dispatch (gpointer source_data, 
+                         GTimeVal *current_time,
+                         gpointer user_data)
+
+{
+  GIOWin32Watch *data = source_data;
+
+  return (*data->callback)(data->channel,
+                          data->pollfd.revents & data->condition,
+                          user_data);
+}
+
+static void
+g_io_win32_pipe_destroy (gpointer source_data)
+{
+  GIOWin32Watch *data = source_data;
+
+  g_io_channel_unref (data->channel);
+  g_free (data);
+}
+
+static gboolean
+g_io_win32_sock_prepare  (gpointer source_data, 
+                       GTimeVal *current_time,
+                       gint    *timeout)
+{
+  *timeout = -1;
+
+  return FALSE;
+}
+
+static gboolean 
+g_io_win32_sock_check    (gpointer source_data,
+                       GTimeVal *current_time)
+{
+  GIOWin32Watch *data = source_data;
+
+  return (data->pollfd.revents & data->condition);
+}
+
+static gboolean
+g_io_win32_sock_dispatch (gpointer source_data, 
+                       GTimeVal *current_time,
+                       gpointer user_data)
+
+{
+  GIOWin32Watch *data = source_data;
+
+  return (*data->callback)(data->channel,
+                          data->pollfd.revents & data->condition,
+                          user_data);
+}
+
+static GIOError
+g_io_win32_fd_read (GIOChannel *channel, 
+                   gchar     *buf, 
+                   guint      count,
+                   guint     *bytes_read)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint result;
+
+  result = read (win32_channel->fd, buf, count);
+  if (result < 0)
+    {
+      *bytes_read = 0;
+      switch (errno)
+       {
+       case EINVAL:
+         return G_IO_ERROR_INVAL;
+       case EAGAIN:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      *bytes_read = result;
+      return G_IO_ERROR_NONE;
+    }
+}
+                      
+static GIOError 
+g_io_win32_fd_write(GIOChannel *channel, 
+                   gchar     *buf, 
+                   guint      count,
+                   guint     *bytes_written)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint result;
+
+  result = write (win32_channel->fd, buf, count);
+      
+  if (result < 0)
+    {
+      *bytes_written = 0;
+      switch (errno)
+       {
+       case EINVAL:
+         return G_IO_ERROR_INVAL;
+       case EAGAIN:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      *bytes_written = result;
+      return G_IO_ERROR_NONE;
+    }
+}
+
+static GIOError 
+g_io_win32_fd_seek (GIOChannel *channel,
+                   gint      offset, 
+                   GSeekType type)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  int whence;
+  off_t result;
+
+  switch (type)
+    {
+    case G_SEEK_SET:
+      whence = SEEK_SET;
+      break;
+    case G_SEEK_CUR:
+      whence = SEEK_CUR;
+      break;
+    case G_SEEK_END:
+      whence = SEEK_END;
+      break;
+    default:
+      g_warning ("g_io_win32_fd_seek: unknown seek type");
+      return G_IO_ERROR_UNKNOWN;
+    }
+  
+  result = lseek (win32_channel->fd, offset, whence);
+  
+  if (result < 0)
+    {
+      switch (errno)
+       {
+       case EINVAL:
+         return G_IO_ERROR_INVAL;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    return G_IO_ERROR_NONE;
+}
+
+static void 
+g_io_win32_fd_close (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  close (win32_channel->fd);
+  return;
+}
+
+static guint 
+g_io_win32_fd_add_watch (GIOChannel    *channel,
+                        gint           priority,
+                        GIOCondition   condition,
+                        GIOFunc        func,
+                        gpointer       user_data,
+                        GDestroyNotify notify)
+{
+  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  
+  watch->channel = channel;
+  g_io_channel_ref (channel);
+
+  watch->callback = func;
+  watch->condition = condition;
+
+  /* This probably does not work, except for CONIN$. */
+  watch->pollfd.fd = _get_osfhandle (win32_channel->fd);
+  watch->pollfd.events = condition;
+
+  g_main_add_poll (&watch->pollfd, priority);
+
+  return g_source_add (priority, TRUE, &win32_watch_fd_funcs,
+                      watch, user_data, notify);
+}
+
+static GIOError
+g_io_win32_pipe_read (GIOChannel *channel, 
+                     gchar     *buf, 
+                     guint      count,
+                     guint     *bytes_read)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  HANDLE handle;
+  DWORD avail;
+  gint result;
+
+  handle = (HANDLE) _get_osfhandle (win32_channel->fd);
+  if (!PeekNamedPipe (handle, NULL, 0, NULL, &avail, NULL))
+    {
+      return G_IO_ERROR_UNKNOWN;
+    }
+
+  count = MIN (count, avail);
+
+  count = MAX (count, 1);      /* Must read at least one byte, or
+                                * caller will think it's EOF.
+                                */
+  /* g_print ("g_io_win32_pipe_read: %d %d\n", win32_channel->fd, count); */
+  if (count == 0)
+    result = 0;
+  else
+    result = read (win32_channel->fd, buf, count);
+  if (result < 0)
+    {
+      *bytes_read = 0;
+      switch (errno)
+       {
+       case EINVAL:
+         return G_IO_ERROR_INVAL;
+       case EAGAIN:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      *bytes_read = result;
+      win32_channel->offset += result;
+      /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
+      return G_IO_ERROR_NONE;
+    }
+}
+                      
+static GIOError 
+g_io_win32_pipe_write(GIOChannel *channel, 
+                     gchar     *buf, 
+                     guint      count,
+                     guint     *bytes_written)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  LONG prevcnt;
+  gint result;
+
+  /* g_print ("g_io_win32_pipe_write: %d %d\n", win32_channel->fd, count); */
+  result = write (win32_channel->fd, buf, count);
+  if (result < 0)
+    {
+      *bytes_written = 0;
+      switch (errno)
+       {
+       case EINVAL:
+         return G_IO_ERROR_INVAL;
+       case EAGAIN:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      if (g_pipe_readable_msg == 0)
+       g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
+
+      win32_channel->offset += result;
+      /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
+      if (win32_channel->need_wakeups)
+       {
+         PostThreadMessage (win32_channel->peer,
+                            g_pipe_readable_msg,
+                            win32_channel->peer_fd,
+                            win32_channel->offset);
+       }
+      *bytes_written = result;
+      return G_IO_ERROR_NONE;
+    }
+}
+
+static void 
+g_io_win32_pipe_close (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  /* g_print ("g_io_win32_pipe_close: %#x %d\n", channel, win32_channel->fd); */
+
+  close (win32_channel->fd);
+  return;
+}
+
+static guint 
+g_io_win32_pipe_add_watch (GIOChannel    *channel,
+                          gint           priority,
+                          GIOCondition   condition,
+                          GIOFunc        func,
+                          gpointer       user_data,
+                          GDestroyNotify notify)
+{
+  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint i;
+  
+  /* g_print ("g_io_win32_pipe_add_watch: %d\n", win32_channel->fd); */
+
+  watch->channel = channel;
+  g_io_channel_ref (channel);
+
+  watch->callback = func;
+  watch->condition = condition;
+
+  watch->pollfd.fd = win32_channel->fd;
+  watch->pollfd.events = condition;
+
+  for (i = 0; i < n_watched_pipes; i++)
+    if (watched_pipes[i].fd == -1)
+      break;
+  if (i == N_WATCHED_PIPES)
+    g_error ("Too many watched pipes");
+  else
+    {
+      watched_pipes[i].fd = win32_channel->fd;
+      watched_pipes[i].watch = watch;
+      watched_pipes[i].channel = win32_channel;
+      watched_pipes[i].user_data = user_data;
+      n_watched_pipes = MAX (i + 1, n_watched_pipes);
+    }
+  return g_source_add (priority, FALSE, &win32_watch_pipe_funcs, watch, user_data, notify);
+}
+
+static void
+g_io_win32_pipe_free (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint i;
+
+  /* g_print ("g_io_win32_pipe_free: %#x %#x\n", channel, channel->channel_data); */
+
+  for (i = 0; i < n_watched_pipes; i++)
+    if (watched_pipes[i].fd == win32_channel->fd)
+      {
+       watched_pipes[i].fd = -1;
+       break;
+      }
+  g_io_win32_free (channel);
+}
+
+static GIOError 
+g_io_win32_sock_read (GIOChannel *channel, 
+                     gchar      *buf, 
+                     guint       count,
+                     guint      *bytes_read)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint result;
+
+  result = recv (win32_channel->fd, buf, count, 0);
+  if (result == SOCKET_ERROR)
+    {
+      *bytes_read = 0;
+      switch (WSAGetLastError ())
+       {
+       case WSAEINVAL:
+         return G_IO_ERROR_INVAL;
+       case WSAEWOULDBLOCK:
+       case WSAEINTR:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      *bytes_read = result;
+      return G_IO_ERROR_NONE;
+    }
+}
+                      
+static GIOError 
+g_io_win32_sock_write(GIOChannel *channel, 
+                     gchar      *buf, 
+                     guint       count,
+                     guint      *bytes_written)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint result;
+
+  result = send (win32_channel->fd, buf, count, 0);
+      
+  if (result == SOCKET_ERROR)
+    {
+      *bytes_written = 0;
+      switch (WSAGetLastError ())
+       {
+       case WSAEINVAL:
+         return G_IO_ERROR_INVAL;
+       case WSAEWOULDBLOCK:
+       case WSAEINTR:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      *bytes_written = result;
+      return G_IO_ERROR_NONE;
+    }
+}
+
+static void 
+g_io_win32_sock_close (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  closesocket (win32_channel->fd);
+  return;
+}
+
+static guint 
+g_io_win32_sock_add_watch (GIOChannel    *channel,
+                          gint           priority,
+                          GIOCondition   condition,
+                          GIOFunc        func,
+                          gpointer       user_data,
+                          GDestroyNotify notify)
+{
+  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  
+  watch->channel = channel;
+  g_io_channel_ref (channel);
+
+  watch->callback = func;
+  watch->condition = condition;
+
+  watch->pollfd.fd = win32_channel->fd;
+  watch->pollfd.events = condition;
+
+  g_main_add_poll (&watch->pollfd, priority);
+
+  return g_source_add (priority, TRUE, &win32_watch_sock_funcs, watch, user_data, notify);
+}
+
+GIOChannel *
+g_io_channel_win32_new_messages (guint hwnd)
+{
+  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
+  GIOChannel *channel = (GIOChannel *) win32_channel;
+
+  g_io_channel_init (channel);
+  channel->funcs = &win32_channel_msg_funcs;
+  win32_channel->fd = -1;
+  win32_channel->type = G_IO_WINDOWS_MESSAGES;
+  win32_channel->hwnd = (HWND) hwnd;
+
+  return channel;
+}
+
+GIOChannel *
+g_io_channel_unix_new (gint fd)
+{
+  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
+  GIOChannel *channel = (GIOChannel *) win32_channel;
+
+  g_io_channel_init (channel);
+  channel->funcs = &win32_channel_fd_funcs;
+  win32_channel->fd = fd;
+  win32_channel->type = G_IO_FILE_DESC;
+
+  return channel;
+}
+
+gint
+g_io_channel_unix_get_fd (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  return win32_channel->fd;
+}
+
+GIOChannel *
+g_io_channel_win32_new_pipe_with_wakeups (int   fd,
+                                         guint peer,
+                                         int   peer_fd)
+{
+  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
+  GIOChannel *channel = (GIOChannel *) win32_channel;
+
+  /* g_print ("g_io_channel_win32_new_pipe_with_wakeups %d %#x %d\n", fd, peer, peer_fd); */
+
+  g_io_channel_init (channel);
+  channel->funcs = &win32_channel_pipe_funcs;
+  win32_channel->fd = fd;
+  win32_channel->type = G_IO_PIPE;
+  win32_channel->peer = peer;
+  win32_channel->peer_fd = peer_fd;
+  win32_channel->offset = 0;
+  win32_channel->need_wakeups = TRUE;
+
+  return channel;
+}
+
+GIOChannel *
+g_io_channel_win32_new_pipe (int fd)
+{
+  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
+  GIOChannel *channel = (GIOChannel *) win32_channel;
+
+  g_io_channel_init (channel);
+  channel->funcs = &win32_channel_pipe_funcs;
+  win32_channel->fd = fd;
+  win32_channel->type = G_IO_PIPE;
+  win32_channel->offset = 0;
+  win32_channel->need_wakeups = FALSE;
+
+  return channel;
+}
+
+GIOChannel *
+g_io_channel_win32_new_stream_socket (int socket)
+{
+  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
+  GIOChannel *channel = (GIOChannel *) win32_channel;
+
+  g_io_channel_init (channel);
+  channel->funcs = &win32_channel_sock_funcs;
+  win32_channel->fd = socket;
+  win32_channel->type = G_IO_STREAM_SOCKET;
+
+  return channel;
+}
+
+gint
+g_io_channel_win32_get_fd (GIOChannel *channel)
+{
+  return g_io_channel_unix_get_fd (channel);
+}
+
+void
+g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
+                                        guint       peer,
+                                        int         peer_fd)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  win32_channel->peer = peer;
+  win32_channel->peer_fd = peer_fd;
+  win32_channel->need_wakeups = TRUE;
+}
+
+void
+g_io_channel_win32_pipe_readable (gint  fd,
+                                 guint offset)
+{
+  gint i;
+
+  for (i = 0; i < n_watched_pipes; i++)
+    if (watched_pipes[i].fd == fd)
+      {
+       if (watched_pipes[i].channel->offset < offset)
+         (*watched_pipes[i].watch->callback) (watched_pipes[i].watch->channel,
+                                              G_IO_IN,
+                                              watched_pipes[i].user_data);
+       break;
+      }
+}
index 4858d6cb9d8ef02db11c8511c67e3db1c0a119cb..15177bc8b9f2892d1da8b07e3be4352cccaba63a 100644 (file)
--- a/glib.def
+++ b/glib.def
@@ -1,6 +1,7 @@
 EXPORTS
        g_array_append_vals
        g_array_free
+       g_array_insert_vals
        g_array_new
        g_array_prepend_vals
        g_array_remove_index
@@ -42,11 +43,55 @@ EXPORTS
        g_dataset_id_get_data
        g_dataset_id_remove_no_notify
        g_dataset_id_set_data_full
+       g_date_add_days
+       g_date_add_months
+       g_date_add_years
+       g_date_clear
+       g_date_compare
+       g_date_day
+       g_date_day_of_year
+       g_date_days_in_month
+       g_date_free
+       g_date_is_first_of_month
+       g_date_is_last_of_month
+       g_date_is_leap_year
+       g_date_julian
+       g_date_julian
+       g_date_monday_week_of_year
+       g_date_monday_weeks_in_year
+       g_date_new
+       g_date_new_dmy
+       g_date_new_julian
+       g_date_month
+       g_date_set_day
+       g_date_set_dmy
+       g_date_set_julian
+       g_date_set_month
+       g_date_set_parse
+       g_date_set_time
+       g_date_set_year
+       g_date_strftime
+       g_date_subtract_days
+       g_date_subtract_months
+       g_date_subtract_years
+       g_date_sunday_week_of_year
+       g_date_sunday_weeks_in_year
+       g_date_to_struct_tm
+       g_date_valid
+       g_date_valid_day
+       g_date_valid_dmy
+       g_date_valid_julian
+       g_date_valid_month
+       g_date_valid_weekday
+       g_date_valid_year
+       g_date_weekday
+       g_date_year
        g_direct_equal
        g_direct_hash
        g_dirname
        g_free
        g_get_current_dir
+       g_get_current_time
        g_get_home_dir
        g_get_prgname
        g_get_real_name
@@ -81,22 +126,38 @@ EXPORTS
        g_hook_list_invoke
        g_hook_list_invoke_check
        g_hook_list_marshal
+       g_hook_list_marshal_check
        g_hook_list_clear
        g_hook_next_valid
        g_hook_prepend
        g_hook_ref
        g_hook_unref
+       g_idle_add
+       g_idle_add_full
        g_int_equal
        g_int_hash
-       g_iochannel_new
-       g_iochannel_free
-       g_iochannel_close_and_free
-       g_iochannel_wakeup_peer
+       g_io_add_watch
+       g_io_add_watch_full
+       g_io_channel_close
+       g_io_channel_init
+       g_io_channel_read
+       g_io_channel_ref
+       g_io_channel_seek
+       g_io_channel_unix_get_fd
+       g_io_channel_unix_new
+       g_io_channel_unref
+       g_io_channel_win32_get_fd
+       g_io_channel_win32_new_messages
+       g_io_channel_win32_new_pipe
+       g_io_channel_win32_new_pipe_with_wakeups
+       g_io_channel_win32_new_stream_socket
+       g_io_channel_win32_pipe_readable
+       g_io_channel_win32_pipe_request_wakeups
+       g_io_channel_write
        g_list_alloc
-       g_list_allocator_free
-       g_list_allocator_new
        g_list_append
        g_list_concat
+       g_list_copy
        g_list_find
        g_list_find_custom
        g_list_first
@@ -115,7 +176,6 @@ EXPORTS
        g_list_remove
        g_list_remove_link
        g_list_reverse
-       g_list_set_allocator
        g_list_sort
        g_log
        g_log_default_handler
@@ -124,6 +184,16 @@ EXPORTS
        g_log_set_fatal_mask
        g_log_set_handler
        g_logv
+       g_main_add_poll
+       g_main_destroy
+       g_main_is_running
+       g_main_iteration
+       g_main_new
+       g_main_pending
+       g_main_remove_poll
+       g_main_quit
+       g_main_run
+       g_main_set_poll_func
        g_malloc
        g_malloc0
        g_mem_check
@@ -136,8 +206,11 @@ EXPORTS
        g_mem_chunk_new
        g_mem_chunk_print
        g_mem_chunk_reset
+       g_mem_init
        g_mem_profile
        g_memdup
+       g_messages_init
+       g_mutex_init
        g_node_child_index
        g_node_child_position
        g_node_children_foreach
@@ -166,6 +239,7 @@ EXPORTS
        g_parse_debug_string
        g_path_is_absolute
        g_path_skip_root
+       g_pipe_readable_msg
        g_print
        g_printerr
        g_printf_string_upper_bound
@@ -224,6 +298,7 @@ EXPORTS
        g_slist_alloc
        g_slist_append
        g_slist_concat
+       g_slist_copy
        g_slist_find
        g_slist_find_custom
        g_slist_foreach
@@ -241,9 +316,15 @@ EXPORTS
        g_slist_remove
        g_slist_remove_link
        g_slist_reverse
-       g_slist_set_allocator
        g_slist_sort
        g_snprintf
+       g_source_add
+       g_source_remove
+       g_source_remove_by_source_data
+       g_source_remove_by_user_data
+       g_static_mutex_get_mutex_impl
+       g_static_private_get
+       g_static_private_set
        g_str_equal
        g_str_hash
        g_strcasecmp
@@ -284,6 +365,8 @@ EXPORTS
        g_strsplit
        g_strtod
        g_strup
+       g_timeout_add
+       g_timeout_add_full
        g_timer_destroy
        g_timer_elapsed
        g_timer_new
diff --git a/glib.h b/glib.h
index cd4ff5cfc873610a54090d5006074804913e5e59..0bbafe119f7744d8f05497cffa2ebb4b3931f395 100644 (file)
--- a/glib.h
+++ b/glib.h
@@ -2447,7 +2447,26 @@ guint            g_idle_add_full         (gint           priority,
 
 /* GPollFD
  *
- * Unix-specific IO and main loop calls
+ * System-specific IO and main loop calls
+ *
+ * On Win32, the fd in a GPollFD should be Win32 HANDLE (*not* a file
+ * descriptor as provided by the C runtime) that can be used by
+ * MsgWaitForMultipleObjects. This does *not* include file handles
+ * from CreateFile, SOCKETs, nor pipe handles. (But you can use
+ * WSAEventSelect to signal events when a SOCKET is readable).
+ *
+ * On Win32, fd can also be the special value G_WIN32_MSG_HANDLE to
+ * indicate polling for messages. These message queue GPollFDs should
+ * be added with the g_main_poll_win32_msg_add function.
+ *
+ * But note that G_WIN32_MSG_HANDLE GPollFDs should not be used by GDK
+ * (GTK) programs, as GDK itself wants to read messages and convert them
+ * to GDK events.
+ *
+ * So, unless you really know what you are doing, it's best not to try
+ * to use the main loop polling stuff for your own needs on
+ * Win32. It's really only written for the GIMP's needs so
+ * far.
  */
 
 typedef struct _GPollFD GPollFD;
@@ -2466,45 +2485,77 @@ void        g_main_add_poll          (GPollFD    *fd,
 void        g_main_remove_poll       (GPollFD    *fd);
 void        g_main_set_poll_func     (GPollFunc   func);
 
+/* On Unix, IO channels created with this function for any file
+ * descriptor or socket.
+ *
+ * On Win32, use this only for plain files opened with the MSVCRT (the
+ * Microsoft run-time C library) _open(), including file descriptors
+ * 0, 1 and 2 (corresponding to stdin, stdout and stderr).
+ * Actually, don't do even that, this code isn't done yet.
+ *
+ * The term file descriptor as used in the context of Win32 refers to
+ * the emulated Unix-like file descriptors MSVCRT provides.
+ */
 GIOChannel* g_io_channel_unix_new    (int         fd);
 gint        g_io_channel_unix_get_fd (GIOChannel *channel);
 
+#ifdef NATIVE_WIN32
+
+GUTILS_C_VAR guint g_pipe_readable_msg;
 
-/* old IO Channels */
-#if 0
-/* IO Channels.
- * These are used for plug-in communication in the GIMP, for instance.
- * On Unix, it's simply an encapsulated file descriptor (a pipe).
- * On Windows, it's a handle to an anonymouos pipe, *and* (in the case
- * of the writable end) a thread id to post a message to when you have written
- * stuff.
+#define G_WIN32_MSG_HANDLE 19981206
+
+/* This is used to add polling for Windows messages. GDK (GTk+) programs
+ * should *not* use this. (In fact, I can't think of any program that
+ * would want to use this, but it's here just for completeness's sake.
  */
-struct _GIOChannel
-{
-  gint fd;                     /* file handle (pseudo such in Win32) */
-#ifdef NATIVE_WIN32
-  guint peer;                  /* thread to post message to */
-  guint peer_fd;               /* read handle (in the other process) */
-  guint offset;                        /* counter of accumulated bytes, to
-                                * be included in the message posted
-                                * so we keep in sync.
-                                */
-  guint need_wakeups;          /* in output channels whether the reader
-                                * needs wakeups
-                                */
-#endif
-};
-GIOChannel *g_iochannel_new            (gint        fd);
-void        g_iochannel_free           (GIOChannel *channel);
-void        g_iochannel_close_and_free (GIOChannel *channel);
-void        g_iochannel_wakeup_peer    (GIOChannel *channel);
-#ifndef NATIVE_WIN32
-#  define   g_iochannel_wakeup_peer(channel) G_STMT_START { } G_STMT_END
-#endif
-#endif /* old IO Channels */
+void        g_main_poll_win32_msg_add(gint        priority,
+                                     GPollFD    *fd,
+                                     guint       hwnd);
+
+/* An IO channel for Windows messages for window handle hwnd. */
+GIOChannel *g_io_channel_win32_new_messages (guint hwnd);
+
+/* An IO channel for an anonymous pipe as returned from the MSVCRT
+ * _pipe(), with no mechanism for the writer to tell the reader when
+ * there is data in the pipe.
+ *
+ * This is not really implemented yet.
+ */
+GIOChannel *g_io_channel_win32_new_pipe (int fd);
 
+/* An IO channel for a pipe as returned from the MSVCRT _pipe(), with
+ * Windows user messages used to signal data in the pipe for the
+ * reader.
+ *
+ * fd is the file descriptor. For the write end, peer is the thread id
+ * of the reader, and peer_fd is his file descriptor for the read end
+ * of the pipe.
+ *
+ * This is used by the GIMP, and works.
+ */
+GIOChannel *g_io_channel_win32_new_pipe_with_wakeups (int   fd,
+                                                     guint peer,
+                                                     int   peer_fd);
+
+void        g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
+                                                    guint       peer,
+                                                    int         peer_fd);
+
+void        g_io_channel_win32_pipe_readable (int   fd,
+                                             guint offset);
+
+/* Get the C runtime file descriptor of a channel. */
+gint        g_io_channel_win32_get_fd (GIOChannel *channel);
+
+/* An IO channel for a SOCK_STREAM winsock socket. The parameter is
+ * actually a SOCKET.
+ */
+GIOChannel *g_io_channel_win32_new_stream_socket (int socket);
+
+#endif
 
-/* Windows emulation stubs for common unix functions
+/* Windows emulation stubs for common Unix functions
  */
 #ifdef NATIVE_WIN32
 #  define MAXPATHLEN 1024
index a9bf10a8aa1ea7258559c17261373c135b667e2c..7c05e3c8162966691133a8d75f3ff20a401ae5d0 100644 (file)
  * MT safe
  */
 
+#include "config.h"
+
 #include "glib.h"
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 
 void
 g_io_channel_init (GIOChannel *channel)
@@ -94,7 +98,7 @@ g_io_channel_close (GIOChannel *channel)
 }
 
 guint 
-g_io_add_watch_full (GIOChannel      *channel,
+g_io_add_watch_full (GIOChannel    *channel,
                     gint           priority,
                     GIOCondition   condition,
                     GIOFunc        func,
@@ -108,7 +112,7 @@ g_io_add_watch_full (GIOChannel      *channel,
 }
 
 guint 
-g_io_add_watch (GIOChannel      *channel,
+g_io_add_watch (GIOChannel    *channel,
                GIOCondition   condition,
                GIOFunc        func,
                gpointer       user_data)
diff --git a/glib/giowin32.c b/glib/giowin32.c
new file mode 100644 (file)
index 0000000..16387d4
--- /dev/null
@@ -0,0 +1,1027 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * giowin32.c: IO Channels for Win32.
+ * Copyright 1998 Owen Taylor and Tor Lillqvist
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "glib.h"
+#include <windows.h>
+#include <winsock.h>           /* Not everybody has winsock2 */
+#include <fcntl.h>
+#include <io.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <stdio.h>
+
+typedef struct _GIOWin32Channel GIOWin32Channel;
+typedef struct _GIOWin32Watch GIOWin32Watch;
+
+guint g_pipe_readable_msg;
+
+typedef enum {
+  G_IO_WINDOWS_MESSAGES,       /* Windows messages */
+  G_IO_FILE_DESC,              /* Unix-like file descriptors from _open*/
+  G_IO_PIPE,                   /* pipe, with windows messages for signalling */
+  G_IO_STREAM_SOCKET           /* Stream sockets */
+} GIOWin32ChannelType;
+
+struct _GIOWin32Channel {
+  GIOChannel channel;
+  gint fd;                     /* Either a Unix-like file handle as provided
+                                * by the Microsoft C runtime, or a SOCKET
+                                * as provided by WinSock.
+                                */
+  GIOWin32ChannelType type;
+
+  /* This is used by G_IO_WINDOWS_MESSAGES channels */
+  HWND hwnd;                   /* handle of window, or NULL */
+
+  /* This is used by G_IO_PIPE channels */
+  guint peer;                  /* thread id of reader */
+  guint peer_fd;               /* fd in the reader */
+  guint offset;                        /* counter of accumulated bytes */
+  guint need_wakeups;          /* in output channels whether the
+                                * reader needs wakeups
+                                */
+};
+
+struct _GIOWin32Watch {
+  GPollFD       pollfd;
+  GIOChannel   *channel;
+  GIOCondition  condition;
+  GIOFunc       callback;
+};
+
+static gboolean g_io_win32_msg_prepare  (gpointer  source_data, 
+                                        GTimeVal *current_time,
+                                        gint     *timeout);
+static gboolean g_io_win32_msg_check    (gpointer  source_data,
+                                        GTimeVal *current_time);
+static gboolean g_io_win32_msg_dispatch (gpointer  source_data,
+                                        GTimeVal *current_time,
+                                        gpointer  user_data);
+
+static gboolean g_io_win32_fd_prepare  (gpointer  source_data, 
+                                       GTimeVal *current_time,
+                                       gint     *timeout);
+static gboolean g_io_win32_fd_check    (gpointer  source_data,
+                                       GTimeVal *current_time);
+static gboolean g_io_win32_fd_dispatch (gpointer  source_data,
+                                       GTimeVal *current_time,
+                                       gpointer  user_data);
+
+static gboolean g_io_win32_pipe_prepare  (gpointer  source_data, 
+                                         GTimeVal *current_time,
+                                         gint     *timeout);
+static gboolean g_io_win32_pipe_check    (gpointer  source_data,
+                                         GTimeVal *current_time);
+static gboolean g_io_win32_pipe_dispatch (gpointer  source_data,
+                                         GTimeVal *current_time,
+                                         gpointer  user_data);
+static void g_io_win32_pipe_destroy     (gpointer source_data);
+
+static gboolean g_io_win32_sock_prepare  (gpointer  source_data, 
+                                         GTimeVal *current_time,
+                                         gint     *timeout);
+static gboolean g_io_win32_sock_check    (gpointer  source_data,
+                                         GTimeVal *current_time);
+static gboolean g_io_win32_sock_dispatch (gpointer  source_data,
+                                         GTimeVal *current_time,
+                                         gpointer  user_data);
+
+static void g_io_win32_destroy (gpointer source_data);
+
+static GIOError g_io_win32_msg_read (GIOChannel *channel, 
+                                    gchar      *buf, 
+                                    guint       count,
+                                    guint      *bytes_written);
+
+static GIOError g_io_win32_msg_write(GIOChannel *channel, 
+                                    gchar      *buf, 
+                                    guint       count,
+                                    guint      *bytes_written);
+static GIOError g_io_win32_msg_seek (GIOChannel *channel,
+                                    gint        offset, 
+                                    GSeekType   type);
+static void g_io_win32_msg_close    (GIOChannel *channel);
+static guint g_io_win32_msg_add_watch (GIOChannel      *channel,
+                                      gint             priority,
+                                      GIOCondition     condition,
+                                      GIOFunc          func,
+                                      gpointer         user_data,
+                                      GDestroyNotify   notify);
+
+static GIOError g_io_win32_fd_read (GIOChannel *channel, 
+                                   gchar      *buf, 
+                                   guint       count,
+                                   guint      *bytes_written);
+static GIOError g_io_win32_fd_write(GIOChannel *channel, 
+                                   gchar      *buf, 
+                                   guint       count,
+                                   guint      *bytes_written);
+static GIOError g_io_win32_fd_seek (GIOChannel *channel,
+                                   gint        offset, 
+                                   GSeekType   type);
+static void g_io_win32_fd_close (GIOChannel *channel);
+
+static void g_io_win32_free (GIOChannel *channel);
+
+static guint g_io_win32_fd_add_watch (GIOChannel      *channel,
+                                     gint             priority,
+                                     GIOCondition     condition,
+                                     GIOFunc          func,
+                                     gpointer         user_data,
+                                     GDestroyNotify   notify);
+
+static GIOError g_io_win32_no_seek (GIOChannel *channel,
+                                   gint        offset, 
+                                   GSeekType   type);
+
+static GIOError g_io_win32_pipe_read (GIOChannel *channel, 
+                                     gchar      *buf, 
+                                     guint       count,
+                                     guint      *bytes_written);
+static GIOError g_io_win32_pipe_write (GIOChannel *channel, 
+                                      gchar      *buf, 
+                                      guint       count,
+                                      guint      *bytes_written);
+static void g_io_win32_pipe_close    (GIOChannel *channel);
+static guint g_io_win32_pipe_add_watch (GIOChannel      *channel,
+                                       gint             priority,
+                                       GIOCondition     condition,
+                                       GIOFunc          func,
+                                       gpointer         user_data,
+                                       GDestroyNotify   notify);
+static void g_io_win32_pipe_free (GIOChannel *channel);
+
+static GIOError g_io_win32_sock_read (GIOChannel *channel, 
+                                     gchar      *buf, 
+                                     guint       count,
+                                     guint      *bytes_written);
+static GIOError g_io_win32_sock_write(GIOChannel *channel, 
+                                     gchar      *buf, 
+                                     guint       count,
+                                     guint      *bytes_written);
+static void g_io_win32_sock_close    (GIOChannel *channel);
+static guint g_io_win32_sock_add_watch (GIOChannel      *channel,
+                                       gint             priority,
+                                       GIOCondition     condition,
+                                       GIOFunc          func,
+                                       gpointer         user_data,
+                                       GDestroyNotify   notify);
+
+GSourceFuncs win32_watch_msg_funcs = {
+  g_io_win32_msg_prepare,
+  g_io_win32_msg_check,
+  g_io_win32_msg_dispatch,
+  g_io_win32_destroy
+};
+
+GSourceFuncs win32_watch_fd_funcs = {
+  g_io_win32_fd_prepare,
+  g_io_win32_fd_check,
+  g_io_win32_fd_dispatch,
+  g_io_win32_destroy
+};
+
+GSourceFuncs win32_watch_pipe_funcs = {
+  g_io_win32_pipe_prepare,
+  g_io_win32_pipe_check,
+  g_io_win32_pipe_dispatch,
+  g_io_win32_pipe_destroy
+};
+
+GSourceFuncs win32_watch_sock_funcs = {
+  g_io_win32_sock_prepare,
+  g_io_win32_sock_check,
+  g_io_win32_sock_dispatch,
+  g_io_win32_destroy
+};
+
+GIOFuncs win32_channel_msg_funcs = {
+  g_io_win32_msg_read,
+  g_io_win32_msg_write,
+  g_io_win32_no_seek,
+  g_io_win32_msg_close,
+  g_io_win32_msg_add_watch,
+  g_io_win32_free
+};
+
+GIOFuncs win32_channel_fd_funcs = {
+  g_io_win32_fd_read,
+  g_io_win32_fd_write,
+  g_io_win32_fd_seek,
+  g_io_win32_fd_close,
+  g_io_win32_fd_add_watch,
+  g_io_win32_free
+};
+
+GIOFuncs win32_channel_pipe_funcs = {
+  g_io_win32_pipe_read,
+  g_io_win32_pipe_write,
+  g_io_win32_no_seek,
+  g_io_win32_pipe_close,
+  g_io_win32_pipe_add_watch,
+  g_io_win32_pipe_free
+};
+
+GIOFuncs win32_channel_sock_funcs = {
+  g_io_win32_sock_read,
+  g_io_win32_sock_write,
+  g_io_win32_no_seek,
+  g_io_win32_sock_close,
+  g_io_win32_sock_add_watch,
+  g_io_win32_free
+};
+
+#define N_WATCHED_PIPES 4
+
+static struct {
+  gint fd;
+  GIOWin32Watch *watch;
+  GIOWin32Channel *channel;
+  gpointer user_data;
+} watched_pipes[N_WATCHED_PIPES];
+
+static gint n_watched_pipes = 0;
+
+static gboolean
+g_io_win32_msg_prepare  (gpointer source_data, 
+                        GTimeVal *current_time,
+                        gint    *timeout)
+{
+  GIOWin32Watch *data = source_data;
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
+  MSG msg;
+
+  *timeout = -1;
+
+  return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
+}
+
+static gboolean 
+g_io_win32_msg_check    (gpointer source_data,
+                        GTimeVal *current_time)
+{
+  GIOWin32Watch *data = source_data;
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) data->channel;
+  MSG msg;
+
+  return PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_NOREMOVE) == TRUE;
+}
+
+static gboolean
+g_io_win32_msg_dispatch (gpointer source_data, 
+                        GTimeVal *current_time,
+                        gpointer user_data)
+
+{
+  GIOWin32Watch *data = source_data;
+
+  return (*data->callback)(data->channel,
+                          data->pollfd.revents & data->condition,
+                          user_data);
+}
+
+static void
+g_io_win32_destroy (gpointer source_data)
+{
+  GIOWin32Watch *data = source_data;
+
+  g_main_remove_poll (&data->pollfd);
+  g_io_channel_unref (data->channel);
+  g_free (data);
+}
+
+static gboolean
+g_io_win32_fd_prepare  (gpointer source_data, 
+                       GTimeVal *current_time,
+                       gint    *timeout)
+{
+  *timeout = -1;
+
+  return FALSE;
+}
+
+static gboolean 
+g_io_win32_fd_check    (gpointer source_data,
+                       GTimeVal *current_time)
+{
+  GIOWin32Watch *data = source_data;
+
+  return (data->pollfd.revents & data->condition);
+}
+
+static gboolean
+g_io_win32_fd_dispatch (gpointer source_data, 
+                       GTimeVal *current_time,
+                       gpointer user_data)
+
+{
+  GIOWin32Watch *data = source_data;
+
+  return (*data->callback)(data->channel,
+                          data->pollfd.revents & data->condition,
+                          user_data);
+}
+
+static GIOError
+g_io_win32_msg_read (GIOChannel *channel, 
+                    gchar     *buf, 
+                    guint      count,
+                    guint     *bytes_read)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  MSG msg;                     /* In case of alignment problems */
+
+  if (count < sizeof (MSG))
+    return G_IO_ERROR_INVAL;
+  
+  if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
+    return G_IO_ERROR_AGAIN;
+
+  memmove (buf, &msg, sizeof (MSG));
+  *bytes_read = sizeof (MSG);
+  return G_IO_ERROR_NONE;
+}
+                      
+static GIOError 
+g_io_win32_msg_write(GIOChannel *channel, 
+                    gchar     *buf, 
+                    guint      count,
+                    guint     *bytes_written)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  MSG msg;
+  gint result;
+
+  if (count != sizeof (MSG))
+    return G_IO_ERROR_INVAL;
+
+  /* In case of alignment problems */
+  memmove (&msg, buf, sizeof (MSG));
+  if (!PostMessage (win32_channel->hwnd, msg.message, msg.wParam, msg.lParam))
+    return G_IO_ERROR_UNKNOWN;
+
+  *bytes_written = sizeof (MSG);
+  return G_IO_ERROR_NONE; 
+}
+
+static GIOError 
+g_io_win32_no_seek (GIOChannel *channel,
+                   gint      offset, 
+                   GSeekType type)
+{
+  g_warning ("g_io_win32_no_seek: unseekable IO channel type");
+  return G_IO_ERROR_UNKNOWN;
+}
+
+
+static void 
+g_io_win32_msg_close (GIOChannel *channel)
+{
+  /* Nothing to be done. Or should we set hwnd to some invalid value? */
+}
+
+static void 
+g_io_win32_free (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  g_free (win32_channel);
+}
+
+static guint 
+g_io_win32_msg_add_watch (GIOChannel    *channel,
+                         gint           priority,
+                         GIOCondition   condition,
+                         GIOFunc        func,
+                         gpointer       user_data,
+                         GDestroyNotify notify)
+{
+  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  
+  watch->channel = channel;
+  g_io_channel_ref (channel);
+
+  watch->callback = func;
+  watch->condition = condition;
+
+  watch->pollfd.fd = G_WIN32_MSG_HANDLE;
+  watch->pollfd.events = condition;
+
+  g_main_add_poll (&watch->pollfd, priority);
+
+  return g_source_add (priority, TRUE, &win32_watch_msg_funcs,
+                      watch, user_data, notify);
+}
+
+static gboolean
+g_io_win32_pipe_prepare  (gpointer source_data, 
+                         GTimeVal *current_time,
+                         gint    *timeout)
+{
+  *timeout = -1;
+
+  return FALSE;
+}
+
+static gboolean 
+g_io_win32_pipe_check    (gpointer source_data,
+                         GTimeVal *current_time)
+{
+  GIOWin32Watch *data = source_data;
+  return FALSE;
+}
+
+static gboolean
+g_io_win32_pipe_dispatch (gpointer source_data, 
+                         GTimeVal *current_time,
+                         gpointer user_data)
+
+{
+  GIOWin32Watch *data = source_data;
+
+  return (*data->callback)(data->channel,
+                          data->pollfd.revents & data->condition,
+                          user_data);
+}
+
+static void
+g_io_win32_pipe_destroy (gpointer source_data)
+{
+  GIOWin32Watch *data = source_data;
+
+  g_io_channel_unref (data->channel);
+  g_free (data);
+}
+
+static gboolean
+g_io_win32_sock_prepare  (gpointer source_data, 
+                       GTimeVal *current_time,
+                       gint    *timeout)
+{
+  *timeout = -1;
+
+  return FALSE;
+}
+
+static gboolean 
+g_io_win32_sock_check    (gpointer source_data,
+                       GTimeVal *current_time)
+{
+  GIOWin32Watch *data = source_data;
+
+  return (data->pollfd.revents & data->condition);
+}
+
+static gboolean
+g_io_win32_sock_dispatch (gpointer source_data, 
+                       GTimeVal *current_time,
+                       gpointer user_data)
+
+{
+  GIOWin32Watch *data = source_data;
+
+  return (*data->callback)(data->channel,
+                          data->pollfd.revents & data->condition,
+                          user_data);
+}
+
+static GIOError
+g_io_win32_fd_read (GIOChannel *channel, 
+                   gchar     *buf, 
+                   guint      count,
+                   guint     *bytes_read)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint result;
+
+  result = read (win32_channel->fd, buf, count);
+  if (result < 0)
+    {
+      *bytes_read = 0;
+      switch (errno)
+       {
+       case EINVAL:
+         return G_IO_ERROR_INVAL;
+       case EAGAIN:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      *bytes_read = result;
+      return G_IO_ERROR_NONE;
+    }
+}
+                      
+static GIOError 
+g_io_win32_fd_write(GIOChannel *channel, 
+                   gchar     *buf, 
+                   guint      count,
+                   guint     *bytes_written)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint result;
+
+  result = write (win32_channel->fd, buf, count);
+      
+  if (result < 0)
+    {
+      *bytes_written = 0;
+      switch (errno)
+       {
+       case EINVAL:
+         return G_IO_ERROR_INVAL;
+       case EAGAIN:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      *bytes_written = result;
+      return G_IO_ERROR_NONE;
+    }
+}
+
+static GIOError 
+g_io_win32_fd_seek (GIOChannel *channel,
+                   gint      offset, 
+                   GSeekType type)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  int whence;
+  off_t result;
+
+  switch (type)
+    {
+    case G_SEEK_SET:
+      whence = SEEK_SET;
+      break;
+    case G_SEEK_CUR:
+      whence = SEEK_CUR;
+      break;
+    case G_SEEK_END:
+      whence = SEEK_END;
+      break;
+    default:
+      g_warning ("g_io_win32_fd_seek: unknown seek type");
+      return G_IO_ERROR_UNKNOWN;
+    }
+  
+  result = lseek (win32_channel->fd, offset, whence);
+  
+  if (result < 0)
+    {
+      switch (errno)
+       {
+       case EINVAL:
+         return G_IO_ERROR_INVAL;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    return G_IO_ERROR_NONE;
+}
+
+static void 
+g_io_win32_fd_close (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  close (win32_channel->fd);
+  return;
+}
+
+static guint 
+g_io_win32_fd_add_watch (GIOChannel    *channel,
+                        gint           priority,
+                        GIOCondition   condition,
+                        GIOFunc        func,
+                        gpointer       user_data,
+                        GDestroyNotify notify)
+{
+  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  
+  watch->channel = channel;
+  g_io_channel_ref (channel);
+
+  watch->callback = func;
+  watch->condition = condition;
+
+  /* This probably does not work, except for CONIN$. */
+  watch->pollfd.fd = _get_osfhandle (win32_channel->fd);
+  watch->pollfd.events = condition;
+
+  g_main_add_poll (&watch->pollfd, priority);
+
+  return g_source_add (priority, TRUE, &win32_watch_fd_funcs,
+                      watch, user_data, notify);
+}
+
+static GIOError
+g_io_win32_pipe_read (GIOChannel *channel, 
+                     gchar     *buf, 
+                     guint      count,
+                     guint     *bytes_read)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  HANDLE handle;
+  DWORD avail;
+  gint result;
+
+  handle = (HANDLE) _get_osfhandle (win32_channel->fd);
+  if (!PeekNamedPipe (handle, NULL, 0, NULL, &avail, NULL))
+    {
+      return G_IO_ERROR_UNKNOWN;
+    }
+
+  count = MIN (count, avail);
+
+  count = MAX (count, 1);      /* Must read at least one byte, or
+                                * caller will think it's EOF.
+                                */
+  /* g_print ("g_io_win32_pipe_read: %d %d\n", win32_channel->fd, count); */
+  if (count == 0)
+    result = 0;
+  else
+    result = read (win32_channel->fd, buf, count);
+  if (result < 0)
+    {
+      *bytes_read = 0;
+      switch (errno)
+       {
+       case EINVAL:
+         return G_IO_ERROR_INVAL;
+       case EAGAIN:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      *bytes_read = result;
+      win32_channel->offset += result;
+      /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
+      return G_IO_ERROR_NONE;
+    }
+}
+                      
+static GIOError 
+g_io_win32_pipe_write(GIOChannel *channel, 
+                     gchar     *buf, 
+                     guint      count,
+                     guint     *bytes_written)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  LONG prevcnt;
+  gint result;
+
+  /* g_print ("g_io_win32_pipe_write: %d %d\n", win32_channel->fd, count); */
+  result = write (win32_channel->fd, buf, count);
+  if (result < 0)
+    {
+      *bytes_written = 0;
+      switch (errno)
+       {
+       case EINVAL:
+         return G_IO_ERROR_INVAL;
+       case EAGAIN:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      if (g_pipe_readable_msg == 0)
+       g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
+
+      win32_channel->offset += result;
+      /* g_print ("=%d (%d)\n", result, win32_channel->offset); */
+      if (win32_channel->need_wakeups)
+       {
+         PostThreadMessage (win32_channel->peer,
+                            g_pipe_readable_msg,
+                            win32_channel->peer_fd,
+                            win32_channel->offset);
+       }
+      *bytes_written = result;
+      return G_IO_ERROR_NONE;
+    }
+}
+
+static void 
+g_io_win32_pipe_close (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  /* g_print ("g_io_win32_pipe_close: %#x %d\n", channel, win32_channel->fd); */
+
+  close (win32_channel->fd);
+  return;
+}
+
+static guint 
+g_io_win32_pipe_add_watch (GIOChannel    *channel,
+                          gint           priority,
+                          GIOCondition   condition,
+                          GIOFunc        func,
+                          gpointer       user_data,
+                          GDestroyNotify notify)
+{
+  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint i;
+  
+  /* g_print ("g_io_win32_pipe_add_watch: %d\n", win32_channel->fd); */
+
+  watch->channel = channel;
+  g_io_channel_ref (channel);
+
+  watch->callback = func;
+  watch->condition = condition;
+
+  watch->pollfd.fd = win32_channel->fd;
+  watch->pollfd.events = condition;
+
+  for (i = 0; i < n_watched_pipes; i++)
+    if (watched_pipes[i].fd == -1)
+      break;
+  if (i == N_WATCHED_PIPES)
+    g_error ("Too many watched pipes");
+  else
+    {
+      watched_pipes[i].fd = win32_channel->fd;
+      watched_pipes[i].watch = watch;
+      watched_pipes[i].channel = win32_channel;
+      watched_pipes[i].user_data = user_data;
+      n_watched_pipes = MAX (i + 1, n_watched_pipes);
+    }
+  return g_source_add (priority, FALSE, &win32_watch_pipe_funcs, watch, user_data, notify);
+}
+
+static void
+g_io_win32_pipe_free (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint i;
+
+  /* g_print ("g_io_win32_pipe_free: %#x %#x\n", channel, channel->channel_data); */
+
+  for (i = 0; i < n_watched_pipes; i++)
+    if (watched_pipes[i].fd == win32_channel->fd)
+      {
+       watched_pipes[i].fd = -1;
+       break;
+      }
+  g_io_win32_free (channel);
+}
+
+static GIOError 
+g_io_win32_sock_read (GIOChannel *channel, 
+                     gchar      *buf, 
+                     guint       count,
+                     guint      *bytes_read)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint result;
+
+  result = recv (win32_channel->fd, buf, count, 0);
+  if (result == SOCKET_ERROR)
+    {
+      *bytes_read = 0;
+      switch (WSAGetLastError ())
+       {
+       case WSAEINVAL:
+         return G_IO_ERROR_INVAL;
+       case WSAEWOULDBLOCK:
+       case WSAEINTR:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      *bytes_read = result;
+      return G_IO_ERROR_NONE;
+    }
+}
+                      
+static GIOError 
+g_io_win32_sock_write(GIOChannel *channel, 
+                     gchar      *buf, 
+                     guint       count,
+                     guint      *bytes_written)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  gint result;
+
+  result = send (win32_channel->fd, buf, count, 0);
+      
+  if (result == SOCKET_ERROR)
+    {
+      *bytes_written = 0;
+      switch (WSAGetLastError ())
+       {
+       case WSAEINVAL:
+         return G_IO_ERROR_INVAL;
+       case WSAEWOULDBLOCK:
+       case WSAEINTR:
+         return G_IO_ERROR_AGAIN;
+       default:
+         return G_IO_ERROR_UNKNOWN;
+       }
+    }
+  else
+    {
+      *bytes_written = result;
+      return G_IO_ERROR_NONE;
+    }
+}
+
+static void 
+g_io_win32_sock_close (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  closesocket (win32_channel->fd);
+  return;
+}
+
+static guint 
+g_io_win32_sock_add_watch (GIOChannel    *channel,
+                          gint           priority,
+                          GIOCondition   condition,
+                          GIOFunc        func,
+                          gpointer       user_data,
+                          GDestroyNotify notify)
+{
+  GIOWin32Watch *watch = g_new (GIOWin32Watch, 1);
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+  
+  watch->channel = channel;
+  g_io_channel_ref (channel);
+
+  watch->callback = func;
+  watch->condition = condition;
+
+  watch->pollfd.fd = win32_channel->fd;
+  watch->pollfd.events = condition;
+
+  g_main_add_poll (&watch->pollfd, priority);
+
+  return g_source_add (priority, TRUE, &win32_watch_sock_funcs, watch, user_data, notify);
+}
+
+GIOChannel *
+g_io_channel_win32_new_messages (guint hwnd)
+{
+  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
+  GIOChannel *channel = (GIOChannel *) win32_channel;
+
+  g_io_channel_init (channel);
+  channel->funcs = &win32_channel_msg_funcs;
+  win32_channel->fd = -1;
+  win32_channel->type = G_IO_WINDOWS_MESSAGES;
+  win32_channel->hwnd = (HWND) hwnd;
+
+  return channel;
+}
+
+GIOChannel *
+g_io_channel_unix_new (gint fd)
+{
+  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
+  GIOChannel *channel = (GIOChannel *) win32_channel;
+
+  g_io_channel_init (channel);
+  channel->funcs = &win32_channel_fd_funcs;
+  win32_channel->fd = fd;
+  win32_channel->type = G_IO_FILE_DESC;
+
+  return channel;
+}
+
+gint
+g_io_channel_unix_get_fd (GIOChannel *channel)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  return win32_channel->fd;
+}
+
+GIOChannel *
+g_io_channel_win32_new_pipe_with_wakeups (int   fd,
+                                         guint peer,
+                                         int   peer_fd)
+{
+  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
+  GIOChannel *channel = (GIOChannel *) win32_channel;
+
+  /* g_print ("g_io_channel_win32_new_pipe_with_wakeups %d %#x %d\n", fd, peer, peer_fd); */
+
+  g_io_channel_init (channel);
+  channel->funcs = &win32_channel_pipe_funcs;
+  win32_channel->fd = fd;
+  win32_channel->type = G_IO_PIPE;
+  win32_channel->peer = peer;
+  win32_channel->peer_fd = peer_fd;
+  win32_channel->offset = 0;
+  win32_channel->need_wakeups = TRUE;
+
+  return channel;
+}
+
+GIOChannel *
+g_io_channel_win32_new_pipe (int fd)
+{
+  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
+  GIOChannel *channel = (GIOChannel *) win32_channel;
+
+  g_io_channel_init (channel);
+  channel->funcs = &win32_channel_pipe_funcs;
+  win32_channel->fd = fd;
+  win32_channel->type = G_IO_PIPE;
+  win32_channel->offset = 0;
+  win32_channel->need_wakeups = FALSE;
+
+  return channel;
+}
+
+GIOChannel *
+g_io_channel_win32_new_stream_socket (int socket)
+{
+  GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
+  GIOChannel *channel = (GIOChannel *) win32_channel;
+
+  g_io_channel_init (channel);
+  channel->funcs = &win32_channel_sock_funcs;
+  win32_channel->fd = socket;
+  win32_channel->type = G_IO_STREAM_SOCKET;
+
+  return channel;
+}
+
+gint
+g_io_channel_win32_get_fd (GIOChannel *channel)
+{
+  return g_io_channel_unix_get_fd (channel);
+}
+
+void
+g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
+                                        guint       peer,
+                                        int         peer_fd)
+{
+  GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
+
+  win32_channel->peer = peer;
+  win32_channel->peer_fd = peer_fd;
+  win32_channel->need_wakeups = TRUE;
+}
+
+void
+g_io_channel_win32_pipe_readable (gint  fd,
+                                 guint offset)
+{
+  gint i;
+
+  for (i = 0; i < n_watched_pipes; i++)
+    if (watched_pipes[i].fd == fd)
+      {
+       if (watched_pipes[i].channel->offset < offset)
+         (*watched_pipes[i].watch->callback) (watched_pipes[i].watch->channel,
+                                              G_IO_IN,
+                                              watched_pipes[i].user_data);
+       break;
+      }
+}
index 4858d6cb9d8ef02db11c8511c67e3db1c0a119cb..15177bc8b9f2892d1da8b07e3be4352cccaba63a 100644 (file)
@@ -1,6 +1,7 @@
 EXPORTS
        g_array_append_vals
        g_array_free
+       g_array_insert_vals
        g_array_new
        g_array_prepend_vals
        g_array_remove_index
@@ -42,11 +43,55 @@ EXPORTS
        g_dataset_id_get_data
        g_dataset_id_remove_no_notify
        g_dataset_id_set_data_full
+       g_date_add_days
+       g_date_add_months
+       g_date_add_years
+       g_date_clear
+       g_date_compare
+       g_date_day
+       g_date_day_of_year
+       g_date_days_in_month
+       g_date_free
+       g_date_is_first_of_month
+       g_date_is_last_of_month
+       g_date_is_leap_year
+       g_date_julian
+       g_date_julian
+       g_date_monday_week_of_year
+       g_date_monday_weeks_in_year
+       g_date_new
+       g_date_new_dmy
+       g_date_new_julian
+       g_date_month
+       g_date_set_day
+       g_date_set_dmy
+       g_date_set_julian
+       g_date_set_month
+       g_date_set_parse
+       g_date_set_time
+       g_date_set_year
+       g_date_strftime
+       g_date_subtract_days
+       g_date_subtract_months
+       g_date_subtract_years
+       g_date_sunday_week_of_year
+       g_date_sunday_weeks_in_year
+       g_date_to_struct_tm
+       g_date_valid
+       g_date_valid_day
+       g_date_valid_dmy
+       g_date_valid_julian
+       g_date_valid_month
+       g_date_valid_weekday
+       g_date_valid_year
+       g_date_weekday
+       g_date_year
        g_direct_equal
        g_direct_hash
        g_dirname
        g_free
        g_get_current_dir
+       g_get_current_time
        g_get_home_dir
        g_get_prgname
        g_get_real_name
@@ -81,22 +126,38 @@ EXPORTS
        g_hook_list_invoke
        g_hook_list_invoke_check
        g_hook_list_marshal
+       g_hook_list_marshal_check
        g_hook_list_clear
        g_hook_next_valid
        g_hook_prepend
        g_hook_ref
        g_hook_unref
+       g_idle_add
+       g_idle_add_full
        g_int_equal
        g_int_hash
-       g_iochannel_new
-       g_iochannel_free
-       g_iochannel_close_and_free
-       g_iochannel_wakeup_peer
+       g_io_add_watch
+       g_io_add_watch_full
+       g_io_channel_close
+       g_io_channel_init
+       g_io_channel_read
+       g_io_channel_ref
+       g_io_channel_seek
+       g_io_channel_unix_get_fd
+       g_io_channel_unix_new
+       g_io_channel_unref
+       g_io_channel_win32_get_fd
+       g_io_channel_win32_new_messages
+       g_io_channel_win32_new_pipe
+       g_io_channel_win32_new_pipe_with_wakeups
+       g_io_channel_win32_new_stream_socket
+       g_io_channel_win32_pipe_readable
+       g_io_channel_win32_pipe_request_wakeups
+       g_io_channel_write
        g_list_alloc
-       g_list_allocator_free
-       g_list_allocator_new
        g_list_append
        g_list_concat
+       g_list_copy
        g_list_find
        g_list_find_custom
        g_list_first
@@ -115,7 +176,6 @@ EXPORTS
        g_list_remove
        g_list_remove_link
        g_list_reverse
-       g_list_set_allocator
        g_list_sort
        g_log
        g_log_default_handler
@@ -124,6 +184,16 @@ EXPORTS
        g_log_set_fatal_mask
        g_log_set_handler
        g_logv
+       g_main_add_poll
+       g_main_destroy
+       g_main_is_running
+       g_main_iteration
+       g_main_new
+       g_main_pending
+       g_main_remove_poll
+       g_main_quit
+       g_main_run
+       g_main_set_poll_func
        g_malloc
        g_malloc0
        g_mem_check
@@ -136,8 +206,11 @@ EXPORTS
        g_mem_chunk_new
        g_mem_chunk_print
        g_mem_chunk_reset
+       g_mem_init
        g_mem_profile
        g_memdup
+       g_messages_init
+       g_mutex_init
        g_node_child_index
        g_node_child_position
        g_node_children_foreach
@@ -166,6 +239,7 @@ EXPORTS
        g_parse_debug_string
        g_path_is_absolute
        g_path_skip_root
+       g_pipe_readable_msg
        g_print
        g_printerr
        g_printf_string_upper_bound
@@ -224,6 +298,7 @@ EXPORTS
        g_slist_alloc
        g_slist_append
        g_slist_concat
+       g_slist_copy
        g_slist_find
        g_slist_find_custom
        g_slist_foreach
@@ -241,9 +316,15 @@ EXPORTS
        g_slist_remove
        g_slist_remove_link
        g_slist_reverse
-       g_slist_set_allocator
        g_slist_sort
        g_snprintf
+       g_source_add
+       g_source_remove
+       g_source_remove_by_source_data
+       g_source_remove_by_user_data
+       g_static_mutex_get_mutex_impl
+       g_static_private_get
+       g_static_private_set
        g_str_equal
        g_str_hash
        g_strcasecmp
@@ -284,6 +365,8 @@ EXPORTS
        g_strsplit
        g_strtod
        g_strup
+       g_timeout_add
+       g_timeout_add_full
        g_timer_destroy
        g_timer_elapsed
        g_timer_new
index cd4ff5cfc873610a54090d5006074804913e5e59..0bbafe119f7744d8f05497cffa2ebb4b3931f395 100644 (file)
@@ -2447,7 +2447,26 @@ guint            g_idle_add_full         (gint           priority,
 
 /* GPollFD
  *
- * Unix-specific IO and main loop calls
+ * System-specific IO and main loop calls
+ *
+ * On Win32, the fd in a GPollFD should be Win32 HANDLE (*not* a file
+ * descriptor as provided by the C runtime) that can be used by
+ * MsgWaitForMultipleObjects. This does *not* include file handles
+ * from CreateFile, SOCKETs, nor pipe handles. (But you can use
+ * WSAEventSelect to signal events when a SOCKET is readable).
+ *
+ * On Win32, fd can also be the special value G_WIN32_MSG_HANDLE to
+ * indicate polling for messages. These message queue GPollFDs should
+ * be added with the g_main_poll_win32_msg_add function.
+ *
+ * But note that G_WIN32_MSG_HANDLE GPollFDs should not be used by GDK
+ * (GTK) programs, as GDK itself wants to read messages and convert them
+ * to GDK events.
+ *
+ * So, unless you really know what you are doing, it's best not to try
+ * to use the main loop polling stuff for your own needs on
+ * Win32. It's really only written for the GIMP's needs so
+ * far.
  */
 
 typedef struct _GPollFD GPollFD;
@@ -2466,45 +2485,77 @@ void        g_main_add_poll          (GPollFD    *fd,
 void        g_main_remove_poll       (GPollFD    *fd);
 void        g_main_set_poll_func     (GPollFunc   func);
 
+/* On Unix, IO channels created with this function for any file
+ * descriptor or socket.
+ *
+ * On Win32, use this only for plain files opened with the MSVCRT (the
+ * Microsoft run-time C library) _open(), including file descriptors
+ * 0, 1 and 2 (corresponding to stdin, stdout and stderr).
+ * Actually, don't do even that, this code isn't done yet.
+ *
+ * The term file descriptor as used in the context of Win32 refers to
+ * the emulated Unix-like file descriptors MSVCRT provides.
+ */
 GIOChannel* g_io_channel_unix_new    (int         fd);
 gint        g_io_channel_unix_get_fd (GIOChannel *channel);
 
+#ifdef NATIVE_WIN32
+
+GUTILS_C_VAR guint g_pipe_readable_msg;
 
-/* old IO Channels */
-#if 0
-/* IO Channels.
- * These are used for plug-in communication in the GIMP, for instance.
- * On Unix, it's simply an encapsulated file descriptor (a pipe).
- * On Windows, it's a handle to an anonymouos pipe, *and* (in the case
- * of the writable end) a thread id to post a message to when you have written
- * stuff.
+#define G_WIN32_MSG_HANDLE 19981206
+
+/* This is used to add polling for Windows messages. GDK (GTk+) programs
+ * should *not* use this. (In fact, I can't think of any program that
+ * would want to use this, but it's here just for completeness's sake.
  */
-struct _GIOChannel
-{
-  gint fd;                     /* file handle (pseudo such in Win32) */
-#ifdef NATIVE_WIN32
-  guint peer;                  /* thread to post message to */
-  guint peer_fd;               /* read handle (in the other process) */
-  guint offset;                        /* counter of accumulated bytes, to
-                                * be included in the message posted
-                                * so we keep in sync.
-                                */
-  guint need_wakeups;          /* in output channels whether the reader
-                                * needs wakeups
-                                */
-#endif
-};
-GIOChannel *g_iochannel_new            (gint        fd);
-void        g_iochannel_free           (GIOChannel *channel);
-void        g_iochannel_close_and_free (GIOChannel *channel);
-void        g_iochannel_wakeup_peer    (GIOChannel *channel);
-#ifndef NATIVE_WIN32
-#  define   g_iochannel_wakeup_peer(channel) G_STMT_START { } G_STMT_END
-#endif
-#endif /* old IO Channels */
+void        g_main_poll_win32_msg_add(gint        priority,
+                                     GPollFD    *fd,
+                                     guint       hwnd);
+
+/* An IO channel for Windows messages for window handle hwnd. */
+GIOChannel *g_io_channel_win32_new_messages (guint hwnd);
+
+/* An IO channel for an anonymous pipe as returned from the MSVCRT
+ * _pipe(), with no mechanism for the writer to tell the reader when
+ * there is data in the pipe.
+ *
+ * This is not really implemented yet.
+ */
+GIOChannel *g_io_channel_win32_new_pipe (int fd);
 
+/* An IO channel for a pipe as returned from the MSVCRT _pipe(), with
+ * Windows user messages used to signal data in the pipe for the
+ * reader.
+ *
+ * fd is the file descriptor. For the write end, peer is the thread id
+ * of the reader, and peer_fd is his file descriptor for the read end
+ * of the pipe.
+ *
+ * This is used by the GIMP, and works.
+ */
+GIOChannel *g_io_channel_win32_new_pipe_with_wakeups (int   fd,
+                                                     guint peer,
+                                                     int   peer_fd);
+
+void        g_io_channel_win32_pipe_request_wakeups (GIOChannel *channel,
+                                                    guint       peer,
+                                                    int         peer_fd);
+
+void        g_io_channel_win32_pipe_readable (int   fd,
+                                             guint offset);
+
+/* Get the C runtime file descriptor of a channel. */
+gint        g_io_channel_win32_get_fd (GIOChannel *channel);
+
+/* An IO channel for a SOCK_STREAM winsock socket. The parameter is
+ * actually a SOCKET.
+ */
+GIOChannel *g_io_channel_win32_new_stream_socket (int socket);
+
+#endif
 
-/* Windows emulation stubs for common unix functions
+/* Windows emulation stubs for common Unix functions
  */
 #ifdef NATIVE_WIN32
 #  define MAXPATHLEN 1024
index ff4c2051384c936694176a2164db1efcc4a5de65..7e3571b4cdce428c12711a8ae7294ea8bf79c9ab 100644 (file)
  * MT safe
  */
 
+#include "config.h"
+
 #include "glib.h"
 #include <sys/types.h>
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
+#endif
 #ifdef GLIB_HAVE_SYS_POLL_H
 #  include <sys/poll.h>
 #  undef events         /* AIX 4.1.5 & 4.3.2 define this for SVR3,4 compatibility */
 #  undef revents /* AIX 4.1.5 & 4.3.2 define this for SVR3,4 compatibility */
 #endif /* GLIB_HAVE_SYS_POLL_H */
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <errno.h>
-#include "config.h"
+
+#ifdef NATIVE_WIN32
+#define STRICT
+#include <windows.h>
+#endif
+
+#ifdef _MSC_VER
+#include <fcntl.h>
+#include <io.h>
+#endif
 
 /* Types */
 
@@ -138,15 +154,160 @@ static GPollRec *poll_free_list = NULL;
 static GMemChunk *poll_chunk;
 static guint n_poll_records = 0;
 
+#ifdef G_THREADS_ENABLED
+#ifndef NATIVE_WIN32
 /* this pipe is used to wake up the main loop when a source is added.
  */
 static gint wake_up_pipe[2] = { -1, -1 };
+#else
+static HANDLE wake_up_semaphore = NULL;
+#endif
 static GPollFD wake_up_rec;
 static gboolean poll_waiting = FALSE;
+#endif
 
 #ifdef HAVE_POLL
 static GPollFunc poll_func = (GPollFunc) poll;
 #else  /* !HAVE_POLL */
+#ifdef NATIVE_WIN32
+
+static gint
+g_poll (GPollFD *fds, guint nfds, gint timeout)
+{
+  HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+  GPollFD *f;
+  DWORD ready;
+  MSG msg;
+  UINT timer;
+  LONG prevcnt;
+  gint poll_msgs = -1;
+  gint nhandles = 0;
+
+  for (f = fds; f < &fds[nfds]; ++f)
+    if (f->fd >= 0)
+      {
+       if (f->events & G_IO_IN)
+         if (f->fd == G_WIN32_MSG_HANDLE)
+           poll_msgs = f - fds;
+         else
+           {
+             /* g_print ("g_poll: waiting for handle %#x\n", f->fd); */
+             handles[nhandles++] = (HANDLE) f->fd;
+           }
+      }
+
+  if (timeout == -1)
+    timeout = INFINITE;
+
+  if (poll_msgs >= 0)
+    {
+      /* Waiting for messages, and maybe events */
+      if (nhandles == 0)
+       {
+         if (timeout == INFINITE)
+           {
+             /* Waiting just for messages, infinite timeout
+              * -> Use PeekMessage, then WaitMessage
+              */
+             /* g_print ("WaitMessage, PeekMessage\n"); */
+             if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+               ready = WAIT_OBJECT_0;
+             else if (!WaitMessage ())
+               g_warning ("g_poll: WaitMessage failed");
+             ready = WAIT_OBJECT_0;
+           }
+         else if (timeout == 0)
+           {
+             /* Waiting just for messages, zero timeout
+              * -> Use PeekMessage
+              */
+             /* g_print ("PeekMessage\n"); */
+             if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+               ready = WAIT_OBJECT_0;
+             else
+               ready = WAIT_TIMEOUT;
+           }
+         else
+           {
+             /* Waiting just for messages, some timeout
+              * -> First try PeekMessage, then set a timer, wait for message,
+              * kill timer, use PeekMessage
+              */
+             /* g_print ("PeekMessage\n"); */
+             if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+               ready = WAIT_OBJECT_0;
+             else if ((timer = SetTimer (NULL, 0, timeout, NULL)) == 0)
+               g_warning ("g_poll: SetTimer failed");
+             else
+               {
+                 /* g_print ("WaitMessage\n"); */
+                 WaitMessage ();
+                 KillTimer (NULL, timer);
+                 if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+                   ready = WAIT_OBJECT_0;
+                 else
+                   ready = WAIT_TIMEOUT;
+               }
+           }
+       }
+      else
+       {
+         /* Wait for either message or event
+          * -> Use MsgWaitForMultipleObjects
+          */
+         /* g_print ("MsgWaitForMultipleObjects(%d, %d)\n", nhandles, timeout); */
+         ready = MsgWaitForMultipleObjects (nhandles, handles, FALSE,
+                                            timeout, QS_ALLINPUT);
+         /* g_print("=%d\n", ready); */
+         if (ready == WAIT_FAILED)
+           g_warning ("g_poll: MsgWaitForMultipleObjects failed");
+       }
+    }
+  else if (nhandles == 0)
+    {
+      /* Wait for nothing (huh?) */
+      return 0;
+    }
+  else
+    {
+      /* Wait for just events
+       * -> Use WaitForMultipleObjects
+       */
+      /* g_print ("WaitForMultipleObjects(%d, %d)\n", nhandles, timeout); */
+      ready = WaitForMultipleObjects (nhandles, handles, FALSE, timeout);
+      /* g_print("=%d\n", ready); */
+      if (ready == WAIT_FAILED)
+       g_warning ("g_poll: WaitForMultipleObjects failed");
+    }
+
+  for (f = fds; f < &fds[nfds]; ++f)
+    f->revents = 0;
+
+  if (ready == WAIT_FAILED)
+    return -1;
+  else if (poll_msgs >= 0 && ready == WAIT_OBJECT_0 + nhandles)
+    {
+      fds[poll_msgs].revents |= G_IO_IN;
+    }
+  else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
+    for (f = fds; f < &fds[nfds]; ++f)
+      {
+       if ((f->events & G_IO_IN)
+           && f->fd == (gint) handles[ready - WAIT_OBJECT_0])
+         {
+           f->revents |= G_IO_IN;
+           /* g_print ("event %#x\n", f->fd); */
+           ResetEvent ((HANDLE) f->fd);
+         }
+      }
+    
+  if (ready == WAIT_TIMEOUT)
+    return 0;
+  else
+    return 1;
+}
+
+#else  /* !NATIVE_WIN32 */
 
 /* The following implementation of poll() comes from the GNU C Library.
  * Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
@@ -219,6 +380,8 @@ g_poll (GPollFD *fds, guint nfds, gint timeout)
 
   return ready;
 }
+#endif /* !NATIVE_WIN32 */
+
 static GPollFunc poll_func = g_poll;
 #endif /* !HAVE_POLL */
 
@@ -280,14 +443,19 @@ g_source_add (gint           priority,
 
   return_val = source->hook.hook_id;
 
+#ifdef G_THREADS_ENABLED
   /* Now wake up the main loop if it is waiting in the poll() */
 
   if (poll_waiting)
     {
       poll_waiting = FALSE;
+#ifndef NATIVE_WIN32
       write (wake_up_pipe[1], "A", 1);
+#else
+      ReleaseSemaphore (wake_up_semaphore, 1, NULL);
+#endif
     }
-
+#endif
   G_UNLOCK (main_loop);
 
   return return_val;
@@ -348,6 +516,7 @@ g_source_remove_by_source_data (gpointer source_data)
 void
 g_get_current_time (GTimeVal *result)
 {
+#ifndef _MSC_VER
   struct timeval r;
   g_return_if_fail (result != NULL);
 
@@ -356,6 +525,29 @@ g_get_current_time (GTimeVal *result)
   gettimeofday (&r, NULL);
   result->tv_sec = r.tv_sec;
   result->tv_usec = r.tv_usec;
+#else
+  /* Avoid calling time() except for the first time.
+   * GetTickCount() should be pretty fast and low-level?
+   * I could also use ftime() but it seems unnecessarily overheady.
+   */
+  static DWORD start_tick = 0;
+  static time_t start_time;
+  DWORD tick;
+  time_t t;
+
+  g_return_if_fail (result != NULL);
+  if (start_tick == 0)
+    {
+      start_tick = GetTickCount ();
+      time (&start_time);
+    }
+
+  tick = GetTickCount ();
+
+  result->tv_sec = (tick - start_tick) / 1000 + start_time;
+  result->tv_usec = ((tick - start_tick) % 1000) * 1000;
+#endif
 }
 
 /* Running the main loop */
@@ -652,7 +844,8 @@ g_main_poll (gint     timeout,
 
   gint i;
   gint npoll;
-
+#ifdef G_THREADS_ENABLED
+#ifndef NATIVE_WIN32
   if (wake_up_pipe[0] < 0)
     {
       if (pipe (wake_up_pipe) < 0)
@@ -663,7 +856,17 @@ g_main_poll (gint     timeout,
       wake_up_rec.events = G_IO_IN;
       g_main_add_poll_unlocked (0, &wake_up_rec);
     }
-  
+#else
+  if (wake_up_semaphore == NULL)
+    {
+      if ((wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL)) == NULL)
+       g_error ("Cannot create wake-up semaphore: %d", GetLastError ());
+      wake_up_rec.fd = (gint) wake_up_semaphore;
+      wake_up_rec.events = G_IO_IN;
+      g_main_add_poll_unlocked (0, &wake_up_rec);
+    }
+#endif
+#endif
   fd_array = g_new (GPollFD, n_poll_records);
  
   pollrec = poll_records;
@@ -677,21 +880,25 @@ g_main_poll (gint     timeout,
       pollrec = pollrec->next;
       i++;
     }
-
+#ifdef G_THREADS_ENABLED
   poll_waiting = TRUE;
-  
+#endif
   G_UNLOCK (main_loop);
   npoll = i;
   (*poll_func) (fd_array, npoll, timeout);
   G_LOCK (main_loop);
 
+#ifdef G_THREADS_ENABLED
   if (!poll_waiting)
     {
+#ifndef NATIVE_WIN32
       gchar c;
       read (wake_up_pipe[0], &c, 1);
+#endif
     }
   else
     poll_waiting = FALSE;
+#endif
 
   pollrec = poll_records;
   i = 0;
index eb8aed7a8c4029eb7463988726b99227971228dc..1ef33445dde3d26af39186f2ff757c445082ec6a 100644 (file)
@@ -35,6 +35,9 @@
 #endif
 
 #ifdef NATIVE_WIN32
+#define STRICT
+#include <windows.h>
+
 /* Just use stdio. If we're out of memory, we're hosed anyway. */
 #undef write
 
@@ -49,6 +52,22 @@ write (FILE       *fd,
 }
 #endif /* NATIVE_WIN32 */
 
+static void
+ensure_stdout_valid (void)
+{
+#ifdef NATIVE_WIN32
+  HANDLE handle;
+
+  handle = GetStdHandle (STD_OUTPUT_HANDLE);
+  
+  if (handle == INVALID_HANDLE_VALUE)
+    {
+      AllocConsole ();
+      freopen ("CONOUT$", "w", stdout);
+    }
+#endif
+}
+       
 
 /* --- structures --- */
 typedef struct _GLogDomain     GLogDomain;
@@ -410,6 +429,7 @@ g_log_default_handler (const gchar    *log_domain,
    * DOS prompt.
    */
   fd = stdout;
+  ensure_stdout_valid ();
 #else
   fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
 #endif
@@ -623,6 +643,7 @@ g_print (const gchar *format,
     local_glib_print_func (string);
   else
     {
+      ensure_stdout_valid ();
       fputs (string, stdout);
       fflush (stdout);
     }
index e154c56dc0b9f1252c999b5eb3cfe52895e0b75a..268d2831c47f453955f6697c246902644ac3657c 100644 (file)
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <locale.h>
 #include <ctype.h>             /* For tolower() */
+#include <signal.h>
 #include "glib.h"
 /* do not include <unistd.h> in this place since it
  * inteferes with g_strsignal() on some OSes
index e235d295fcacca2d39eedbe6a42f22981a903095..5bcaa492afb7d59a847a29d3e17a0156822532d1 100644 (file)
@@ -413,7 +413,30 @@ g_get_any_init (void)
 #endif /* NATIVE_WIN32 */
        }
       
+#ifdef NATIVE_WIN32
+      /* The official way to specify a home directory on NT is
+       * the HOMEDRIVE and HOMEPATH environment variables.
+       *
+       * This is inside #ifdef NATIVE_WIN32 because with the cygwin dll,
+       * HOME should be a POSIX style pathname.
+       */
+      
+      if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
+       {
+         gchar *homedrive, *homepath;
+
+         homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
+         homepath = g_strdup (g_getenv ("HOMEPATH"));
+
+         g_home_dir = g_strconcat (homedrive, homepath, NULL);
+         g_free (homedrive);
+         g_free (homepath);
+       }
+      if (!g_home_dir)
+       g_home_dir = g_strdup (g_getenv ("HOME"));
+#else
       g_home_dir = g_strdup (g_getenv ("HOME"));
+#endif
       
 #ifdef HAVE_PWD_H
       /* FIXME: we must actually use the getpwuid_r function here, as
index 9dde2c23c3d11edb032b27c7511f7fefea25dca8..5ecf82fb4fa2843e330b51d5ccd94e935449fb1e 100644 (file)
@@ -31,22 +31,23 @@ extern "C" {
 #pragma warning(disable:4101)
 #pragma warning(error:4150)
 
-#pragma warning(disable:4244)  /* No possible loss of data warnings, please */
+#pragma warning(disable:4244)  /* No possible loss of data warnings */
+#pragma warning(disable:4305)   /* No truncation from int to char warnings */
 #endif /* _MSC_VER */
 
 #include <limits.h>
 #include <float.h>
 
-#define G_MINFLOAT FLT_MIN
-#define G_MAXFLOAT FLT_MAX
-#define G_MINDOUBLE DBL_MIN
-#define G_MAXDOUBLE DBL_MAX
-#define G_MINSHORT SHRT_MIN
-#define G_MAXSHORT SHRT_MAX
-#define G_MININT INT_MIN
-#define G_MAXINT INT_MAX
-#define G_MINLONG LONG_MIN
-#define G_MAXLONG LONG_MAX
+#define G_MINFLOAT     FLT_MIN
+#define G_MAXFLOAT     FLT_MAX
+#define G_MINDOUBLE    DBL_MIN
+#define G_MAXDOUBLE    DBL_MAX
+#define G_MINSHORT     SHRT_MIN
+#define G_MAXSHORT     SHRT_MAX
+#define G_MININT       INT_MIN
+#define G_MAXINT       INT_MAX
+#define G_MINLONG      LONG_MIN
+#define G_MAXLONG      LONG_MAX
 
 typedef signed char gint8;
 typedef unsigned char guint8;
@@ -54,12 +55,13 @@ typedef signed short gint16;
 typedef unsigned short guint16;
 typedef signed int gint32;
 typedef unsigned int guint32;
+
 #define G_HAVE_GINT64 1
 
 typedef __int64 gint64;
 typedef unsigned __int64 guint64;
 
-#define G_GINT64_CONSTANT(val) (val)
+#define G_GINT64_CONSTANT(val) (val##i64)
 
 #define GPOINTER_TO_INT(p)     ((gint)(p))
 #define GPOINTER_TO_UINT(p)    ((guint)(p))
@@ -71,13 +73,35 @@ typedef unsigned __int64 guint64;
 
 #define g_memmove(d,s,n) G_STMT_START { memmove ((d), (s), (n)); } G_STMT_END
 
+#define G_HAVE_ALLOCA 1
+#define alloca _alloca
+
 #define GLIB_MAJOR_VERSION 1
 #define GLIB_MINOR_VERSION 1
-#define GLIB_MICRO_VERSION 4
-
-#define G_COMPILED_WITH_DEBUGGING "minimum"
+#define GLIB_MICRO_VERSION 12
 
+#ifdef __cplusplus
+#define        G_HAVE_INLINE   1
+#else  /* !__cplusplus */
 #define G_HAVE___INLINE 1
+#endif
+
+#define G_THREADS_ENABLED
+typedef struct _GStaticMutex GStaticMutex;
+struct _GStaticMutex
+{
+  struct _GMutex *runtime_mutex;
+  union {
+    char   pad[24];
+    double dummy_double;
+    void  *dummy_pointer;
+    long   dummy_long;
+  } aligned_pad_u;
+};
+#define        G_STATIC_MUTEX_INIT     { NULL, { { 0, 0, 0, 0, 0 } } }
+#define        g_static_mutex_get_mutex(mutex) \
+  (g_thread_use_default_impl ? ((GMutex*) &(mutex).aligned_pad_u) : \
+   g_static_mutex_get_mutex_impl (&(mutex).runtime_mutex))
 
 #define G_BYTE_ORDER G_LITTLE_ENDIAN
 
@@ -106,13 +130,20 @@ typedef unsigned __int64 guint64;
 #define GINT_TO_BE(val)                ((gint) GINT32_TO_BE (val))
 #define GUINT_TO_BE(val)       ((guint) GUINT32_TO_BE (val))
 
+#define GLIB_SYSDEF_POLLIN     = 1
+#define GLIB_SYSDEF_POLLOUT    = 4
+#define GLIB_SYSDEF_POLLPRI    = 2
+#define GLIB_SYSDEF_POLLERR    = 8
+#define GLIB_SYSDEF_POLLHUP    = 16
+#define GLIB_SYSDEF_POLLNVAL   = 32
+
 #define G_HAVE_WCHAR_H 1
 #define G_HAVE_WCTYPE_H 1
 
-/* Define if this is Win32, possibly using the GNU-Win32 emulation layer. */
+/* Define if this is Win32, possibly using the Cygwin emulation layer. */
 #define WIN32 1
 
-/* Define if this is Win32 without GNU-Win32.  */
+/* Define if this is Win32 without Cygwin.  */
 #define NATIVE_WIN32 1
 
 #ifdef __cplusplus
diff --git a/gmain.c b/gmain.c
index ff4c2051384c936694176a2164db1efcc4a5de65..7e3571b4cdce428c12711a8ae7294ea8bf79c9ab 100644 (file)
--- a/gmain.c
+++ b/gmain.c
  * MT safe
  */
 
+#include "config.h"
+
 #include "glib.h"
 #include <sys/types.h>
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
+#endif
 #ifdef GLIB_HAVE_SYS_POLL_H
 #  include <sys/poll.h>
 #  undef events         /* AIX 4.1.5 & 4.3.2 define this for SVR3,4 compatibility */
 #  undef revents /* AIX 4.1.5 & 4.3.2 define this for SVR3,4 compatibility */
 #endif /* GLIB_HAVE_SYS_POLL_H */
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <errno.h>
-#include "config.h"
+
+#ifdef NATIVE_WIN32
+#define STRICT
+#include <windows.h>
+#endif
+
+#ifdef _MSC_VER
+#include <fcntl.h>
+#include <io.h>
+#endif
 
 /* Types */
 
@@ -138,15 +154,160 @@ static GPollRec *poll_free_list = NULL;
 static GMemChunk *poll_chunk;
 static guint n_poll_records = 0;
 
+#ifdef G_THREADS_ENABLED
+#ifndef NATIVE_WIN32
 /* this pipe is used to wake up the main loop when a source is added.
  */
 static gint wake_up_pipe[2] = { -1, -1 };
+#else
+static HANDLE wake_up_semaphore = NULL;
+#endif
 static GPollFD wake_up_rec;
 static gboolean poll_waiting = FALSE;
+#endif
 
 #ifdef HAVE_POLL
 static GPollFunc poll_func = (GPollFunc) poll;
 #else  /* !HAVE_POLL */
+#ifdef NATIVE_WIN32
+
+static gint
+g_poll (GPollFD *fds, guint nfds, gint timeout)
+{
+  HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+  GPollFD *f;
+  DWORD ready;
+  MSG msg;
+  UINT timer;
+  LONG prevcnt;
+  gint poll_msgs = -1;
+  gint nhandles = 0;
+
+  for (f = fds; f < &fds[nfds]; ++f)
+    if (f->fd >= 0)
+      {
+       if (f->events & G_IO_IN)
+         if (f->fd == G_WIN32_MSG_HANDLE)
+           poll_msgs = f - fds;
+         else
+           {
+             /* g_print ("g_poll: waiting for handle %#x\n", f->fd); */
+             handles[nhandles++] = (HANDLE) f->fd;
+           }
+      }
+
+  if (timeout == -1)
+    timeout = INFINITE;
+
+  if (poll_msgs >= 0)
+    {
+      /* Waiting for messages, and maybe events */
+      if (nhandles == 0)
+       {
+         if (timeout == INFINITE)
+           {
+             /* Waiting just for messages, infinite timeout
+              * -> Use PeekMessage, then WaitMessage
+              */
+             /* g_print ("WaitMessage, PeekMessage\n"); */
+             if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+               ready = WAIT_OBJECT_0;
+             else if (!WaitMessage ())
+               g_warning ("g_poll: WaitMessage failed");
+             ready = WAIT_OBJECT_0;
+           }
+         else if (timeout == 0)
+           {
+             /* Waiting just for messages, zero timeout
+              * -> Use PeekMessage
+              */
+             /* g_print ("PeekMessage\n"); */
+             if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+               ready = WAIT_OBJECT_0;
+             else
+               ready = WAIT_TIMEOUT;
+           }
+         else
+           {
+             /* Waiting just for messages, some timeout
+              * -> First try PeekMessage, then set a timer, wait for message,
+              * kill timer, use PeekMessage
+              */
+             /* g_print ("PeekMessage\n"); */
+             if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+               ready = WAIT_OBJECT_0;
+             else if ((timer = SetTimer (NULL, 0, timeout, NULL)) == 0)
+               g_warning ("g_poll: SetTimer failed");
+             else
+               {
+                 /* g_print ("WaitMessage\n"); */
+                 WaitMessage ();
+                 KillTimer (NULL, timer);
+                 if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
+                   ready = WAIT_OBJECT_0;
+                 else
+                   ready = WAIT_TIMEOUT;
+               }
+           }
+       }
+      else
+       {
+         /* Wait for either message or event
+          * -> Use MsgWaitForMultipleObjects
+          */
+         /* g_print ("MsgWaitForMultipleObjects(%d, %d)\n", nhandles, timeout); */
+         ready = MsgWaitForMultipleObjects (nhandles, handles, FALSE,
+                                            timeout, QS_ALLINPUT);
+         /* g_print("=%d\n", ready); */
+         if (ready == WAIT_FAILED)
+           g_warning ("g_poll: MsgWaitForMultipleObjects failed");
+       }
+    }
+  else if (nhandles == 0)
+    {
+      /* Wait for nothing (huh?) */
+      return 0;
+    }
+  else
+    {
+      /* Wait for just events
+       * -> Use WaitForMultipleObjects
+       */
+      /* g_print ("WaitForMultipleObjects(%d, %d)\n", nhandles, timeout); */
+      ready = WaitForMultipleObjects (nhandles, handles, FALSE, timeout);
+      /* g_print("=%d\n", ready); */
+      if (ready == WAIT_FAILED)
+       g_warning ("g_poll: WaitForMultipleObjects failed");
+    }
+
+  for (f = fds; f < &fds[nfds]; ++f)
+    f->revents = 0;
+
+  if (ready == WAIT_FAILED)
+    return -1;
+  else if (poll_msgs >= 0 && ready == WAIT_OBJECT_0 + nhandles)
+    {
+      fds[poll_msgs].revents |= G_IO_IN;
+    }
+  else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
+    for (f = fds; f < &fds[nfds]; ++f)
+      {
+       if ((f->events & G_IO_IN)
+           && f->fd == (gint) handles[ready - WAIT_OBJECT_0])
+         {
+           f->revents |= G_IO_IN;
+           /* g_print ("event %#x\n", f->fd); */
+           ResetEvent ((HANDLE) f->fd);
+         }
+      }
+    
+  if (ready == WAIT_TIMEOUT)
+    return 0;
+  else
+    return 1;
+}
+
+#else  /* !NATIVE_WIN32 */
 
 /* The following implementation of poll() comes from the GNU C Library.
  * Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
@@ -219,6 +380,8 @@ g_poll (GPollFD *fds, guint nfds, gint timeout)
 
   return ready;
 }
+#endif /* !NATIVE_WIN32 */
+
 static GPollFunc poll_func = g_poll;
 #endif /* !HAVE_POLL */
 
@@ -280,14 +443,19 @@ g_source_add (gint           priority,
 
   return_val = source->hook.hook_id;
 
+#ifdef G_THREADS_ENABLED
   /* Now wake up the main loop if it is waiting in the poll() */
 
   if (poll_waiting)
     {
       poll_waiting = FALSE;
+#ifndef NATIVE_WIN32
       write (wake_up_pipe[1], "A", 1);
+#else
+      ReleaseSemaphore (wake_up_semaphore, 1, NULL);
+#endif
     }
-
+#endif
   G_UNLOCK (main_loop);
 
   return return_val;
@@ -348,6 +516,7 @@ g_source_remove_by_source_data (gpointer source_data)
 void
 g_get_current_time (GTimeVal *result)
 {
+#ifndef _MSC_VER
   struct timeval r;
   g_return_if_fail (result != NULL);
 
@@ -356,6 +525,29 @@ g_get_current_time (GTimeVal *result)
   gettimeofday (&r, NULL);
   result->tv_sec = r.tv_sec;
   result->tv_usec = r.tv_usec;
+#else
+  /* Avoid calling time() except for the first time.
+   * GetTickCount() should be pretty fast and low-level?
+   * I could also use ftime() but it seems unnecessarily overheady.
+   */
+  static DWORD start_tick = 0;
+  static time_t start_time;
+  DWORD tick;
+  time_t t;
+
+  g_return_if_fail (result != NULL);
+  if (start_tick == 0)
+    {
+      start_tick = GetTickCount ();
+      time (&start_time);
+    }
+
+  tick = GetTickCount ();
+
+  result->tv_sec = (tick - start_tick) / 1000 + start_time;
+  result->tv_usec = ((tick - start_tick) % 1000) * 1000;
+#endif
 }
 
 /* Running the main loop */
@@ -652,7 +844,8 @@ g_main_poll (gint     timeout,
 
   gint i;
   gint npoll;
-
+#ifdef G_THREADS_ENABLED
+#ifndef NATIVE_WIN32
   if (wake_up_pipe[0] < 0)
     {
       if (pipe (wake_up_pipe) < 0)
@@ -663,7 +856,17 @@ g_main_poll (gint     timeout,
       wake_up_rec.events = G_IO_IN;
       g_main_add_poll_unlocked (0, &wake_up_rec);
     }
-  
+#else
+  if (wake_up_semaphore == NULL)
+    {
+      if ((wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL)) == NULL)
+       g_error ("Cannot create wake-up semaphore: %d", GetLastError ());
+      wake_up_rec.fd = (gint) wake_up_semaphore;
+      wake_up_rec.events = G_IO_IN;
+      g_main_add_poll_unlocked (0, &wake_up_rec);
+    }
+#endif
+#endif
   fd_array = g_new (GPollFD, n_poll_records);
  
   pollrec = poll_records;
@@ -677,21 +880,25 @@ g_main_poll (gint     timeout,
       pollrec = pollrec->next;
       i++;
     }
-
+#ifdef G_THREADS_ENABLED
   poll_waiting = TRUE;
-  
+#endif
   G_UNLOCK (main_loop);
   npoll = i;
   (*poll_func) (fd_array, npoll, timeout);
   G_LOCK (main_loop);
 
+#ifdef G_THREADS_ENABLED
   if (!poll_waiting)
     {
+#ifndef NATIVE_WIN32
       gchar c;
       read (wake_up_pipe[0], &c, 1);
+#endif
     }
   else
     poll_waiting = FALSE;
+#endif
 
   pollrec = poll_records;
   i = 0;
index eb8aed7a8c4029eb7463988726b99227971228dc..1ef33445dde3d26af39186f2ff757c445082ec6a 100644 (file)
@@ -35,6 +35,9 @@
 #endif
 
 #ifdef NATIVE_WIN32
+#define STRICT
+#include <windows.h>
+
 /* Just use stdio. If we're out of memory, we're hosed anyway. */
 #undef write
 
@@ -49,6 +52,22 @@ write (FILE       *fd,
 }
 #endif /* NATIVE_WIN32 */
 
+static void
+ensure_stdout_valid (void)
+{
+#ifdef NATIVE_WIN32
+  HANDLE handle;
+
+  handle = GetStdHandle (STD_OUTPUT_HANDLE);
+  
+  if (handle == INVALID_HANDLE_VALUE)
+    {
+      AllocConsole ();
+      freopen ("CONOUT$", "w", stdout);
+    }
+#endif
+}
+       
 
 /* --- structures --- */
 typedef struct _GLogDomain     GLogDomain;
@@ -410,6 +429,7 @@ g_log_default_handler (const gchar    *log_domain,
    * DOS prompt.
    */
   fd = stdout;
+  ensure_stdout_valid ();
 #else
   fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
 #endif
@@ -623,6 +643,7 @@ g_print (const gchar *format,
     local_glib_print_func (string);
   else
     {
+      ensure_stdout_valid ();
       fputs (string, stdout);
       fflush (stdout);
     }
index 86dd222ae20fe62988d610304d568311c4aeaac5..e90408a33816b4ee1e19c65820f691c292db7c69 100644 (file)
@@ -1,3 +1,11 @@
+1999-01-16  Tor Lillqvist  <tml@iki.fi>
+
+       * gmodule-dl.c gmodule-dld.c: In
+       _g_module_build_path, don't add the "lib" prefix and
+       ".so" or ".sl" suffix if already there.
+
+       * gmodule-win32.c: Likewise for the ".dll" suffix.
+
 1998-12-10  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * gmodule.c: Made it MT safe, the g_module_error() is now thread
index 4a5686616afade19c80e70f30053fd3635f43fc2..e8c986fc75c75933f4b38d2c6a5cf7f23b24137d 100644 (file)
@@ -125,8 +125,13 @@ static gchar*
 _g_module_build_path (const gchar *directory,
                      const gchar *module_name)
 {
-  if (directory)
-    return g_strconcat (directory, "/lib", module_name, ".so", NULL);
+  if (directory && *directory)
+    if (strncmp (module_name, "lib", 3) == 0)
+      return g_strconcat (directory, "/", module_name, NULL);
+    else
+      return g_strconcat (directory, "/lib", module_name, ".so", NULL);
+  else if (strncmp (module_name, "lib", 3) == 0)
+    return g_strdup (module_name);
   else
     return g_strconcat ("lib", module_name, ".so", NULL);
 }
index 53b269b486d149e4683c0266a878202073f77e2d..17d6e010e9aff50414944190bae8aaf6d25e612f 100644 (file)
@@ -122,8 +122,13 @@ static gchar*
 _g_module_build_path (const gchar *directory,
                      const gchar *module_name)
 {
-  if (directory)
-    return g_strconcat (directory, "/", module_name, ".sl", NULL);
+  if (directory && *directory)
+    if (strncmp (module_name, "lib", 3) == 0)
+      return g_strconcat (directory, "/", module_name, NULL);
+    else
+      return g_strconcat (directory, "/lib", module_name, ".sl", NULL);
+  else if (strncmp (module_name, "lib", 3) == 0)
+    return g_strdup (module_name);
   else
-    return g_strconcat (module_name, ".sl", NULL);
+    return g_strconcat ("lib", module_name, ".sl", NULL);
 }
index 98643ad23bec4ef028049319d0dd9e3843783c4c..c3fc9a90d80d5847f1a72f55555f14cff6bf0917 100644 (file)
@@ -91,8 +91,16 @@ static gchar*
 _g_module_build_path (const gchar *directory,
                      const gchar *module_name)
 {
-  if (directory)
-    return g_strconcat (directory, "\\", module_name, ".dll", NULL);
+  gint k;
+
+  k = strlen (module_name);
+  if (directory && *directory)
+    if (k > 4 && g_strcasecmp (module_name + k - 4, ".dll") == 0)
+      return g_strconcat (directory, "\\", module_name, NULL);
+    else
+      return g_strconcat (directory, "\\", module_name, ".dll", NULL);
+  else if (k > 4 && g_strcasecmp (module_name + k - 4, ".dll") == 0)
+    return g_strdup (module_name);
   else
     return g_strconcat (module_name, ".dll", NULL);
 }
index e154c56dc0b9f1252c999b5eb3cfe52895e0b75a..268d2831c47f453955f6697c246902644ac3657c 100644 (file)
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <locale.h>
 #include <ctype.h>             /* For tolower() */
+#include <signal.h>
 #include "glib.h"
 /* do not include <unistd.h> in this place since it
  * inteferes with g_strsignal() on some OSes
index 939ae56c5fdeb1557b4da5cea43b026874d911c8..13b767410068744ce77791ca8b39d70939c6c5c0 100644 (file)
@@ -1,3 +1,7 @@
+1999-01-16 1999  Tor Lillqvist  <tml@iki.fi>
+
+       * gthread-posix.c: Conditionalize <sys/time.h> inclusion.
+
 1999-01-07  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * testgthread.c: conditionally compile according to the
index b2c293cbfae6c7a3e5d77baba9c06e8ca04a581f..e35acbdd56c2fc05938884abb4340d06ab75f21e 100644 (file)
@@ -27,7 +27,9 @@
 #include <pthread.h>
 #include <errno.h>
 #include <stdlib.h>
+#ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
+#endif
 
 #define posix_print_error( name, num )                          \
   g_error( "file %s: line %d (%s): error %s during %s",         \
index e235d295fcacca2d39eedbe6a42f22981a903095..5bcaa492afb7d59a847a29d3e17a0156822532d1 100644 (file)
--- a/gutils.c
+++ b/gutils.c
@@ -413,7 +413,30 @@ g_get_any_init (void)
 #endif /* NATIVE_WIN32 */
        }
       
+#ifdef NATIVE_WIN32
+      /* The official way to specify a home directory on NT is
+       * the HOMEDRIVE and HOMEPATH environment variables.
+       *
+       * This is inside #ifdef NATIVE_WIN32 because with the cygwin dll,
+       * HOME should be a POSIX style pathname.
+       */
+      
+      if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
+       {
+         gchar *homedrive, *homepath;
+
+         homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
+         homepath = g_strdup (g_getenv ("HOMEPATH"));
+
+         g_home_dir = g_strconcat (homedrive, homepath, NULL);
+         g_free (homedrive);
+         g_free (homepath);
+       }
+      if (!g_home_dir)
+       g_home_dir = g_strdup (g_getenv ("HOME"));
+#else
       g_home_dir = g_strdup (g_getenv ("HOME"));
+#endif
       
 #ifdef HAVE_PWD_H
       /* FIXME: we must actually use the getpwuid_r function here, as
index 6a7f9b6e2857243e25c77fbeec77d3cec9ca7691..3b2b77fb5e1fadf4c12304084aa42dcf5944eb29 100644 (file)
@@ -1,24 +1,29 @@
-## Makefile for building the GLib and gmodule dll with Microsoft C
+## Makefile for building the GLib, gmodule and gthread dlls with Microsoft C
 ## Use: nmake -f makefile.msc install
 
 # Change this to wherever you want to install the DLLs. This directory
 # should be in your PATH.
 BIN = C:\bin
 
+# This is the Cygnus pthread-win32, 
+# see http://sourceware.cygnus.com/pthreads-win32/
+PTHREAD_LIB = ..\lib\pthread.lib
+PTHREAD_INC = ..\include
+
 ################################################################
 
 # Nothing much configurable below
 
 # cl -? described the options
-CC = cl -G5 -GF -Ox -W3 -D_DLL -nologo
+CC = cl -G5 -GF -Ox -W3 -MD -nologo
 
-LDFLAGS = /link /nodefaultlib:libc msvcrt.lib # /debug:full /debugtype:cv 
+# No general LDFLAGS needes
+LDFLAGS = /link
 INSTALL = copy
-TOUCH = copy makefile.msc+nul
 
 GLIB_VER = 1.1
 
-CFLAGS = -I. 
+CFLAGS = -I. -DHAVE_CONFIG_H
 
 all : \
        glibconfig.h    \
@@ -26,24 +31,34 @@ all : \
        glib-$(GLIB_VER).dll    \
        gmodule\gmoduleconf.h \
        gmodule-$(GLIB_VER).dll \
+       gthread-$(GLIB_VER).dll \
        testglib.exe    \
-       testgmodule.exe
+       testgmodule.exe \
+       testgdate.exe   \
+       testgdateparser.exe \
+       testgthread.exe
 
 install : all
        $(INSTALL) glib-$(GLIB_VER).dll $(BIN)
        $(INSTALL) gmodule-$(GLIB_VER).dll $(BIN)
+       $(INSTALL) gthread-$(GLIB_VER).dll $(BIN)
 
 glib_OBJECTS = \
        garray.obj      \
        gcache.obj      \
        gcompletion.obj \
        gdataset.obj    \
+       gdate.obj       \
        gerror.obj      \
        ghook.obj       \
        ghash.obj       \
+       giochannel.obj  \
+       giowin32.obj    \
        glist.obj       \
+       gmain.obj       \
        gmem.obj        \
        gmessages.obj   \
+       gmutex.obj      \
        gnode.obj       \
        gprimes.obj     \
        gslist.obj      \
@@ -55,8 +70,8 @@ glib_OBJECTS = \
        gscanner.obj    \
        gutils.obj
 
-glib-$(GLIB_VER).dll : $(glib_OBJECTS)
-       $(CC) $(CFLAGS) -MD -LD -Feglib-$(GLIB_VER).dll $(glib_OBJECTS) user32.lib advapi32.lib $(LDFLAGS) /def:glib.def
+glib-$(GLIB_VER).dll : $(glib_OBJECTS) glib.def
+       $(CC) $(CFLAGS) -LD -Feglib-$(GLIB_VER).dll $(glib_OBJECTS) user32.lib advapi32.lib wsock32.lib $(LDFLAGS) /def:glib.def
 
 glibconfig.h: glibconfig.h.win32
        copy glibconfig.h.win32 glibconfig.h
@@ -65,44 +80,71 @@ config.h: config.h.win32
        copy config.h.win32 config.h
 
 .c.obj :
-       $(CC) $(CFLAGS) -GD -c -DHAVE_CONFIG_H -DGLIB_COMPILATION -DG_LOG_DOMAIN=g_log_domain_glib $<
+       $(CC) $(CFLAGS) -GD -c -DGLIB_COMPILATION -DG_LOG_DOMAIN=g_log_domain_glib $<
 
 gmodule_OBJECTS = \
        gmodule.obj
 
 gmodule-$(GLIB_VER).dll : $(gmodule_OBJECTS)
-       $(CC) $(CFLAGS) -MD -LD -Fegmodule-$(GLIB_VER).dll $(gmodule_OBJECTS) glib-$(GLIB_VER).lib $(LDFLAGS) /def:gmodule\gmodule.def
+       $(CC) $(CFLAGS) -LD -Fegmodule-$(GLIB_VER).dll $(gmodule_OBJECTS) glib-$(GLIB_VER).lib $(LDFLAGS) /def:gmodule\gmodule.def
 
 gmodule.obj : gmodule\gmodule.c gmodule\gmodule-win32.c
-       $(CC) $(CFLAGS) -Igmodule -c -DG_LIB_DOMAIN=g_log_domain_gmodule gmodule\gmodule.c
+       $(CC) $(CFLAGS) -GD -Igmodule -c -DG_LOG_DOMAIN=g_log_domain_gmodule gmodule\gmodule.c
 
 gmodule\gmoduleconf.h: gmodule\gmoduleconf.h.win32
        copy gmodule\gmoduleconf.h.win32 gmodule\gmoduleconf.h
 
+gthread_OBJECTS = \
+       gthread.obj
+
+gthread-$(GLIB_VER).dll : $(gthread_OBJECTS)
+       $(CC) $(CFLAGS) -LD -Fegthread-$(GLIB_VER).dll $(gthread_OBJECTS) glib-$(GLIB_VER).lib $(PTHREAD_LIB) glib-$(GLIB_VER).lib $(LDFLAGS) /def:gthread\gthread.def
+
+gthread.obj : gthread\gthread.c gthread\gthread-posix.c
+       $(CC) $(CFLAGS) -GD -I$(PTHREAD_INC) -DG_LOG_DOMAIN=\"GThread\" -c gthread\gthread.c
+
 testglib.exe : glib-$(GLIB_VER).dll testglib.obj
-       $(CC) $(CFLAGS) -MD -Fetestglib.exe testglib.obj glib-$(GLIB_VER).lib $(LDFLAGS) /map
+       $(CC) $(CFLAGS) -Fetestglib.exe testglib.obj glib-$(GLIB_VER).lib $(LDFLAGS) /subsystem:console
 
 testglib.obj : testglib.c
        $(CC) -c $(CFLAGS) testglib.c
 
+testgdate.exe : glib-$(GLIB_VER).dll testgdate.obj
+       $(CC) $(CFLAGS) -Fetestgdate.exe testgdate.obj glib-$(GLIB_VER).lib $(LDFLAGS) /subsystem:console
+
+testgdate.obj : testgdate.c
+       $(CC) -c $(CFLAGS) testgdate.c
+
+testgdateparser.exe : glib-$(GLIB_VER).dll testgdateparser.obj
+       $(CC) $(CFLAGS) -Fetestgdateparser.exe testgdateparser.obj glib-$(GLIB_VER).lib $(LDFLAGS) /subsystem:console
+
+testgdateparser.obj : testgdateparser.c
+       $(CC) -c $(CFLAGS) testgdateparser.c
+
 testgmodule.exe : glib-$(GLIB_VER).dll gmodule-$(GLIB_VER).dll testgmodule.obj libgplugin_a.dll libgplugin_b.dll
-       $(CC) $(CFLAGS) -MD testgmodule.obj glib-$(GLIB_VER).lib gmodule-$(GLIB_VER).lib $(LDFLAGS)
+       $(CC) $(CFLAGS) testgmodule.obj glib-$(GLIB_VER).lib gmodule-$(GLIB_VER).lib $(LDFLAGS) /subsystem:console 
 
 testgmodule.obj : gmodule\testgmodule.c
        $(CC) $(CFLAGS) -Igmodule -c gmodule\testgmodule.c
 
 libgplugin_a.dll : libgplugin_a.obj
-       $(CC) $(CFLAGS) -MD -LD libgplugin_a.obj glib-$(GLIB_VER).lib gmodule-$(GLIB_VER).lib $(LDFLAGS)
+       $(CC) $(CFLAGS) -LD libgplugin_a.obj glib-$(GLIB_VER).lib gmodule-$(GLIB_VER).lib $(LDFLAGS)
 
 libgplugin_a.obj : gmodule\libgplugin_a.c
        $(CC) $(CFLAGS) -Igmodule -c gmodule\libgplugin_a.c
 
 libgplugin_b.dll : libgplugin_b.obj
-       $(CC) $(CFLAGS) -MD -LD libgplugin_b.obj glib-$(GLIB_VER).lib gmodule-$(GLIB_VER).lib  $(LDFLAGS)
+       $(CC) $(CFLAGS) -LD libgplugin_b.obj glib-$(GLIB_VER).lib gmodule-$(GLIB_VER).lib  $(LDFLAGS)
 
 libgplugin_b.obj : gmodule\libgplugin_b.c
        $(CC) $(CFLAGS) -Igmodule -c gmodule\libgplugin_b.c
 
+testgthread.exe : glib-$(GLIB_VER).dll gthread-$(GLIB_VER).dll testgthread.obj
+       $(CC) $(CFLAGS) testgthread.obj glib-$(GLIB_VER).lib gthread-$(GLIB_VER).lib $(PTHREAD_LIB) $(LDFLAGS) /subsystem:console 
+
+testgthread.obj : gthread\testgthread.c
+       $(CC) $(CFLAGS) -I$(PTHREAD_INC) -c gthread\testgthread.c
+
 clean:
        del config.h
        del glibconfig.h